1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Rerun tooling to combat agressive any

This commit is contained in:
Bagel03 2022-11-18 10:20:54 -05:00
parent e768561dc6
commit 4dd57c1605
289 changed files with 6536 additions and 6524 deletions

View File

@ -43,10 +43,10 @@ import type { AchievementProviderInterface } from "./platform/achievement_provid
import type { SoundInterface } from "./platform/sound"; import type { SoundInterface } from "./platform/sound";
import type { StorageInterface } from "./platform/storage"; import type { StorageInterface } from "./platform/storage";
const logger: any = createLogger("application"); const logger = createLogger("application");
// Set the name of the hidden property and the change event for visibility // Set the name of the hidden property and the change event for visibility
let pageHiddenPropName: any, pageVisibilityEventName: any; let pageHiddenPropName: string, pageVisibilityEventName: string;
if (typeof document.hidden !== "undefined") { if (typeof document.hidden !== "undefined") {
// Opera 12.10 and Firefox 18 and later support // Opera 12.10 and Firefox 18 and later support
pageHiddenPropName = "hidden"; pageHiddenPropName = "hidden";
@ -62,9 +62,7 @@ if (typeof document.hidden !== "undefined") {
} }
export class Application { export class Application {
public unloaded = true; public unloaded = false;
// Global stuff
public settings = new ApplicationSettings(this); public settings = new ApplicationSettings(this);
public ticker = new AnimationFrame(); public ticker = new AnimationFrame();
public stateMgr = new StateManager(this); public stateMgr = new StateManager(this);
@ -72,44 +70,28 @@ export class Application {
public inputMgr = new InputDistributor(this); public inputMgr = new InputDistributor(this);
public backgroundResourceLoader = new BackgroundResourcesLoader(this); public backgroundResourceLoader = new BackgroundResourcesLoader(this);
public clientApi = new ClientAPI(this); public clientApi = new ClientAPI(this);
// Restrictions (Like demo etc)
public restrictionMgr = new RestrictionManager(this); public restrictionMgr = new RestrictionManager(this);
// Platform dependent stuff
public storage: StorageInterface = null; public storage: StorageInterface = null;
public sound: SoundInterface = new SoundImplBrowser(this); public sound: SoundInterface = null;
public platformWrapper: PlatformWrapperInterface = G_IS_STANDALONE ? new PlatformWrapperImplElectron(this) : new PlatformWrapperImplBrowser(this); public platformWrapper: PlatformWrapperInterface = null;
public achievementProvider: AchievementProviderInterface = new NoAchievementProvider(this); public achievementProvider: AchievementProviderInterface = null;
public adProvider: AdProviderInterface = new NoAdProvider(this); public adProvider: AdProviderInterface = null;
public analytics: AnalyticsInterface = new GoogleAnalyticsImpl(this); public analytics: AnalyticsInterface = null;
public gameAnalytics = new ShapezGameAnalytics(this); public gameAnalytics: ShapezGameAnalytics = null;
// Track if the window is focused (only relevant for browser)
public focused = true; public focused = true;
// Track if the window is visible
public pageVisible = true; public pageVisible = true;
// Track if the app is paused (cordova)
public applicationPaused = false; public applicationPaused = false;
public trackedIsRenderable = new TrackedState(this.onAppRenderableStateChanged, this); public trackedIsRenderable: TypedTrackedState<boolean> = new TrackedState(this.onAppRenderableStateChanged, this);
public trackedIsPlaying = new TrackedState(this.onAppPlayingStateChanged, this); public trackedIsPlaying: TypedTrackedState<boolean> = new TrackedState(this.onAppPlayingStateChanged, this);
// Dimensions
public screenWidth = 0; public screenWidth = 0;
public screenHeight = 0; public screenHeight = 0;
// Store the timestamp where we last checked for a screen resize, since orientationchange is unreliable with cordova public lastResizeCheck = null;
public lastResizeCheck: number = null; public mousePosition: Vector | null = null;
// Store the mouse position, or null if not available
public mousePosition: Vector = null;
/** /**
* Boots the application * Boots the application
*/ */
async boot(): Promise<void> { async boot() {
console.log("Booting ..."); console.log("Booting ...");
assert(!GLOBAL_APP, "Tried to construct application twice"); assert(!GLOBAL_APP, "Tried to construct application twice");
@ -122,12 +104,11 @@ export class Application {
try { try {
await MODS.initMods(); await MODS.initMods();
} }
catch (ex: any) { catch (ex) {
alert("Failed to load mods (launch with --dev for more info): \n\n" + ex); alert("Failed to load mods (launch with --dev for more info): \n\n" + ex);
} }
this.unloaded = false; this.initPlatformDependentInstances();
this.registerStates(); this.registerStates();
this.registerEventListeners(); this.registerEventListeners();
@ -151,10 +132,30 @@ export class Application {
MOD_SIGNALS.appBooted.dispatch(); MOD_SIGNALS.appBooted.dispatch();
} }
/**
* Initializes all platform instances
*/
initPlatformDependentInstances() {
logger.log("Creating platform dependent instances (standalone=", G_IS_STANDALONE, ")");
if (G_IS_STANDALONE) {
this.platformWrapper = new PlatformWrapperImplElectron(this);
}
else {
this.platformWrapper = new PlatformWrapperImplBrowser(this);
}
// Start with empty ad provider
this.adProvider = new NoAdProvider(this);
this.sound = new SoundImplBrowser(this);
this.analytics = new GoogleAnalyticsImpl(this);
this.gameAnalytics = new ShapezGameAnalytics(this);
this.achievementProvider = new NoAchievementProvider(this);
}
/** /**
* Registers all game states * Registers all game states
*/ */
registerStates(): void { registerStates() {
const states: Array<typeof GameState> = [ const states: Array<typeof GameState> = [
WegameSplashState, WegameSplashState,
PreloadState, PreloadState,
@ -169,6 +170,7 @@ export class Application {
LoginState, LoginState,
ModsState, ModsState,
]; ];
for (let i = 0; i < states.length; ++i) { for (let i = 0; i < states.length; ++i) {
this.stateMgr.register(states[i]); this.stateMgr.register(states[i]);
} }
@ -177,7 +179,7 @@ export class Application {
/** /**
* Registers all event listeners * Registers all event listeners
*/ */
registerEventListeners(): void { registerEventListeners() {
window.addEventListener("focus", this.onFocus.bind(this)); window.addEventListener("focus", this.onFocus.bind(this));
window.addEventListener("blur", this.onBlur.bind(this)); window.addEventListener("blur", this.onBlur.bind(this));
@ -191,19 +193,17 @@ 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(pageVisibilityEventName, 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);
document.addEventListener("touchend", this.updateFocusAfterUserInteraction.bind(this), true); document.addEventListener("touchend", this.updateFocusAfterUserInteraction.bind(this), true);
} }
/** /**
* Checks the focus after a touch * Checks the focus after a touch
*/ */
updateFocusAfterUserInteraction(event: TouchEvent): void { updateFocusAfterUserInteraction(event: TouchEvent) {
const target = (event.target as HTMLElement); const target = event.target as HTMLElement;
if (!target || !target.tagName) { if (!target || !target.tagName) {
// Safety check // Safety check
logger.warn("Invalid touchstart/touchend event:", event); logger.warn("Invalid touchstart/touchend event:", event);
@ -222,16 +222,16 @@ export class Application {
// If we click an input field, focus it now // If we click an input field, focus it now
if (target.tagName.toLowerCase() === "input") { if (target.tagName.toLowerCase() === "input") {
// We *really* need the focus // We *really* need the focus
waitNextFrame().then((): any => target.focus()); waitNextFrame().then(() => target.focus());
} }
} }
/** /**
* Handles a page visibility change event * Handles a page visibility change event
*/ */
handleVisibilityChange(event: Event): void { handleVisibilityChange(event: Event) {
window.focus(); window.focus();
const pageVisible: any = !document[pageHiddenPropName]; const pageVisible = !document[pageHiddenPropName];
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);
@ -242,35 +242,35 @@ export class Application {
/** /**
* Handles a mouse move event * Handles a mouse move event
*/ */
handleMousemove(event: MouseEvent): void { handleMousemove(event: MouseEvent) {
this.mousePosition = new Vector(event.clientX, event.clientY); this.mousePosition = new Vector(event.clientX, event.clientY);
} }
/** /**
* Internal on focus handler * Internal on focus handler
*/ */
onFocus(): void { onFocus() {
this.focused = true; this.focused = true;
} }
/** /**
* Internal blur handler * Internal blur handler
*/ */
onBlur(): void { onBlur() {
this.focused = false; this.focused = false;
} }
/** /**
* Returns if the app is currently visible * Returns if the app is currently visible
*/ */
isRenderable(): boolean { isRenderable() {
return !this.applicationPaused && this.pageVisible; return !this.applicationPaused && this.pageVisible;
} }
onAppRenderableStateChanged(renderable: boolean): void { onAppRenderableStateChanged(renderable: boolean) {
logger.log("Application renderable:", renderable); logger.log("Application renderable:", renderable);
window.focus(); window.focus();
const currentState: any = this.stateMgr.getCurrentState(); const currentState = this.stateMgr.getCurrentState();
if (!renderable) { if (!renderable) {
if (currentState) { if (currentState) {
currentState.onAppPause(); currentState.onAppPause();
@ -286,11 +286,11 @@ export class Application {
this.sound.onPageRenderableStateChanged(renderable); this.sound.onPageRenderableStateChanged(renderable);
} }
onAppPlayingStateChanged(playing: boolean): void { onAppPlayingStateChanged(playing: boolean) {
try { try {
this.adProvider.setPlayStatus(playing); this.adProvider.setPlayStatus(playing);
} }
catch (ex: any) { catch (ex) {
console.warn("Play status changed"); console.warn("Play status changed");
} }
} }
@ -298,10 +298,9 @@ export class Application {
/** /**
* Internal before-unload handler * Internal before-unload handler
*/ */
onBeforeUnload(event: BeforeUnloadEvent): void { onBeforeUnload(event) {
logSection("BEFORE UNLOAD HANDLER", "#f77"); logSection("BEFORE UNLOAD HANDLER", "#f77");
const currentState: GameState = this.stateMgr.getCurrentState(); const currentState = this.stateMgr.getCurrentState();
if (!G_IS_DEV && currentState && currentState.getHasUnloadConfirmation()) { if (!G_IS_DEV && currentState && currentState.getHasUnloadConfirmation()) {
if (!G_IS_STANDALONE) { if (!G_IS_STANDALONE) {
// Need to show a "Are you sure you want to exit" // Need to show a "Are you sure you want to exit"
@ -310,7 +309,6 @@ export class Application {
} }
} }
} }
/** /**
* Deinitializes the application * Deinitializes the application
*/ */
@ -321,12 +319,12 @@ export class Application {
/** /**
* Background frame update callback * Background frame update callback
*/ */
onBackgroundFrame(dt: number): void { onBackgroundFrame(dt: number) {
if (this.isRenderable()) { if (this.isRenderable()) {
return; return;
} }
const currentState: any = this.stateMgr.getCurrentState(); const currentState = this.stateMgr.getCurrentState();
if (currentState) { if (currentState) {
currentState.onBackgroundTick(dt); currentState.onBackgroundTick(dt);
} }
@ -335,12 +333,12 @@ export class Application {
/** /**
* Frame update callback * Frame update callback
*/ */
onFrameEmitted(dt: number): void { onFrameEmitted(dt: number) {
if (!this.isRenderable()) { if (!this.isRenderable()) {
return; return;
} }
const time: any = performance.now(); const time = performance.now();
// Periodically check for resizes, this is expensive (takes 2-3ms so only do it once in a while!) // Periodically check for resizes, this is expensive (takes 2-3ms so only do it once in a while!)
if (!this.lastResizeCheck || time - this.lastResizeCheck > 1000) { if (!this.lastResizeCheck || time - this.lastResizeCheck > 1000) {
@ -348,7 +346,7 @@ export class Application {
this.lastResizeCheck = time; this.lastResizeCheck = time;
} }
const currentState: any = this.stateMgr.getCurrentState(); const currentState = this.stateMgr.getCurrentState();
this.trackedIsPlaying.set(currentState && currentState.getIsIngame()); this.trackedIsPlaying.set(currentState && currentState.getIsIngame());
if (currentState) { if (currentState) {
currentState.onRender(dt); currentState.onRender(dt);
@ -358,19 +356,19 @@ export class Application {
/** /**
* Checks if the app resized. Only does this once in a while * Checks if the app resized. Only does this once in a while
*/ */
checkResize(forceUpdate: boolean = false): void { checkResize(forceUpdate: boolean = false) {
const w = window.innerWidth; const w = window.innerWidth;
const h = window.innerHeight; const h = window.innerHeight;
if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) { if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) {
this.screenWidth = w; this.screenWidth = w;
this.screenHeight = h; this.screenHeight = h;
const currentState: GameState = this.stateMgr.getCurrentState(); const currentState = this.stateMgr.getCurrentState();
if (currentState) { if (currentState) {
currentState.onResized(this.screenWidth, this.screenHeight); currentState.onResized(this.screenWidth, this.screenHeight);
} }
const scale: number = this.getEffectiveUiScale(); const scale = this.getEffectiveUiScale();
waitNextFrame().then((): any => document.documentElement.style.setProperty("--ui-scale", `${scale}`)); waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", `${scale}`));
window.focus(); window.focus();
} }
} }
@ -385,7 +383,7 @@ export class Application {
/** /**
* Callback after ui scale has changed * Callback after ui scale has changed
*/ */
updateAfterUiScaleChanged(): void { updateAfterUiScaleChanged() {
this.checkResize(true); this.checkResize(true);
} }
} }

View File

@ -2,9 +2,9 @@ import { Signal } from "./signal";
// @ts-ignore // @ts-ignore
import BackgroundAnimationFrameEmitterWorker from "../webworkers/background_animation_frame_emittter.worker"; import BackgroundAnimationFrameEmitterWorker from "../webworkers/background_animation_frame_emittter.worker";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
const logger: any = createLogger("animation_frame"); const logger = createLogger("animation_frame");
const maxDtMs: any = 1000; const maxDtMs = 1000;
const resetDtMs: any = 16; const resetDtMs = 16;
export class AnimationFrame { export class AnimationFrame {
public frameEmitted = new Signal(); public frameEmitted = new Signal();
public bgFrameEmitted = new Signal(); public bgFrameEmitted = new Signal();
@ -14,33 +14,33 @@ export class AnimationFrame {
public backgroundWorker = new BackgroundAnimationFrameEmitterWorker(); public backgroundWorker = new BackgroundAnimationFrameEmitterWorker();
constructor() { constructor() {
this.backgroundWorker.addEventListener("error", (err: any): any => { this.backgroundWorker.addEventListener("error", err => {
logger.error("Error in background fps worker:", err); logger.error("Error in background fps worker:", err);
}); });
this.backgroundWorker.addEventListener("message", this.handleBackgroundTick.bind(this)); this.backgroundWorker.addEventListener("message", this.handleBackgroundTick.bind(this));
} }
handleBackgroundTick(): any { handleBackgroundTick() {
const time: any = performance.now(); const time = performance.now();
let dt: any = time - this.bgLastTime; let dt = time - this.bgLastTime;
if (dt > maxDtMs) { if (dt > maxDtMs) {
dt = resetDtMs; dt = resetDtMs;
} }
this.bgFrameEmitted.dispatch(dt); this.bgFrameEmitted.dispatch(dt);
this.bgLastTime = time; this.bgLastTime = time;
} }
start(): any { start() {
assertAlways(window.requestAnimationFrame, "requestAnimationFrame is not supported!"); assertAlways(window.requestAnimationFrame, "requestAnimationFrame is not supported!");
this.handleAnimationFrame(); this.handleAnimationFrame();
} }
handleAnimationFrame(time: any): any { handleAnimationFrame(time) {
let dt: any = time - this.lastTime; let dt = time - this.lastTime;
if (dt > maxDtMs) { if (dt > maxDtMs) {
dt = resetDtMs; dt = resetDtMs;
} }
try { try {
this.frameEmitted.dispatch(dt); this.frameEmitted.dispatch(dt);
} }
catch (ex: any) { catch (ex) {
console.error(ex); console.error(ex);
} }
this.lastTime = time; this.lastTime = time;

View File

@ -1,13 +1,13 @@
import { createLogger } from "./logging"; import { createLogger } from "./logging";
const logger: any = createLogger("assert"); const logger = createLogger("assert");
let assertionErrorShown: any = false; let assertionErrorShown = false;
function initAssert(): any { function initAssert() {
/** /**
* Expects a given condition to be true * Expects a given condition to be true
* @param {} failureMessage * @param {} failureMessage
*/ */
// @ts-ignore // @ts-ignore
window.assert = function (condition: Boolean, ...failureMessage: ...String): any { window.assert = function (condition: Boolean, ...failureMessage: ...String) {
if (!condition) { if (!condition) {
logger.error("assertion failed:", ...failureMessage); logger.error("assertion failed:", ...failureMessage);
if (!assertionErrorShown) { if (!assertionErrorShown) {

View File

@ -2,15 +2,15 @@
import CompressionWorker from "../webworkers/compression.worker"; import CompressionWorker from "../webworkers/compression.worker";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { round2Digits } from "./utils"; import { round2Digits } from "./utils";
const logger: any = createLogger("async_compression"); const logger = createLogger("async_compression");
export let compressionPrefix: any = String.fromCodePoint(1); export let compressionPrefix = String.fromCodePoint(1);
function checkCryptPrefix(prefix: any): any { function checkCryptPrefix(prefix) {
try { try {
window.localStorage.setItem("prefix_test", prefix); window.localStorage.setItem("prefix_test", prefix);
window.localStorage.removeItem("prefix_test"); window.localStorage.removeItem("prefix_test");
return true; return true;
} }
catch (ex: any) { catch (ex) {
logger.warn("Prefix '" + prefix + "' not available"); logger.warn("Prefix '" + prefix + "' not available");
return false; return false;
} }
@ -36,27 +36,27 @@ class AsynCompression {
} = {}; } = {};
constructor() { constructor() {
this.worker.addEventListener("message", (event: any): any => { this.worker.addEventListener("message", event => {
const { jobId, result }: any = event.data; const { jobId, result } = event.data;
const jobData: any = this.currentJobs[jobId]; const jobData = this.currentJobs[jobId];
if (!jobData) { if (!jobData) {
logger.error("Failed to resolve job result, job id", jobId, "is not known"); logger.error("Failed to resolve job result, job id", jobId, "is not known");
return; return;
} }
const duration: any = performance.now() - jobData.startTime; const duration = performance.now() - jobData.startTime;
logger.log("Got job", jobId, "response within", round2Digits(duration), "ms: ", result.length, "bytes"); logger.log("Got job", jobId, "response within", round2Digits(duration), "ms: ", result.length, "bytes");
const resolver: any = jobData.resolver; const resolver = jobData.resolver;
delete this.currentJobs[jobId]; delete this.currentJobs[jobId];
resolver(result); resolver(result);
}); });
this.worker.addEventListener("error", (err: any): any => { this.worker.addEventListener("error", err => {
logger.error("Got error from webworker:", err, "aborting all jobs"); logger.error("Got error from webworker:", err, "aborting all jobs");
const failureCalls: any = []; const failureCalls = [];
for (const jobId: any in this.currentJobs) { for (const jobId in this.currentJobs) {
failureCalls.push(this.currentJobs[jobId].errorHandler); failureCalls.push(this.currentJobs[jobId].errorHandler);
} }
this.currentJobs = {}; this.currentJobs = {};
for (let i: any = 0; i < failureCalls.length; ++i) { for (let i = 0; i < failureCalls.length; ++i) {
failureCalls[i](err); failureCalls[i](err);
} }
}); });
@ -64,7 +64,7 @@ class AsynCompression {
/** /**
* Compresses any object * Compresses any object
*/ */
compressObjectAsync(obj: any): any { compressObjectAsync(obj: any) {
logger.log("Compressing object async (optimized)"); logger.log("Compressing object async (optimized)");
return this.internalQueueJob("compressObject", { return this.internalQueueJob("compressObject", {
obj, obj,
@ -76,9 +76,9 @@ class AsynCompression {
* {} * {}
*/ */
internalQueueJob(job: string, data: any): Promise<any> { internalQueueJob(job: string, data: any): Promise<any> {
const jobId: any = ++this.currentJobId; const jobId = ++this.currentJobId;
return new Promise((resolve: any, reject: any): any => { return new Promise((resolve, reject) => {
const errorHandler: any = (err: any): any => { const errorHandler = err => {
logger.error("Failed to compress job", jobId, ":", err); logger.error("Failed to compress job", jobId, ":", err);
reject(err); reject(err);
}; };
@ -92,4 +92,4 @@ class AsynCompression {
}); });
} }
} }
export const asyncCompressor: any = new AsynCompression(); export const asyncCompressor = new AsynCompression();

View File

@ -34,7 +34,7 @@ export class AtlasDefinition {
constructor({ frames, meta }) { constructor({ frames, meta }) {
} }
getFullSourcePath(): any { getFullSourcePath() {
return this.sourceFileName; return this.sourceFileName;
} }
} }
@ -42,6 +42,6 @@ export const atlasFiles: AtlasDefinition[] = require
// @ts-ignore // @ts-ignore
.context("../../../res_built/atlas/", false, /.*\.json/i) .context("../../../res_built/atlas/", false, /.*\.json/i)
.keys() .keys()
.map((f: any): any => f.replace(/^\.\//gi, "")) .map(f => f.replace(/^\.\//gi, ""))
.map((f: any): any => require("../../../res_built/atlas/" + f)) .map(f => require("../../../res_built/atlas/" + f))
.map((data: any): any => new AtlasDefinition(data)); .map(data => new AtlasDefinition(data));

View File

@ -10,18 +10,18 @@ import { Loader } from "./loader";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { Signal } from "./signal"; import { Signal } from "./signal";
import { clamp, getLogoSprite, timeoutPromise } from "./utils"; import { clamp, getLogoSprite, timeoutPromise } from "./utils";
const logger: any = createLogger("background_loader"); const logger = createLogger("background_loader");
const MAIN_MENU_ASSETS: any = { const MAIN_MENU_ASSETS = {
sprites: [getLogoSprite()], sprites: [getLogoSprite()],
sounds: [SOUNDS.uiClick, SOUNDS.uiError, SOUNDS.dialogError, SOUNDS.dialogOk], sounds: [SOUNDS.uiClick, SOUNDS.uiError, SOUNDS.dialogError, SOUNDS.dialogOk],
atlas: [], atlas: [],
css: [], css: [],
}; };
const INGAME_ASSETS: any = { const INGAME_ASSETS = {
sprites: [], sprites: [],
sounds: [ sounds: [
...Array.from(Object.values(MUSIC)), ...Array.from(Object.values(MUSIC)),
...Array.from(Object.values(SOUNDS)).filter((sound: any): any => !MAIN_MENU_ASSETS.sounds.includes(sound)), ...Array.from(Object.values(SOUNDS)).filter(sound => !MAIN_MENU_ASSETS.sounds.includes(sound)),
], ],
atlas: atlasFiles, atlas: atlasFiles,
css: ["async-resources.css"], css: ["async-resources.css"],
@ -30,10 +30,10 @@ if (G_IS_STANDALONE) {
MAIN_MENU_ASSETS.sounds = [...Array.from(Object.values(MUSIC)), ...Array.from(Object.values(SOUNDS))]; MAIN_MENU_ASSETS.sounds = [...Array.from(Object.values(MUSIC)), ...Array.from(Object.values(SOUNDS))];
INGAME_ASSETS.sounds = []; INGAME_ASSETS.sounds = [];
} }
const LOADER_TIMEOUT_PER_RESOURCE: any = 180000; const LOADER_TIMEOUT_PER_RESOURCE = 180000;
// Cloudflare does not send content-length headers with brotli compression, // Cloudflare does not send content-length headers with brotli compression,
// so store the actual (compressed) file sizes so we can show a progress bar. // so store the actual (compressed) file sizes so we can show a progress bar.
const HARDCODED_FILE_SIZES: any = { const HARDCODED_FILE_SIZES = {
"async-resources.css": 2216145, "async-resources.css": 2216145,
}; };
export class BackgroundResourcesLoader { export class BackgroundResourcesLoader {
@ -44,19 +44,19 @@ export class BackgroundResourcesLoader {
constructor(app) { constructor(app) {
} }
getMainMenuPromise(): any { getMainMenuPromise() {
if (this.mainMenuPromise) { if (this.mainMenuPromise) {
return this.mainMenuPromise; return this.mainMenuPromise;
} }
logger.log("⏰ Loading main menu assets"); logger.log("⏰ Loading main menu assets");
return (this.mainMenuPromise = this.loadAssets(MAIN_MENU_ASSETS)); return (this.mainMenuPromise = this.loadAssets(MAIN_MENU_ASSETS));
} }
getIngamePromise(): any { getIngamePromise() {
if (this.ingamePromise) { if (this.ingamePromise) {
return this.ingamePromise; return this.ingamePromise;
} }
logger.log("⏰ Loading ingame assets"); logger.log("⏰ Loading ingame assets");
const promise: any = this.loadAssets(INGAME_ASSETS).then((): any => initSpriteCache()); const promise = this.loadAssets(INGAME_ASSETS).then(() => initSpriteCache());
return (this.ingamePromise = promise); return (this.ingamePromise = promise);
} }
async loadAssets({ sprites, sounds, atlas, css }: { async loadAssets({ sprites, sounds, atlas, css }: {
@ -64,50 +64,50 @@ export class BackgroundResourcesLoader {
sounds: string[]; sounds: string[];
atlas: AtlasDefinition[]; atlas: AtlasDefinition[];
css: string[]; css: string[];
}): any { }) {
let promiseFunctions: ((progressHandler: (progress: number) => void) => Promise<void>)[] = []; let promiseFunctions: ((progressHandler: (progress: number) => void) => Promise<void>)[] = [];
// CSS // CSS
for (let i: any = 0; i < css.length; ++i) { for (let i = 0; i < css.length; ++i) {
promiseFunctions.push((progress: any): any => timeoutPromise(this.internalPreloadCss(css[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch((err: any): any => { promiseFunctions.push(progress => timeoutPromise(this.internalPreloadCss(css[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch(err => {
logger.error("Failed to load css:", css[i], err); logger.error("Failed to load css:", css[i], err);
throw new Error("HUD Stylesheet " + css[i] + " failed to load: " + err); throw new Error("HUD Stylesheet " + css[i] + " failed to load: " + err);
})); }));
} }
// ATLAS FILES // ATLAS FILES
for (let i: any = 0; i < atlas.length; ++i) { for (let i = 0; i < atlas.length; ++i) {
promiseFunctions.push((progress: any): any => timeoutPromise(Loader.preloadAtlas(atlas[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch((err: any): any => { promiseFunctions.push(progress => timeoutPromise(Loader.preloadAtlas(atlas[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch(err => {
logger.error("Failed to load atlas:", atlas[i].sourceFileName, err); logger.error("Failed to load atlas:", atlas[i].sourceFileName, err);
throw new Error("Atlas " + atlas[i].sourceFileName + " failed to load: " + err); throw new Error("Atlas " + atlas[i].sourceFileName + " failed to load: " + err);
})); }));
} }
// HUD Sprites // HUD Sprites
for (let i: any = 0; i < sprites.length; ++i) { for (let i = 0; i < sprites.length; ++i) {
promiseFunctions.push((progress: any): any => timeoutPromise(Loader.preloadCSSSprite(sprites[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch((err: any): any => { promiseFunctions.push(progress => timeoutPromise(Loader.preloadCSSSprite(sprites[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch(err => {
logger.error("Failed to load css sprite:", sprites[i], err); logger.error("Failed to load css sprite:", sprites[i], err);
throw new Error("HUD Sprite " + sprites[i] + " failed to load: " + err); throw new Error("HUD Sprite " + sprites[i] + " failed to load: " + err);
})); }));
} }
// SFX & Music // SFX & Music
for (let i: any = 0; i < sounds.length; ++i) { for (let i = 0; i < sounds.length; ++i) {
promiseFunctions.push((progress: any): any => timeoutPromise(this.app.sound.loadSound(sounds[i]), LOADER_TIMEOUT_PER_RESOURCE).catch((err: any): any => { promiseFunctions.push(progress => timeoutPromise(this.app.sound.loadSound(sounds[i]), LOADER_TIMEOUT_PER_RESOURCE).catch(err => {
logger.warn("Failed to load sound, will not be available:", sounds[i], err); logger.warn("Failed to load sound, will not be available:", sounds[i], err);
})); }));
} }
const originalAmount: any = promiseFunctions.length; const originalAmount = promiseFunctions.length;
const start: any = performance.now(); const start = performance.now();
logger.log("⏰ Preloading", originalAmount, "assets"); logger.log("⏰ Preloading", originalAmount, "assets");
let progress: any = 0; let progress = 0;
this.resourceStateChangedSignal.dispatch({ progress }); this.resourceStateChangedSignal.dispatch({ progress });
let promises: any = []; let promises = [];
for (let i: any = 0; i < promiseFunctions.length; i++) { for (let i = 0; i < promiseFunctions.length; i++) {
let lastIndividualProgress: any = 0; let lastIndividualProgress = 0;
const progressHandler: any = (individualProgress: any): any => { const progressHandler = individualProgress => {
const delta: any = clamp(individualProgress) - lastIndividualProgress; const delta = clamp(individualProgress) - lastIndividualProgress;
lastIndividualProgress = clamp(individualProgress); lastIndividualProgress = clamp(individualProgress);
progress += delta / originalAmount; progress += delta / originalAmount;
this.resourceStateChangedSignal.dispatch({ progress }); this.resourceStateChangedSignal.dispatch({ progress });
}; };
promises.push(promiseFunctions[i](progressHandler).then((): any => { promises.push(promiseFunctions[i](progressHandler).then(() => {
progressHandler(1); progressHandler(1);
})); }));
} }
@ -117,28 +117,28 @@ export class BackgroundResourcesLoader {
/** /**
* Shows an error when a resource failed to load and allows to reload the game * Shows an error when a resource failed to load and allows to reload the game
*/ */
showLoaderError(dialogs: any, err: any): any { showLoaderError(dialogs, err) {
if (G_IS_STANDALONE) { if (G_IS_STANDALONE) {
dialogs dialogs
.showWarning(T.dialogs.resourceLoadFailed.title, T.dialogs.resourceLoadFailed.descSteamDemo + "<br>" + err, ["retry"]) .showWarning(T.dialogs.resourceLoadFailed.title, T.dialogs.resourceLoadFailed.descSteamDemo + "<br>" + err, ["retry"])
.retry.add((): any => window.location.reload()); .retry.add(() => window.location.reload());
} }
else { else {
dialogs dialogs
.showWarning(T.dialogs.resourceLoadFailed.title, T.dialogs.resourceLoadFailed.descWeb.replace("<demoOnSteamLinkText>", `<a href="https://get.shapez.io/resource_timeout" target="_blank">${T.dialogs.resourceLoadFailed.demoLinkText}</a>`) + .showWarning(T.dialogs.resourceLoadFailed.title, T.dialogs.resourceLoadFailed.descWeb.replace("<demoOnSteamLinkText>", `<a href="https://get.shapez.io/resource_timeout" target="_blank">${T.dialogs.resourceLoadFailed.demoLinkText}</a>`) +
"<br>" + "<br>" +
err, ["retry"]) err, ["retry"])
.retry.add((): any => window.location.reload()); .retry.add(() => window.location.reload());
} }
} }
preloadWithProgress(src: any, progressHandler: any): any { preloadWithProgress(src, progressHandler) {
return new Promise((resolve: any, reject: any): any => { return new Promise((resolve, reject) => {
const xhr: any = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
let notifiedNotComputable: any = false; let notifiedNotComputable = false;
const fullUrl: any = cachebust(src); const fullUrl = cachebust(src);
xhr.open("GET", fullUrl, true); xhr.open("GET", fullUrl, true);
xhr.responseType = "arraybuffer"; xhr.responseType = "arraybuffer";
xhr.onprogress = function (ev: any): any { xhr.onprogress = function (ev) {
if (ev.lengthComputable) { if (ev.lengthComputable) {
progressHandler(ev.loaded / ev.total); progressHandler(ev.loaded / ev.total);
} }
@ -158,7 +158,7 @@ export class BackgroundResourcesLoader {
} }
} }
}; };
xhr.onloadend = function (): any { xhr.onloadend = function () {
if (!xhr.status.toString().match(/^2/)) { if (!xhr.status.toString().match(/^2/)) {
reject(fullUrl + ": " + xhr.status + " " + xhr.statusText); reject(fullUrl + ": " + xhr.status + " " + xhr.statusText);
} }
@ -166,22 +166,22 @@ export class BackgroundResourcesLoader {
if (!notifiedNotComputable) { if (!notifiedNotComputable) {
progressHandler(1); progressHandler(1);
} }
const options: any = {}; const options = {};
const headers: any = xhr.getAllResponseHeaders(); const headers = xhr.getAllResponseHeaders();
const contentType: any = headers.match(/^Content-Type:\s*(.*?)$/im); const contentType = headers.match(/^Content-Type:\s*(.*?)$/im);
if (contentType && contentType[1]) { if (contentType && contentType[1]) {
options.type = contentType[1].split(";")[0]; options.type = contentType[1].split(";")[0];
} }
const blob: any = new Blob([this.response], options); const blob = new Blob([this.response], options);
resolve(window.URL.createObjectURL(blob)); resolve(window.URL.createObjectURL(blob));
} }
}; };
xhr.send(); xhr.send();
}); });
} }
internalPreloadCss(src: any, progressHandler: any): any { internalPreloadCss(src, progressHandler) {
return this.preloadWithProgress(src, progressHandler).then((blobSrc: any): any => { return this.preloadWithProgress(src, progressHandler).then(blobSrc => {
var styleElement: any = document.createElement("link"); var styleElement = document.createElement("link");
styleElement.href = blobSrc; styleElement.href = blobSrc;
styleElement.rel = "stylesheet"; styleElement.rel = "stylesheet";
styleElement.setAttribute("media", "all"); styleElement.setAttribute("media", "all");

View File

@ -8,8 +8,8 @@ export type CacheEntry = {
lastUse: number; lastUse: number;
}; };
const logger: any = createLogger("buffers"); const logger = createLogger("buffers");
const bufferGcDurationSeconds: any = 0.5; const bufferGcDurationSeconds = 0.5;
export class BufferMaintainer { export class BufferMaintainer {
public root = root; public root = root;
public cache: Map<string, Map<string, CacheEntry>> = new Map(); public cache: Map<string, Map<string, CacheEntry>> = new Map();
@ -22,17 +22,17 @@ export class BufferMaintainer {
/** /**
* Returns the buffer stats * Returns the buffer stats
*/ */
getStats(): any { getStats() {
let stats: any = { let stats = {
rootKeys: 0, rootKeys: 0,
subKeys: 0, subKeys: 0,
vramBytes: 0, vramBytes: 0,
}; };
this.cache.forEach((subCache: any, key: any): any => { this.cache.forEach((subCache, key) => {
++stats.rootKeys; ++stats.rootKeys;
subCache.forEach((cacheEntry: any, subKey: any): any => { subCache.forEach((cacheEntry, subKey) => {
++stats.subKeys; ++stats.subKeys;
const canvas: any = cacheEntry.canvas; const canvas = cacheEntry.canvas;
stats.vramBytes += canvas.width * canvas.height * 4; stats.vramBytes += canvas.width * canvas.height * 4;
}); });
}); });
@ -42,14 +42,14 @@ export class BufferMaintainer {
* Goes to the next buffer iteration, clearing all buffers which were not used * Goes to the next buffer iteration, clearing all buffers which were not used
* for a few iterations * for a few iterations
*/ */
garbargeCollect(): any { garbargeCollect() {
let totalKeys: any = 0; let totalKeys = 0;
let deletedKeys: any = 0; let deletedKeys = 0;
const minIteration: any = this.iterationIndex; const minIteration = this.iterationIndex;
this.cache.forEach((subCache: any, key: any): any => { this.cache.forEach((subCache, key) => {
let unusedSubKeys: any = []; let unusedSubKeys = [];
// Filter sub cache // Filter sub cache
subCache.forEach((cacheEntry: any, subKey: any): any => { subCache.forEach((cacheEntry, subKey) => {
if (cacheEntry.lastUse < minIteration || if (cacheEntry.lastUse < minIteration ||
// @ts-ignore // @ts-ignore
cacheEntry.canvas._contextLost) { cacheEntry.canvas._contextLost) {
@ -62,7 +62,7 @@ export class BufferMaintainer {
} }
}); });
// Delete unused sub keys // Delete unused sub keys
for (let i: any = 0; i < unusedSubKeys.length; ++i) { for (let i = 0; i < unusedSubKeys.length; ++i) {
subCache.delete(unusedSubKeys[i]); subCache.delete(unusedSubKeys[i]);
} }
}); });
@ -91,8 +91,8 @@ export class BufferMaintainer {
// } // }
++this.iterationIndex; ++this.iterationIndex;
} }
update(): any { update() {
const now: any = this.root.time.realtimeNow(); const now = this.root.time.realtimeNow();
if (now - this.lastIteration > bufferGcDurationSeconds) { if (now - this.lastIteration > bufferGcDurationSeconds) {
this.lastIteration = now; this.lastIteration = now;
this.garbargeCollect(); this.garbargeCollect();
@ -112,21 +112,21 @@ export class BufferMaintainer {
additionalParams: object=; additionalParams: object=;
}): HTMLCanvasElement { }): HTMLCanvasElement {
// First, create parent key // First, create parent key
let parent: any = this.cache.get(key); let parent = this.cache.get(key);
if (!parent) { if (!parent) {
parent = new Map(); parent = new Map();
this.cache.set(key, parent); this.cache.set(key, parent);
} }
// Now search for sub key // Now search for sub key
const cacheHit: any = parent.get(subKey); const cacheHit = parent.get(subKey);
if (cacheHit) { if (cacheHit) {
cacheHit.lastUse = this.iterationIndex; cacheHit.lastUse = this.iterationIndex;
return cacheHit.canvas; return cacheHit.canvas;
} }
// Need to generate new buffer // Need to generate new buffer
const effectiveWidth: any = w * dpi; const effectiveWidth = w * dpi;
const effectiveHeight: any = h * dpi; const effectiveHeight = h * dpi;
const [canvas, context]: any = makeOffscreenBuffer(effectiveWidth, effectiveHeight, { const [canvas, context] = makeOffscreenBuffer(effectiveWidth, effectiveHeight, {
reusable: true, reusable: true,
label: "buffer-" + key + "/" + subKey, label: "buffer-" + key + "/" + subKey,
smooth: true, smooth: true,
@ -147,12 +147,12 @@ export class BufferMaintainer {
key: string; key: string;
subKey: string; subKey: string;
}): ?HTMLCanvasElement { }): ?HTMLCanvasElement {
let parent: any = this.cache.get(key); let parent = this.cache.get(key);
if (!parent) { if (!parent) {
return null; return null;
} }
// Now search for sub key // Now search for sub key
const cacheHit: any = parent.get(subKey); const cacheHit = parent.get(subKey);
if (cacheHit) { if (cacheHit) {
return cacheHit.canvas; return cacheHit.canvas;
} }

View File

@ -1,11 +1,11 @@
import { globalConfig } from "./config"; import { globalConfig } from "./config";
import { fastArrayDelete } from "./utils"; import { fastArrayDelete } from "./utils";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
const logger: any = createLogger("buffer_utils"); const logger = createLogger("buffer_utils");
/** /**
* Enables images smoothing on a context * Enables images smoothing on a context
*/ */
export function enableImageSmoothing(context: CanvasRenderingContext2D): any { export function enableImageSmoothing(context: CanvasRenderingContext2D) {
context.imageSmoothingEnabled = true; context.imageSmoothingEnabled = true;
context.webkitImageSmoothingEnabled = true; context.webkitImageSmoothingEnabled = true;
// @ts-ignore // @ts-ignore
@ -14,7 +14,7 @@ export function enableImageSmoothing(context: CanvasRenderingContext2D): any {
/** /**
* Disables image smoothing on a context * Disables image smoothing on a context
*/ */
export function disableImageSmoothing(context: CanvasRenderingContext2D): any { export function disableImageSmoothing(context: CanvasRenderingContext2D) {
context.imageSmoothingEnabled = false; context.imageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false; context.webkitImageSmoothingEnabled = false;
} }
@ -31,14 +31,14 @@ const freeCanvasBuckets: Map<number, Array<CanvasCacheEntry>> = new Map();
/** /**
* Track statistics * Track statistics
*/ */
const stats: any = { const stats = {
vramUsage: 0, vramUsage: 0,
backlogVramUsage: 0, backlogVramUsage: 0,
bufferCount: 0, bufferCount: 0,
numReused: 0, numReused: 0,
numCreated: 0, numCreated: 0,
}; };
export function getBufferVramUsageBytes(canvas: HTMLCanvasElement): any { export function getBufferVramUsageBytes(canvas: HTMLCanvasElement) {
assert(canvas, "no canvas given"); assert(canvas, "no canvas given");
assert(Number.isFinite(canvas.width), "bad canvas width: " + canvas.width); assert(Number.isFinite(canvas.width), "bad canvas width: " + canvas.width);
assert(Number.isFinite(canvas.height), "bad canvas height" + canvas.height); assert(Number.isFinite(canvas.height), "bad canvas height" + canvas.height);
@ -47,9 +47,9 @@ export function getBufferVramUsageBytes(canvas: HTMLCanvasElement): any {
/** /**
* Returns stats on the allocated buffers * Returns stats on the allocated buffers
*/ */
export function getBufferStats(): any { export function getBufferStats() {
let numBuffersFree: any = 0; let numBuffersFree = 0;
freeCanvasBuckets.forEach((bucket: any): any => { freeCanvasBuckets.forEach(bucket => {
numBuffersFree += bucket.length; numBuffersFree += bucket.length;
}); });
return { return {
@ -61,10 +61,10 @@ export function getBufferStats(): any {
/** /**
* Clears the backlog buffers if they grew too much * Clears the backlog buffers if they grew too much
*/ */
export function clearBufferBacklog(): any { export function clearBufferBacklog() {
freeCanvasBuckets.forEach((bucket: any): any => { freeCanvasBuckets.forEach(bucket => {
while (bucket.length > 500) { while (bucket.length > 500) {
const entry: any = bucket[bucket.length - 1]; const entry = bucket[bucket.length - 1];
stats.backlogVramUsage -= getBufferVramUsageBytes(entry.canvas); stats.backlogVramUsage -= getBufferVramUsageBytes(entry.canvas);
delete entry.canvas; delete entry.canvas;
delete entry.context; delete entry.context;
@ -76,7 +76,7 @@ export function clearBufferBacklog(): any {
* Creates a new offscreen buffer * Creates a new offscreen buffer
* {} * {}
*/ */
export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusable = true, label = "buffer" }: any): [ export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusable = true, label = "buffer" }): [
HTMLCanvasElement, HTMLCanvasElement,
CanvasRenderingContext2D CanvasRenderingContext2D
] { ] {
@ -89,18 +89,18 @@ export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusa
w = Math.max(1, w); w = Math.max(1, w);
h = Math.max(1, h); h = Math.max(1, h);
} }
const recommendedSize: any = 1024 * 1024; const recommendedSize = 1024 * 1024;
if (w * h > recommendedSize) { if (w * h > recommendedSize) {
logger.warn("Creating huge buffer:", w, "x", h, "with label", label); logger.warn("Creating huge buffer:", w, "x", h, "with label", label);
} }
w = Math.floor(w); w = Math.floor(w);
h = Math.floor(h); h = Math.floor(h);
let canvas: any = null; let canvas = null;
let context: any = null; let context = null;
// Ok, search in cache first // Ok, search in cache first
const bucket: any = freeCanvasBuckets.get(w * h) || []; const bucket = freeCanvasBuckets.get(w * h) || [];
for (let i: any = 0; i < bucket.length; ++i) { for (let i = 0; i < bucket.length; ++i) {
const { canvas: useableCanvas, context: useableContext }: any = bucket[i]; const { canvas: useableCanvas, context: useableContext } = bucket[i];
if (useableCanvas.width === w && useableCanvas.height === h) { if (useableCanvas.width === w && useableCanvas.height === h) {
// Ok we found one // Ok we found one
canvas = useableCanvas; canvas = useableCanvas;
@ -126,12 +126,12 @@ export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusa
canvas.height = h; canvas.height = h;
// Initial state // Initial state
context.save(); context.save();
canvas.addEventListener("webglcontextlost", (): any => { canvas.addEventListener("webglcontextlost", () => {
console.warn("canvas::webglcontextlost", canvas); console.warn("canvas::webglcontextlost", canvas);
// @ts-ignore // @ts-ignore
canvas._contextLost = true; canvas._contextLost = true;
}); });
canvas.addEventListener("contextlost", (): any => { canvas.addEventListener("contextlost", () => {
console.warn("canvas::contextlost", canvas); console.warn("canvas::contextlost", canvas);
// @ts-ignore // @ts-ignore
canvas._contextLost = true; canvas._contextLost = true;
@ -155,20 +155,20 @@ export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusa
/** /**
* Frees a canvas * Frees a canvas
*/ */
export function registerCanvas(canvas: HTMLCanvasElement, context: any): any { export function registerCanvas(canvas: HTMLCanvasElement, context) {
registeredCanvas.push({ canvas, context }); registeredCanvas.push({ canvas, context });
stats.bufferCount += 1; stats.bufferCount += 1;
const bytesUsed: any = getBufferVramUsageBytes(canvas); const bytesUsed = getBufferVramUsageBytes(canvas);
stats.vramUsage += bytesUsed; stats.vramUsage += bytesUsed;
} }
/** /**
* Frees a canvas * Frees a canvas
*/ */
export function freeCanvas(canvas: HTMLCanvasElement): any { export function freeCanvas(canvas: HTMLCanvasElement) {
assert(canvas, "Canvas is empty"); assert(canvas, "Canvas is empty");
let index: any = -1; let index = -1;
let data: any = null; let data = null;
for (let i: any = 0; i < registeredCanvas.length; ++i) { for (let i = 0; i < registeredCanvas.length; ++i) {
if (registeredCanvas[i].canvas === canvas) { if (registeredCanvas[i].canvas === canvas) {
index = i; index = i;
data = registeredCanvas[i]; data = registeredCanvas[i];
@ -180,8 +180,8 @@ export function freeCanvas(canvas: HTMLCanvasElement): any {
return; return;
} }
fastArrayDelete(registeredCanvas, index); fastArrayDelete(registeredCanvas, index);
const key: any = canvas.width * canvas.height; const key = canvas.width * canvas.height;
const bucket: any = freeCanvasBuckets.get(key); const bucket = freeCanvasBuckets.get(key);
if (bucket) { if (bucket) {
bucket.push(data); bucket.push(data);
} }
@ -189,7 +189,7 @@ export function freeCanvas(canvas: HTMLCanvasElement): any {
freeCanvasBuckets.set(key, [data]); freeCanvasBuckets.set(key, [data]);
} }
stats.bufferCount -= 1; stats.bufferCount -= 1;
const bytesUsed: any = getBufferVramUsageBytes(canvas); const bytesUsed = getBufferVramUsageBytes(canvas);
stats.vramUsage -= bytesUsed; stats.vramUsage -= bytesUsed;
stats.backlogVramUsage += bytesUsed; stats.backlogVramUsage += bytesUsed;
} }

View File

@ -1,7 +1,7 @@
/** /**
* Generates a cachebuster string. This only modifies the path in the browser version * Generates a cachebuster string. This only modifies the path in the browser version
*/ */
export function cachebust(path: string): any { export function cachebust(path: string) {
if (G_IS_BROWSER && !G_IS_STANDALONE && !G_IS_DEV) { if (G_IS_BROWSER && !G_IS_STANDALONE && !G_IS_DEV) {
return "/v/" + G_BUILD_COMMIT_HASH + "/" + path; return "/v/" + G_BUILD_COMMIT_HASH + "/" + path;
} }

View File

@ -5,17 +5,17 @@ import { Vector } from "./vector";
import { IS_MOBILE, SUPPORT_TOUCH } from "./config"; import { IS_MOBILE, SUPPORT_TOUCH } from "./config";
import { SOUNDS } from "../platform/sound"; import { SOUNDS } from "../platform/sound";
import { GLOBAL_APP } from "./globals"; import { GLOBAL_APP } from "./globals";
const logger: any = createLogger("click_detector"); const logger = createLogger("click_detector");
export const MAX_MOVE_DISTANCE_PX: any = IS_MOBILE ? 20 : 80; export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 80;
// For debugging // For debugging
const registerClickDetectors: any = G_IS_DEV && true; const registerClickDetectors = G_IS_DEV && true;
if (registerClickDetectors) { if (registerClickDetectors) {
window.activeClickDetectors = []; window.activeClickDetectors = [];
} }
// Store active click detectors so we can cancel them // Store active click detectors so we can cancel them
const ongoingClickDetectors: Array<ClickDetector> = []; const ongoingClickDetectors: Array<ClickDetector> = [];
// Store when the last touch event was registered, to avoid accepting a touch *and* a click event // Store when the last touch event was registered, to avoid accepting a touch *and* a click event
export let clickDetectorGlobals: any = { export let clickDetectorGlobals = {
lastTouchTime: -1000, lastTouchTime: -1000,
}; };
export type ClickDetectorConstructorArgs = { export type ClickDetectorConstructorArgs = {
@ -59,10 +59,10 @@ export class ClickDetector {
/** /**
* Cleans up all event listeners of this detector * Cleans up all event listeners of this detector
*/ */
cleanup(): any { cleanup() {
if (this.element) { if (this.element) {
if (registerClickDetectors) { if (registerClickDetectors) {
const index: any = window.activeClickDetectors.indexOf(this); const index = window.activeClickDetectors.indexOf(this);
if (index < 0) { if (index < 0) {
logger.error("Click detector cleanup but is not active"); logger.error("Click detector cleanup but is not active");
} }
@ -70,7 +70,7 @@ export class ClickDetector {
window.activeClickDetectors.splice(index, 1); window.activeClickDetectors.splice(index, 1);
} }
} }
const options: any = this.internalGetEventListenerOptions(); const options = this.internalGetEventListenerOptions();
if (SUPPORT_TOUCH) { if (SUPPORT_TOUCH) {
this.element.removeEventListener("touchstart", this.handlerTouchStart, options); this.element.removeEventListener("touchstart", this.handlerTouchStart, options);
this.element.removeEventListener("touchend", this.handlerTouchEnd, options); this.element.removeEventListener("touchend", this.handlerTouchEnd, options);
@ -97,14 +97,14 @@ export class ClickDetector {
} }
} }
// INTERNAL METHODS // INTERNAL METHODS
internalPreventClick(event: Event): any { internalPreventClick(event: Event) {
window.focus(); window.focus();
event.preventDefault(); event.preventDefault();
} }
/** /**
* Internal method to get the options to pass to an event listener * Internal method to get the options to pass to an event listener
*/ */
internalGetEventListenerOptions(): any { internalGetEventListenerOptions() {
return { return {
capture: this.consumeEvents, capture: this.consumeEvents,
passive: !this.preventDefault, passive: !this.preventDefault,
@ -113,8 +113,8 @@ export class ClickDetector {
/** /**
* Binds the click detector to an element * Binds the click detector to an element
*/ */
internalBindTo(element: HTMLElement): any { internalBindTo(element: HTMLElement) {
const options: any = this.internalGetEventListenerOptions(); const options = this.internalGetEventListenerOptions();
this.handlerTouchStart = this.internalOnPointerDown.bind(this); this.handlerTouchStart = this.internalOnPointerDown.bind(this);
this.handlerTouchEnd = this.internalOnPointerEnd.bind(this); this.handlerTouchEnd = this.internalOnPointerEnd.bind(this);
this.handlerTouchMove = this.internalOnPointerMove.bind(this); this.handlerTouchMove = this.internalOnPointerMove.bind(this);
@ -145,13 +145,13 @@ export class ClickDetector {
/** /**
* Returns if the bound element is currently in the DOM. * Returns if the bound element is currently in the DOM.
*/ */
internalIsDomElementAttached(): any { internalIsDomElementAttached() {
return this.element && document.documentElement.contains(this.element); return this.element && document.documentElement.contains(this.element);
} }
/** /**
* Checks if the given event is relevant for this detector * Checks if the given event is relevant for this detector
*/ */
internalEventPreHandler(event: TouchEvent | MouseEvent, expectedRemainingTouches: any = 1): any { internalEventPreHandler(event: TouchEvent | MouseEvent, expectedRemainingTouches = 1) {
if (!this.element) { if (!this.element) {
// Already cleaned up // Already cleaned up
return false; return false;
@ -191,7 +191,7 @@ export class ClickDetector {
logger.warn("Got unexpected target touches:", event.targetTouches.length, "->", event.targetTouches); logger.warn("Got unexpected target touches:", event.targetTouches.length, "->", event.targetTouches);
return new Vector(0, 0); return new Vector(0, 0);
} }
const touch: any = event.changedTouches[0]; const touch = event.changedTouches[0];
return new Vector(touch.clientX, touch.clientY); return new Vector(touch.clientX, touch.clientY);
} }
if (event instanceof MouseEvent) { if (event instanceof MouseEvent) {
@ -203,7 +203,7 @@ export class ClickDetector {
/** /**
* Cacnels all ongoing events on this detector * Cacnels all ongoing events on this detector
*/ */
cancelOngoingEvents(): any { cancelOngoingEvents() {
if (this.applyCssClass && this.element) { if (this.applyCssClass && this.element) {
this.element.classList.remove(this.applyCssClass); this.element.classList.remove(this.applyCssClass);
} }
@ -215,15 +215,15 @@ export class ClickDetector {
/** /**
* Internal pointer down handler * Internal pointer down handler
*/ */
internalOnPointerDown(event: TouchEvent | MouseEvent): any { internalOnPointerDown(event: TouchEvent | MouseEvent) {
window.focus(); window.focus();
if (!this.internalEventPreHandler(event, 1)) { if (!this.internalEventPreHandler(event, 1)) {
return false; return false;
} }
const position: any = (this.constructor as typeof ClickDetector).extractPointerPosition(event); const position = this.constructor as typeof ClickDetector).extractPointerPosition(event);
if (event instanceof MouseEvent) { if (event instanceof MouseEvent) {
const isRightClick: any = event.button === 2; const isRightClick = event.button === 2;
if (isRightClick) { if (isRightClick) {
// Ignore right clicks // Ignore right clicks
this.rightClick.dispatch(position, event); this.rightClick.dispatch(position, event);
@ -262,20 +262,20 @@ export class ClickDetector {
/** /**
* Internal pointer move handler * Internal pointer move handler
*/ */
internalOnPointerMove(event: TouchEvent | MouseEvent): any { internalOnPointerMove(event: TouchEvent | MouseEvent) {
if (!this.internalEventPreHandler(event, 1)) { if (!this.internalEventPreHandler(event, 1)) {
return false; return false;
} }
this.touchmove.dispatch(event); this.touchmove.dispatch(event);
const pos: any = (this.constructor as typeof ClickDetector).extractPointerPosition(event); const pos = this.constructor as typeof ClickDetector).extractPointerPosition(event);
this.touchmoveSimple.dispatch(pos.x, pos.y); this.touchmoveSimple.dispatch(pos.x, pos.y);
return false; return false;
} }
/** /**
* Internal pointer end handler * Internal pointer end handler
*/ */
internalOnPointerEnd(event: TouchEvent | MouseEvent): any { internalOnPointerEnd(event: TouchEvent | MouseEvent) {
window.focus(); window.focus();
if (!this.internalEventPreHandler(event, 0)) { if (!this.internalEventPreHandler(event, 0)) {
return false; return false;
@ -285,25 +285,25 @@ export class ClickDetector {
return false; return false;
} }
if (event instanceof MouseEvent) { if (event instanceof MouseEvent) {
const isRightClick: any = event.button === 2; const isRightClick = event.button === 2;
if (isRightClick) { if (isRightClick) {
return; return;
} }
} }
const index: any = ongoingClickDetectors.indexOf(this); const index = ongoingClickDetectors.indexOf(this);
if (index < 0) { if (index < 0) {
logger.warn("Got pointer end but click detector is not in pressed state"); logger.warn("Got pointer end but click detector is not in pressed state");
} }
else { else {
fastArrayDelete(ongoingClickDetectors, index); fastArrayDelete(ongoingClickDetectors, index);
} }
let dispatchClick: any = false; let dispatchClick = false;
let dispatchClickPos: any = null; let dispatchClickPos = null;
// Check for correct down position, otherwise must have pinched or so // Check for correct down position, otherwise must have pinched or so
if (this.clickDownPosition) { if (this.clickDownPosition) {
const pos: any = (this.constructor as typeof ClickDetector).extractPointerPosition(event); const pos = this.constructor as typeof ClickDetector).extractPointerPosition(event);
const distance: any = pos.distance(this.clickDownPosition); const distance = pos.distance(this.clickDownPosition);
if (!IS_MOBILE || distance <= this.maxDistance) { if (!IS_MOBILE || distance <= this.maxDistance) {
dispatchClick = true; dispatchClick = true;
dispatchClickPos = pos; dispatchClickPos = pos;
@ -323,8 +323,8 @@ export class ClickDetector {
this.touchend.dispatch(event); this.touchend.dispatch(event);
this.touchendSimple.dispatch(); this.touchendSimple.dispatch();
if (dispatchClick) { if (dispatchClick) {
const detectors: any = ongoingClickDetectors.slice(); const detectors = ongoingClickDetectors.slice();
for (let i: any = 0; i < detectors.length; ++i) { for (let i = 0; i < detectors.length; ++i) {
detectors[i].cancelOngoingEvents(); detectors[i].cancelOngoingEvents();
} }
this.click.dispatch(dispatchClickPos, event); this.click.dispatch(dispatchClickPos, event);
@ -335,7 +335,7 @@ export class ClickDetector {
/** /**
* Internal touch cancel handler * Internal touch cancel handler
*/ */
internalOnTouchCancel(event: TouchEvent | MouseEvent): any { internalOnTouchCancel(event: TouchEvent | MouseEvent) {
if (!this.internalEventPreHandler(event, 0)) { if (!this.internalEventPreHandler(event, 0)) {
return false; return false;
} }

View File

@ -1,14 +1,14 @@
/* typehints:start */ /* typehints:start */
import type { Application } from "../application"; import type { Application } from "../application";
/* typehints:end */ /* typehints:end */
export const IS_DEBUG: any = G_IS_DEV && export const IS_DEBUG = G_IS_DEV &&
typeof window !== "undefined" && typeof window !== "undefined" &&
window.location.port === "3005" && window.location.port === "3005" &&
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) && (window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
window.location.search.indexOf("nodebug") < 0; window.location.search.indexOf("nodebug") < 0;
export const SUPPORT_TOUCH: any = false; export const SUPPORT_TOUCH = false;
const smoothCanvas: any = true; const smoothCanvas = true;
export const THIRDPARTY_URLS: any = { export const THIRDPARTY_URLS = {
discord: "https://discord.gg/HN7EVzV", discord: "https://discord.gg/HN7EVzV",
github: "https://github.com/tobspr-games/shapez.io", github: "https://github.com/tobspr-games/shapez.io",
reddit: "https://www.reddit.com/r/shapezio", reddit: "https://www.reddit.com/r/shapezio",
@ -25,13 +25,13 @@ export const THIRDPARTY_URLS: any = {
}, },
modBrowser: "https://shapez.mod.io/", modBrowser: "https://shapez.mod.io/",
}; };
export function openStandaloneLink(app: Application, campaign: string): any { export function openStandaloneLink(app: Application, campaign: string) {
const discount: any = globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : ""; const discount = globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : "";
const event: any = campaign + discount; const event = campaign + discount;
app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneCampaignLink.replace("$campaign", event)); app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneCampaignLink.replace("$campaign", event));
app.gameAnalytics.noteMinor("g.stdlink." + event); app.gameAnalytics.noteMinor("g.stdlink." + event);
} }
export const globalConfig: any = { export const globalConfig = {
// Size of a single tile in Pixels. // Size of a single tile in Pixels.
// NOTICE: Update webpack.production.config too! // NOTICE: Update webpack.production.config too!
tileSize: 32, tileSize: 32,
@ -106,7 +106,7 @@ export const globalConfig: any = {
analyticsApiKey: "baf6a50f0cc7dfdec5a0e21c88a1c69a4b34bc4a", analyticsApiKey: "baf6a50f0cc7dfdec5a0e21c88a1c69a4b34bc4a",
}, },
}; };
export const IS_MOBILE: any = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); export const IS_MOBILE = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
// Automatic calculations // Automatic calculations
globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5; globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5;
globalConfig.mapChunkWorldSize = globalConfig.mapChunkSize * globalConfig.tileSize; globalConfig.mapChunkWorldSize = globalConfig.mapChunkSize * globalConfig.tileSize;

View File

@ -33,8 +33,8 @@ export function smoothenDpi(dpi: number): number {
/** /**
* Prepares a context for hihg dpi rendering * Prepares a context for hihg dpi rendering
*/ */
export function prepareHighDPIContext(context: CanvasRenderingContext2D, smooth: any = true): any { export function prepareHighDPIContext(context: CanvasRenderingContext2D, smooth = true) {
const dpi: any = getDeviceDPI(); const dpi = getDeviceDPI();
context.scale(dpi, dpi); context.scale(dpi, dpi);
if (smooth) { if (smooth) {
context.imageSmoothingEnabled = true; context.imageSmoothingEnabled = true;
@ -50,12 +50,12 @@ export function prepareHighDPIContext(context: CanvasRenderingContext2D, smooth:
/** /**
* Resizes a high dpi canvas * Resizes a high dpi canvas
*/ */
export function resizeHighDPICanvas(canvas: HTMLCanvasElement, w: number, h: number, smooth: any = true): any { export function resizeHighDPICanvas(canvas: HTMLCanvasElement, w: number, h: number, smooth = true) {
const dpi: any = getDeviceDPI(); const dpi = getDeviceDPI();
const wNumber: any = Math.floor(w); const wNumber = Math.floor(w);
const hNumber: any = Math.floor(h); const hNumber = Math.floor(h);
const targetW: any = Math.floor(wNumber * dpi); const targetW = Math.floor(wNumber * dpi);
const targetH: any = Math.floor(hNumber * dpi); const targetH = Math.floor(hNumber * dpi);
if (targetW !== canvas.width || targetH !== canvas.height) { if (targetW !== canvas.width || targetH !== canvas.height) {
// console.log("Resize Canvas from", canvas.width, canvas.height, "to", targetW, targetH) // console.log("Resize Canvas from", canvas.width, canvas.height, "to", targetW, targetH)
canvas.width = targetW; canvas.width = targetW;
@ -68,9 +68,9 @@ export function resizeHighDPICanvas(canvas: HTMLCanvasElement, w: number, h: num
/** /**
* Resizes a canvas * Resizes a canvas
*/ */
export function resizeCanvas(canvas: HTMLCanvasElement, w: number, h: number, setStyle: any = true): any { export function resizeCanvas(canvas: HTMLCanvasElement, w: number, h: number, setStyle = true) {
const actualW: any = Math.ceil(w); const actualW = Math.ceil(w);
const actualH: any = Math.ceil(h); const actualH = Math.ceil(h);
if (actualW !== canvas.width || actualH !== canvas.height) { if (actualW !== canvas.width || actualH !== canvas.height) {
canvas.width = actualW; canvas.width = actualW;
canvas.height = actualH; canvas.height = actualH;
@ -84,9 +84,9 @@ export function resizeCanvas(canvas: HTMLCanvasElement, w: number, h: number, se
/** /**
* Resizes a canvas and makes sure its cleared * Resizes a canvas and makes sure its cleared
*/ */
export function resizeCanvasAndClear(canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, w: number, h: number): any { export function resizeCanvasAndClear(canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, w: number, h: number) {
const actualW: any = Math.ceil(w); const actualW = Math.ceil(w);
const actualH: any = Math.ceil(h); const actualH = Math.ceil(h);
if (actualW !== canvas.width || actualH !== canvas.height) { if (actualW !== canvas.width || actualH !== canvas.height) {
canvas.width = actualW; canvas.width = actualW;
canvas.height = actualH; canvas.height = actualH;

View File

@ -4,9 +4,9 @@ export type DrawParameters = import("./draw_parameters").DrawParameters;
import { globalConfig } from "./config"; import { globalConfig } from "./config";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { Rectangle } from "./rectangle"; import { Rectangle } from "./rectangle";
const logger: any = createLogger("draw_utils"); const logger = createLogger("draw_utils");
export function initDrawUtils(): any { export function initDrawUtils() {
CanvasRenderingContext2D.prototype.beginRoundedRect = function (x: any, y: any, w: any, h: any, r: any): any { CanvasRenderingContext2D.prototype.beginRoundedRect = function (x, y, w, h, r) {
this.beginPath(); this.beginPath();
if (r < 0.05) { if (r < 0.05) {
this.rect(x, y, w, h); this.rect(x, y, w, h);
@ -24,7 +24,7 @@ export function initDrawUtils(): any {
this.arcTo(x, y + h, x, y, r); this.arcTo(x, y + h, x, y, r);
this.arcTo(x, y, x + w, y, r); this.arcTo(x, y, x + w, y, r);
}; };
CanvasRenderingContext2D.prototype.beginCircle = function (x: any, y: any, r: any): any { CanvasRenderingContext2D.prototype.beginCircle = function (x, y, r) {
this.beginPath(); this.beginPath();
if (r < 0.05) { if (r < 0.05) {
this.rect(x, y, 1, 1); this.rect(x, y, 1, 1);
@ -42,7 +42,7 @@ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offse
size: number; size: number;
offsetX: number=; offsetX: number=;
offsetY: number=; offsetY: number=;
}): any { }) {
if (angle === 0) { if (angle === 0) {
sprite.drawCachedCentered(parameters, x + offsetX, y + offsetY, size); sprite.drawCachedCentered(parameters, x + offsetX, y + offsetY, size);
return; return;
@ -53,7 +53,7 @@ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offse
parameters.context.rotate(-angle); parameters.context.rotate(-angle);
parameters.context.translate(-x, -y); parameters.context.translate(-x, -y);
} }
let warningsShown: any = 0; let warningsShown = 0;
/** /**
* Draws a sprite with clipping * Draws a sprite with clipping
*/ */
@ -66,9 +66,9 @@ export function drawSpriteClipped({ parameters, sprite, x, y, w, h, originalW, o
h: number; h: number;
originalW: number; originalW: number;
originalH: number; originalH: number;
}): any { }) {
const rect: any = new Rectangle(x, y, w, h); const rect = new Rectangle(x, y, w, h);
const intersection: any = rect.getIntersection(parameters.visibleRect); const intersection = rect.getIntersection(parameters.visibleRect);
if (!intersection) { if (!intersection) {
// Clipped // Clipped
if (++warningsShown % 200 === 1) { if (++warningsShown % 200 === 1) {

View File

@ -4,25 +4,25 @@ export class ExplainedResult {
constructor(result = true, reason = null, additionalProps = {}) { constructor(result = true, reason = null, additionalProps = {}) {
// Copy additional props // Copy additional props
for (const key: any in additionalProps) { for (const key in additionalProps) {
this[key] = additionalProps[key]; this[key] = additionalProps[key];
} }
} }
isGood(): any { isGood() {
return !!this.result; return !!this.result;
} }
isBad(): any { isBad() {
return !this.result; return !this.result;
} }
static good(): any { static good() {
return new ExplainedResult(true); return new ExplainedResult(true);
} }
static bad(reason: any, additionalProps: any): any { static bad(reason, additionalProps) {
return new ExplainedResult(false, reason, additionalProps); return new ExplainedResult(false, reason, additionalProps);
} }
static requireAll(...args: any): any { static requireAll(...args) {
for (let i: any = 0; i < args.length; ++i) { for (let i = 0; i < args.length; ++i) {
const subResult: any = args[i].call(); const subResult = args[i].call();
if (!subResult.isGood()) { if (!subResult.isGood()) {
return subResult; return subResult;
} }

View File

@ -1,5 +1,5 @@
import { createLogger } from "./logging"; import { createLogger } from "./logging";
const logger: any = createLogger("factory"); const logger = createLogger("factory");
// simple factory pattern // simple factory pattern
export class Factory { export class Factory {
public id = id; public id = id;
@ -9,12 +9,12 @@ export class Factory {
constructor(id) { constructor(id) {
} }
getId(): any { getId() {
return this.id; return this.id;
} }
register(entry: any): any { register(entry) {
// Extract id // Extract id
const id: any = entry.getId(); const id = entry.getId();
assert(id, "Factory: Invalid id for class: " + entry); assert(id, "Factory: Invalid id for class: " + entry);
// Check duplicates // Check duplicates
assert(!this.idToEntry[id], "Duplicate factory entry for " + id); assert(!this.idToEntry[id], "Duplicate factory entry for " + id);
@ -35,7 +35,7 @@ export class Factory {
* {} * {}
*/ */
findById(id: string): object { findById(id: string): object {
const entry: any = this.idToEntry[id]; const entry = this.idToEntry[id];
if (!entry) { if (!entry) {
logger.error("Object with id", id, "is not registered on factory", this.id, "!"); logger.error("Object with id", id, "is not registered on factory", this.id, "!");
assert(false, "Factory: Object with id '" + id + "' is not registered!"); assert(false, "Factory: Object with id '" + id + "' is not registered!");

View File

@ -9,7 +9,7 @@ import { InputReceiver } from "./input_receiver";
import { waitNextFrame } from "./utils"; import { waitNextFrame } from "./utils";
import { RequestChannel } from "./request_channel"; import { RequestChannel } from "./request_channel";
import { MUSIC } from "../platform/sound"; import { MUSIC } from "../platform/sound";
const logger: any = createLogger("game_state"); const logger = createLogger("game_state");
/** /**
* Basic state of the game state machine. This is the base of the whole game * Basic state of the game state machine. This is the base of the whole game
*/ */
@ -46,7 +46,7 @@ export class GameState {
/** /**
* Transfers to a new state * Transfers to a new state
*/ */
moveToState(stateKey: string, payload: any = {}, skipFadeOut: any = false): any { moveToState(stateKey: string, payload = {}, skipFadeOut = false) {
if (this.fadingOut) { if (this.fadingOut) {
logger.warn("Skipping move to '" + stateKey + "' since already fading out"); logger.warn("Skipping move to '" + stateKey + "' since already fading out");
return; return;
@ -54,13 +54,13 @@ export class GameState {
// Clean up event listeners // Clean up event listeners
this.internalCleanUpClickDetectors(); this.internalCleanUpClickDetectors();
// Fading // Fading
const fadeTime: any = this.internalGetFadeInOutTime(); const fadeTime = this.internalGetFadeInOutTime();
const doFade: any = !skipFadeOut && this.getHasFadeOut() && fadeTime !== 0; const doFade = !skipFadeOut && this.getHasFadeOut() && fadeTime !== 0;
logger.log("Moving to", stateKey, "(fading=", doFade, ")"); logger.log("Moving to", stateKey, "(fading=", doFade, ")");
if (doFade) { if (doFade) {
this.htmlElement.classList.remove("arrived"); this.htmlElement.classList.remove("arrived");
this.fadingOut = true; this.fadingOut = true;
setTimeout((): any => { setTimeout(() => {
this.stateManager.moveToState(stateKey, payload); this.stateManager.moveToState(stateKey, payload);
}, fadeTime); }, fadeTime);
} }
@ -72,8 +72,8 @@ export class GameState {
* Tracks clicks on a given element and calls the given callback *on this state*. * Tracks clicks on a given element and calls the given callback *on this state*.
* If you want to call another function wrap it inside a lambda. * If you want to call another function wrap it inside a lambda.
*/ */
trackClicks(element: Element, handler: function():void, args: import("./click_detector").ClickDetectorConstructorArgs= = {}): any { trackClicks(element: Element, handler: function():void, args: import("./click_detector").ClickDetectorConstructorArgs= = {}) {
const detector: any = new ClickDetector(element, args); const detector = new ClickDetector(element, args);
detector.click.add(handler, this); detector.click.add(handler, this);
if (G_IS_DEV) { if (G_IS_DEV) {
// Append a source so we can check where the click detector is from // Append a source so we can check where the click detector is from
@ -85,43 +85,43 @@ export class GameState {
/** /**
* Cancels all promises on the api as well as our async channel * Cancels all promises on the api as well as our async channel
*/ */
cancelAllAsyncOperations(): any { cancelAllAsyncOperations() {
this.asyncChannel.cancelAll(); this.asyncChannel.cancelAll();
} }
//// CALLBACKS //// //// CALLBACKS ////
/** /**
* Callback when entering the state, to be overriddemn * Callback when entering the state, to be overriddemn
*/ */
onEnter(payload: any): any { } onEnter(payload: any) { }
/** /**
* Callback when leaving the state * Callback when leaving the state
*/ */
onLeave(): any { } onLeave() { }
/** /**
* Callback when the app got paused (on android, this means in background) * Callback when the app got paused (on android, this means in background)
*/ */
onAppPause(): any { } onAppPause() { }
/** /**
* Callback when the app got resumed (on android, this means in foreground again) * Callback when the app got resumed (on android, this means in foreground again)
*/ */
onAppResume(): any { } onAppResume() { }
/** /**
* Render callback * Render callback
*/ */
onRender(dt: number): any { } onRender(dt: number) { }
/** /**
* Background tick callback, called while the game is inactiev * Background tick callback, called while the game is inactiev
*/ */
onBackgroundTick(dt: number): any { } onBackgroundTick(dt: number) { }
/** /**
* Called when the screen resized * Called when the screen resized
*/ */
onResized(w: number, h: number): any { } onResized(w: number, h: number) { }
/** /**
* Internal backbutton handler, called when the hardware back button is pressed or * Internal backbutton handler, called when the hardware back button is pressed or
* the escape key is pressed * the escape key is pressed
*/ */
onBackButton(): any { } onBackButton() { }
//// INTERFACE //// //// INTERFACE ////
/** /**
* Should return how many mulliseconds to fade in / out the state. Not recommended to override! * Should return how many mulliseconds to fade in / out the state. Not recommended to override!
@ -169,7 +169,7 @@ export class GameState {
* Returns if the state has an unload confirmation, this is the * Returns if the state has an unload confirmation, this is the
* "Are you sure you want to leave the page" message. * "Are you sure you want to leave the page" message.
*/ */
getHasUnloadConfirmation(): any { getHasUnloadConfirmation() {
return false; return false;
} }
/** /**
@ -198,7 +198,7 @@ export class GameState {
/** /**
* Internal callback from the manager. Do not override! * Internal callback from the manager. Do not override!
*/ */
internalRegisterCallback(stateManager: StateManager, app: any): any { internalRegisterCallback(stateManager: StateManager, app) {
assert(stateManager, "No state manager"); assert(stateManager, "No state manager");
assert(app, "No app"); assert(app, "No app");
this.stateManager = stateManager; this.stateManager = stateManager;
@ -207,13 +207,13 @@ export class GameState {
/** /**
* Internal callback when entering the state. Do not override! * Internal callback when entering the state. Do not override!
*/ */
internalEnterCallback(payload: any, callCallback: boolean = true): any { internalEnterCallback(payload: any, callCallback: boolean = true) {
logSection(this.key, "#26a69a"); logSection(this.key, "#26a69a");
this.app.inputMgr.pushReciever(this.inputReciever); this.app.inputMgr.pushReciever(this.inputReciever);
this.htmlElement = this.getDivElement(); this.htmlElement = this.getDivElement();
this.htmlElement.classList.add("active"); this.htmlElement.classList.add("active");
// Apply classes in the next frame so the css transition keeps up // Apply classes in the next frame so the css transition keeps up
waitNextFrame().then((): any => { waitNextFrame().then(() => {
if (this.htmlElement) { if (this.htmlElement) {
this.htmlElement.classList.remove("fadingOut"); this.htmlElement.classList.remove("fadingOut");
this.htmlElement.classList.remove("fadingIn"); this.htmlElement.classList.remove("fadingIn");
@ -227,7 +227,7 @@ export class GameState {
/** /**
* Internal callback when the state is left. Do not override! * Internal callback when the state is left. Do not override!
*/ */
internalLeaveCallback(): any { internalLeaveCallback() {
this.onLeave(); this.onLeave();
this.htmlElement.classList.remove("active"); this.htmlElement.classList.remove("active");
this.app.inputMgr.popReciever(this.inputReciever); this.app.inputMgr.popReciever(this.inputReciever);
@ -237,21 +237,21 @@ export class GameState {
/** /**
* Internal app pause callback * Internal app pause callback
*/ */
internalOnAppPauseCallback(): any { internalOnAppPauseCallback() {
this.onAppPause(); this.onAppPause();
} }
/** /**
* Internal app resume callback * Internal app resume callback
*/ */
internalOnAppResumeCallback(): any { internalOnAppResumeCallback() {
this.onAppResume(); this.onAppResume();
} }
/** /**
* Cleans up all click detectors * Cleans up all click detectors
*/ */
internalCleanUpClickDetectors(): any { internalCleanUpClickDetectors() {
if (this.clickDetectors) { if (this.clickDetectors) {
for (let i: any = 0; i < this.clickDetectors.length; ++i) { for (let i = 0; i < this.clickDetectors.length; ++i) {
this.clickDetectors[i].cleanup(); this.clickDetectors[i].cleanup();
} }
this.clickDetectors = []; this.clickDetectors = [];

View File

@ -17,6 +17,6 @@ export let gItemRegistry: FactoryTemplate<BaseItem> = new Factory("item");
// Helpers // Helpers
export function initBuildingsByCategory(buildings: { export function initBuildingsByCategory(buildings: {
[idx: string]: Array<Class<MetaBuilding>>; [idx: string]: Array<Class<MetaBuilding>>;
}): any { }) {
gBuildingsByCategory = buildings; gBuildingsByCategory = buildings;
} }

View File

@ -6,11 +6,11 @@ import type { Application } from "../application";
* It would be nicer to have no globals, but this is the only one. I promise! * It would be nicer to have no globals, but this is the only one. I promise!
*/ */
export let GLOBAL_APP: Application = null; export let GLOBAL_APP: Application = null;
export function setGlobalApp(app: Application): any { export function setGlobalApp(app: Application) {
assert(!GLOBAL_APP, "Create application twice!"); assert(!GLOBAL_APP, "Create application twice!");
GLOBAL_APP = app; GLOBAL_APP = app;
} }
export const BUILD_OPTIONS: any = { export const BUILD_OPTIONS = {
HAVE_ASSERT: G_HAVE_ASSERT, HAVE_ASSERT: G_HAVE_ASSERT,
APP_ENVIRONMENT: G_APP_ENVIRONMENT, APP_ENVIRONMENT: G_APP_ENVIRONMENT,
IS_DEV: G_IS_DEV, IS_DEV: G_IS_DEV,

View File

@ -5,7 +5,7 @@ import type { InputReceiver } from "./input_receiver";
import { Signal, STOP_PROPAGATION } from "./signal"; import { Signal, STOP_PROPAGATION } from "./signal";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { arrayDeleteValue, fastArrayDeleteValue } from "./utils"; import { arrayDeleteValue, fastArrayDeleteValue } from "./utils";
const logger: any = createLogger("input_distributor"); const logger = createLogger("input_distributor");
export class InputDistributor { export class InputDistributor {
public app = app; public app = app;
public recieverStack: Array<InputReceiver> = []; public recieverStack: Array<InputReceiver> = [];
@ -18,16 +18,16 @@ export class InputDistributor {
/** /**
* Attaches a new filter which can filter and reject events * Attaches a new filter which can filter and reject events
*/ */
installFilter(filter: function(: boolean):boolean): any { installFilter(filter: function(: boolean):boolean) {
this.filters.push(filter); this.filters.push(filter);
} }
/** /**
* Removes an attached filter * Removes an attached filter
*/ */
dismountFilter(filter: function(: boolean):boolean): any { dismountFilter(filter: function(: boolean):boolean) {
fastArrayDeleteValue(this.filters, filter); fastArrayDeleteValue(this.filters, filter);
} }
pushReciever(reciever: InputReceiver): any { pushReciever(reciever: InputReceiver) {
if (this.isRecieverAttached(reciever)) { if (this.isRecieverAttached(reciever)) {
assert(false, "Can not add reciever " + reciever.context + " twice"); assert(false, "Can not add reciever " + reciever.context + " twice");
logger.error("Can not add reciever", reciever.context, "twice"); logger.error("Can not add reciever", reciever.context, "twice");
@ -35,48 +35,48 @@ export class InputDistributor {
} }
this.recieverStack.push(reciever); this.recieverStack.push(reciever);
if (this.recieverStack.length > 10) { if (this.recieverStack.length > 10) {
logger.error("Reciever stack is huge, probably some dead receivers arround:", this.recieverStack.map((x: any): any => x.context)); logger.error("Reciever stack is huge, probably some dead receivers arround:", this.recieverStack.map(x => x.context));
} }
} }
popReciever(reciever: InputReceiver): any { popReciever(reciever: InputReceiver) {
if (this.recieverStack.indexOf(reciever) < 0) { if (this.recieverStack.indexOf(reciever) < 0) {
assert(false, "Can not pop reciever " + reciever.context + " since its not contained"); assert(false, "Can not pop reciever " + reciever.context + " since its not contained");
logger.error("Can not pop reciever", reciever.context, "since its not contained"); logger.error("Can not pop reciever", reciever.context, "since its not contained");
return; return;
} }
if (this.recieverStack[this.recieverStack.length - 1] !== reciever) { if (this.recieverStack[this.recieverStack.length - 1] !== reciever) {
logger.warn("Popping reciever", reciever.context, "which is not on top of the stack. Stack is: ", this.recieverStack.map((x: any): any => x.context)); logger.warn("Popping reciever", reciever.context, "which is not on top of the stack. Stack is: ", this.recieverStack.map(x => x.context));
} }
arrayDeleteValue(this.recieverStack, reciever); arrayDeleteValue(this.recieverStack, reciever);
} }
isRecieverAttached(reciever: InputReceiver): any { isRecieverAttached(reciever: InputReceiver) {
return this.recieverStack.indexOf(reciever) >= 0; return this.recieverStack.indexOf(reciever) >= 0;
} }
isRecieverOnTop(reciever: InputReceiver): any { isRecieverOnTop(reciever: InputReceiver) {
return (this.isRecieverAttached(reciever) && return (this.isRecieverAttached(reciever) &&
this.recieverStack[this.recieverStack.length - 1] === reciever); this.recieverStack[this.recieverStack.length - 1] === reciever);
} }
makeSureAttachedAndOnTop(reciever: InputReceiver): any { makeSureAttachedAndOnTop(reciever: InputReceiver) {
this.makeSureDetached(reciever); this.makeSureDetached(reciever);
this.pushReciever(reciever); this.pushReciever(reciever);
} }
makeSureDetached(reciever: InputReceiver): any { makeSureDetached(reciever: InputReceiver) {
if (this.isRecieverAttached(reciever)) { if (this.isRecieverAttached(reciever)) {
arrayDeleteValue(this.recieverStack, reciever); arrayDeleteValue(this.recieverStack, reciever);
} }
} }
destroyReceiver(reciever: InputReceiver): any { destroyReceiver(reciever: InputReceiver) {
this.makeSureDetached(reciever); this.makeSureDetached(reciever);
reciever.cleanup(); reciever.cleanup();
} }
// Internal // Internal
getTopReciever(): any { getTopReciever() {
if (this.recieverStack.length > 0) { if (this.recieverStack.length > 0) {
return this.recieverStack[this.recieverStack.length - 1]; return this.recieverStack[this.recieverStack.length - 1];
} }
return null; return null;
} }
bindToEvents(): any { bindToEvents() {
window.addEventListener("popstate", this.handleBackButton.bind(this), false); window.addEventListener("popstate", this.handleBackButton.bind(this), false);
document.addEventListener("backbutton", this.handleBackButton.bind(this), false); document.addEventListener("backbutton", this.handleBackButton.bind(this), false);
window.addEventListener("keydown", this.handleKeyMouseDown.bind(this)); window.addEventListener("keydown", this.handleKeyMouseDown.bind(this));
@ -86,23 +86,23 @@ export class InputDistributor {
window.addEventListener("blur", this.handleBlur.bind(this)); window.addEventListener("blur", this.handleBlur.bind(this));
document.addEventListener("paste", this.handlePaste.bind(this)); document.addEventListener("paste", this.handlePaste.bind(this));
} }
forwardToReceiver(eventId: any, payload: any = null): any { forwardToReceiver(eventId, payload = null) {
// Check filters // Check filters
for (let i: any = 0; i < this.filters.length; ++i) { for (let i = 0; i < this.filters.length; ++i) {
if (!this.filters[i](eventId)) { if (!this.filters[i](eventId)) {
return STOP_PROPAGATION; return STOP_PROPAGATION;
} }
} }
const reciever: any = this.getTopReciever(); const reciever = this.getTopReciever();
if (!reciever) { if (!reciever) {
logger.warn("Dismissing event because not reciever was found:", eventId); logger.warn("Dismissing event because not reciever was found:", eventId);
return; return;
} }
const signal: any = reciever[eventId]; const signal = reciever[eventId];
assert(signal instanceof Signal, "Not a valid event id"); assert(signal instanceof Signal, "Not a valid event id");
return signal.dispatch(payload); return signal.dispatch(payload);
} }
handleBackButton(event: Event): any { handleBackButton(event: Event) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
this.forwardToReceiver("backButton"); this.forwardToReceiver("backButton");
@ -110,16 +110,16 @@ export class InputDistributor {
/** /**
* Handles when the page got blurred * Handles when the page got blurred
*/ */
handleBlur(): any { handleBlur() {
this.forwardToReceiver("pageBlur", {}); this.forwardToReceiver("pageBlur", {});
this.keysDown.clear(); this.keysDown.clear();
} }
handlePaste(ev: any): any { handlePaste(ev) {
this.forwardToReceiver("paste", ev); this.forwardToReceiver("paste", ev);
} }
handleKeyMouseDown(event: KeyboardEvent | MouseEvent): any { handleKeyMouseDown(event: KeyboardEvent | MouseEvent) {
const keyCode: any = event instanceof MouseEvent ? event.button + 1 : event.keyCode; const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
if (keyCode === 4 || // MB4 if (keyCode === 4 || // MB4
keyCode === 5 || // MB5 keyCode === 5 || // MB5
keyCode === 9 || // TAB keyCode === 9 || // TAB
@ -130,7 +130,7 @@ export class InputDistributor {
) { ) {
event.preventDefault(); event.preventDefault();
} }
const isInitial: any = !this.keysDown.has(keyCode); const isInitial = !this.keysDown.has(keyCode);
this.keysDown.add(keyCode); this.keysDown.add(keyCode);
if (this.forwardToReceiver("keydown", { if (this.forwardToReceiver("keydown", {
keyCode: keyCode, keyCode: keyCode,
@ -149,8 +149,8 @@ export class InputDistributor {
return this.forwardToReceiver("backButton"); return this.forwardToReceiver("backButton");
} }
} }
handleKeyMouseUp(event: KeyboardEvent | MouseEvent): any { handleKeyMouseUp(event: KeyboardEvent | MouseEvent) {
const keyCode: any = event instanceof MouseEvent ? event.button + 1 : event.keyCode; const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
this.keysDown.delete(keyCode); this.keysDown.delete(keyCode);
this.forwardToReceiver("keyup", { this.forwardToReceiver("keyup", {
keyCode: keyCode, keyCode: keyCode,

View File

@ -10,7 +10,7 @@ export class InputReceiver {
constructor(context = "unknown") { constructor(context = "unknown") {
} }
cleanup(): any { cleanup() {
this.backButton.removeAll(); this.backButton.removeAll();
this.keydown.removeAll(); this.keydown.removeAll();
this.keyup.removeAll(); this.keyup.removeAll();

View File

@ -5,8 +5,8 @@ import { createLogger } from "./logging";
export type Application = import("../application").Application; export type Application = import("../application").Application;
export type AtlasDefinition = import("./atlas_definitions").AtlasDefinition; export type AtlasDefinition = import("./atlas_definitions").AtlasDefinition;
const logger: any = createLogger("loader"); const logger = createLogger("loader");
const missingSpriteIds: any = {}; const missingSpriteIds = {};
class LoaderImpl { class LoaderImpl {
public app = null; public app = null;
public sprites: Map<string, BaseSprite> = new Map(); public sprites: Map<string, BaseSprite> = new Map();
@ -14,7 +14,7 @@ class LoaderImpl {
constructor() { constructor() {
} }
linkAppAfterBoot(app: Application): any { linkAppAfterBoot(app: Application) {
this.app = app; this.app = app;
this.makeSpriteNotFoundCanvas(); this.makeSpriteNotFoundCanvas();
} }
@ -23,7 +23,7 @@ class LoaderImpl {
* {} * {}
*/ */
getSpriteInternal(key: string): BaseSprite { getSpriteInternal(key: string): BaseSprite {
const sprite: any = this.sprites.get(key); const sprite = this.sprites.get(key);
if (!sprite) { if (!sprite) {
if (!missingSpriteIds[key]) { if (!missingSpriteIds[key]) {
// Only show error once // Only show error once
@ -39,7 +39,7 @@ class LoaderImpl {
* {} * {}
*/ */
getSprite(key: string): AtlasSprite { getSprite(key: string): AtlasSprite {
const sprite: any = this.getSpriteInternal(key); const sprite = this.getSpriteInternal(key);
assert(sprite instanceof AtlasSprite || sprite === this.spriteNotFoundSprite, "Not an atlas sprite"); assert(sprite instanceof AtlasSprite || sprite === this.spriteNotFoundSprite, "Not an atlas sprite");
return sprite as AtlasSprite); return sprite as AtlasSprite);
} }
@ -48,7 +48,7 @@ class LoaderImpl {
* {} * {}
*/ */
getRegularSprite(key: string): RegularSprite { getRegularSprite(key: string): RegularSprite {
const sprite: any = this.getSpriteInternal(key); const sprite = this.getSpriteInternal(key);
assert(sprite instanceof RegularSprite || sprite === this.spriteNotFoundSprite, "Not a regular sprite"); assert(sprite instanceof RegularSprite || sprite === this.spriteNotFoundSprite, "Not a regular sprite");
return sprite as RegularSprite); return sprite as RegularSprite);
} }
@ -58,14 +58,14 @@ class LoaderImpl {
*/ */
internalPreloadImage(key: string, progressHandler: (progress: number) => void): Promise<HTMLImageElement | null> { internalPreloadImage(key: string, progressHandler: (progress: number) => void): Promise<HTMLImageElement | null> {
return this.app.backgroundResourceLoader return this.app.backgroundResourceLoader
.preloadWithProgress("res/" + key, (progress: any): any => { .preloadWithProgress("res/" + key, progress => {
progressHandler(progress); progressHandler(progress);
}) })
.then((url: any): any => { .then(url => {
return new Promise((resolve: any, reject: any): any => { return new Promise((resolve, reject) => {
const image: any = new Image(); const image = new Image();
image.addEventListener("load", (): any => resolve(image)); image.addEventListener("load", () => resolve(image));
image.addEventListener("error", (err: any): any => reject("Failed to load sprite " + key + ": " + err)); image.addEventListener("error", err => reject("Failed to load sprite " + key + ": " + err));
image.src = url; image.src = url;
}); });
}); });
@ -75,7 +75,7 @@ class LoaderImpl {
* {} * {}
*/ */
preloadCSSSprite(key: string, progressHandler: (progress: number) => void): Promise<void> { preloadCSSSprite(key: string, progressHandler: (progress: number) => void): Promise<void> {
return this.internalPreloadImage(key, progressHandler).then((image: any): any => { return this.internalPreloadImage(key, progressHandler).then(image => {
if (key.indexOf("game_misc") >= 0) { if (key.indexOf("game_misc") >= 0) {
// Allow access to regular sprites // Allow access to regular sprites
this.sprites.set(key, new RegularSprite(image, image.width, image.height)); this.sprites.set(key, new RegularSprite(image, image.width, image.height));
@ -88,17 +88,17 @@ class LoaderImpl {
* {} * {}
*/ */
preloadAtlas(atlas: AtlasDefinition, progressHandler: (progress: number) => void): Promise<void> { preloadAtlas(atlas: AtlasDefinition, progressHandler: (progress: number) => void): Promise<void> {
return this.internalPreloadImage(atlas.getFullSourcePath(), progressHandler).then((image: any): any => { return this.internalPreloadImage(atlas.getFullSourcePath(), progressHandler).then(image => {
// @ts-ignore // @ts-ignore
image.label = atlas.sourceFileName; image.label = atlas.sourceFileName;
return this.internalParseAtlas(atlas, image); return this.internalParseAtlas(atlas, image);
}); });
} }
internalParseAtlas({ meta: { scale }, sourceData }: AtlasDefinition, loadedImage: HTMLImageElement): any { internalParseAtlas({ meta: { scale }, sourceData }: AtlasDefinition, loadedImage: HTMLImageElement) {
this.rawImages.push(loadedImage); this.rawImages.push(loadedImage);
for (const spriteName: any in sourceData) { for (const spriteName in sourceData) {
const { frame, sourceSize, spriteSourceSize }: any = sourceData[spriteName]; const { frame, sourceSize, spriteSourceSize } = sourceData[spriteName];
let sprite: any = (this.sprites.get(spriteName) as AtlasSprite); let sprite = this.sprites.get(spriteName) as AtlasSprite);
if (!sprite) { if (!sprite) {
sprite = new AtlasSprite(spriteName); sprite = new AtlasSprite(spriteName);
this.sprites.set(spriteName, sprite); this.sprites.set(spriteName, sprite);
@ -106,7 +106,7 @@ class LoaderImpl {
if (sprite.frozen) { if (sprite.frozen) {
continue; continue;
} }
const link: any = new SpriteAtlasLink({ const link = new SpriteAtlasLink({
packedX: frame.x, packedX: frame.x,
packedY: frame.y, packedY: frame.y,
packedW: frame.w, packedW: frame.w,
@ -123,9 +123,9 @@ class LoaderImpl {
/** /**
* Makes the canvas which shows the question mark, shown when a sprite was not found * Makes the canvas which shows the question mark, shown when a sprite was not found
*/ */
makeSpriteNotFoundCanvas(): any { makeSpriteNotFoundCanvas() {
const dims: any = 128; const dims = 128;
const [canvas, context]: any = makeOffscreenBuffer(dims, dims, { const [canvas, context] = makeOffscreenBuffer(dims, dims, {
smooth: false, smooth: false,
label: "not-found-sprite", label: "not-found-sprite",
}); });
@ -139,8 +139,8 @@ class LoaderImpl {
// TODO: Not sure why this is set here // TODO: Not sure why this is set here
// @ts-ignore // @ts-ignore
canvas.src = "not-found"; canvas.src = "not-found";
const sprite: any = new AtlasSprite("not-found"); const sprite = new AtlasSprite("not-found");
["0.1", "0.25", "0.5", "0.75", "1"].forEach((resolution: any): any => { ["0.1", "0.25", "0.5", "0.75", "1"].forEach(resolution => {
sprite.linksByResolution[resolution] = new SpriteAtlasLink({ sprite.linksByResolution[resolution] = new SpriteAtlasLink({
packedX: 0, packedX: 0,
packedY: 0, packedY: 0,
@ -156,4 +156,4 @@ class LoaderImpl {
this.spriteNotFoundSprite = sprite; this.spriteNotFoundSprite = sprite;
} }
} }
export const Loader: any = new LoaderImpl(); export const Loader = new LoaderImpl();

View File

@ -1,5 +1,5 @@
import { globalConfig } from "./config"; import { globalConfig } from "./config";
const circularJson: any = require("circular-json"); const circularJson = require("circular-json");
/* /*
Logging functions Logging functions
- To be extended - To be extended
@ -12,23 +12,23 @@ class Logger {
constructor(context) { constructor(context) {
} }
debug(...args: any): any { debug(...args) {
globalDebug(this.context, ...args); globalDebug(this.context, ...args);
} }
log(...args: any): any { log(...args) {
globalLog(this.context, ...args); globalLog(this.context, ...args);
} }
warn(...args: any): any { warn(...args) {
globalWarn(this.context, ...args); globalWarn(this.context, ...args);
} }
error(...args: any): any { error(...args) {
globalError(this.context, ...args); globalError(this.context, ...args);
} }
} }
export function createLogger(context: any): any { export function createLogger(context) {
return new Logger(context); return new Logger(context);
} }
function prepareObjectForLogging(obj: any, maxDepth: any = 1): any { function prepareObjectForLogging(obj, maxDepth = 1) {
if (!window.Sentry) { if (!window.Sentry) {
// Not required without sentry // Not required without sentry
return obj; return obj;
@ -36,9 +36,9 @@ function prepareObjectForLogging(obj: any, maxDepth: any = 1): any {
if (typeof obj !== "object" && !Array.isArray(obj)) { if (typeof obj !== "object" && !Array.isArray(obj)) {
return obj; return obj;
} }
const result: any = {}; const result = {};
for (const key: any in obj) { for (const key in obj) {
const val: any = obj[key]; const val = obj[key];
if (typeof val === "object") { if (typeof val === "object") {
if (maxDepth > 0) { if (maxDepth > 0) {
result[key] = prepareObjectForLogging(val, maxDepth - 1); result[key] = prepareObjectForLogging(val, maxDepth - 1);
@ -56,11 +56,11 @@ function prepareObjectForLogging(obj: any, maxDepth: any = 1): any {
/** /**
* Serializes an error * Serializes an error
*/ */
export function serializeError(err: Error | ErrorEvent): any { export function serializeError(err: Error | ErrorEvent) {
if (!err) { if (!err) {
return null; return null;
} }
const result: any = { const result = {
type: err.constructor.name, type: err.constructor.name,
}; };
@ -91,8 +91,8 @@ export function serializeError(err: Error | ErrorEvent): any {
/** /**
* Serializes an event * Serializes an event
*/ */
function serializeEvent(event: Event): any { function serializeEvent(event: Event) {
let result: any = { let result = {
type: "{type.Event:" + typeof event + "}", type: "{type.Event:" + typeof event + "}",
}; };
result.eventType = event.type; result.eventType = event.type;
@ -101,7 +101,7 @@ function serializeEvent(event: Event): any {
/** /**
* Prepares a json payload * Prepares a json payload
*/ */
function preparePayload(key: string, value: any): any { function preparePayload(key: string, value: any) {
if (value instanceof Error || value instanceof ErrorEvent) { if (value instanceof Error || value instanceof ErrorEvent) {
return serializeError(value); return serializeError(value);
} }
@ -116,44 +116,44 @@ function preparePayload(key: string, value: any): any {
/** /**
* Stringifies an object containing circular references and errors * Stringifies an object containing circular references and errors
*/ */
export function stringifyObjectContainingErrors(payload: any): any { export function stringifyObjectContainingErrors(payload: any) {
return circularJson.stringify(payload, preparePayload); return circularJson.stringify(payload, preparePayload);
} }
export function globalDebug(context: any, ...args: any): any { export function globalDebug(context, ...args) {
if (G_IS_DEV) { if (G_IS_DEV) {
logInternal(context, console.log, prepareArgsForLogging(args)); logInternal(context, console.log, prepareArgsForLogging(args));
} }
} }
export function globalLog(context: any, ...args: any): any { export function globalLog(context, ...args) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
logInternal(context, console.log, prepareArgsForLogging(args)); logInternal(context, console.log, prepareArgsForLogging(args));
} }
export function globalWarn(context: any, ...args: any): any { export function globalWarn(context, ...args) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
logInternal(context, console.warn, prepareArgsForLogging(args)); logInternal(context, console.warn, prepareArgsForLogging(args));
} }
export function globalError(context: any, ...args: any): any { export function globalError(context, ...args) {
args = prepareArgsForLogging(args); args = prepareArgsForLogging(args);
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
logInternal(context, console.error, args); logInternal(context, console.error, args);
if (window.Sentry) { if (window.Sentry) {
window.Sentry.withScope((scope: any): any => { window.Sentry.withScope(scope => {
scope.setExtra("args", args); scope.setExtra("args", args);
window.Sentry.captureMessage(internalBuildStringFromArgs(args), "error"); window.Sentry.captureMessage(internalBuildStringFromArgs(args), "error");
}); });
} }
} }
function prepareArgsForLogging(args: any): any { function prepareArgsForLogging(args) {
let result: any = []; let result = [];
for (let i: any = 0; i < args.length; ++i) { for (let i = 0; i < args.length; ++i) {
result.push(prepareObjectForLogging(args[i])); result.push(prepareObjectForLogging(args[i]));
} }
return result; return result;
} }
function internalBuildStringFromArgs(args: Array<any>): any { function internalBuildStringFromArgs(args: Array<any>) {
let result: any = []; let result = [];
for (let i: any = 0; i < args.length; ++i) { for (let i = 0; i < args.length; ++i) {
let arg: any = args[i]; let arg = args[i];
if (typeof arg === "string" || if (typeof arg === "string" ||
typeof arg === "number" || typeof arg === "number" ||
typeof arg === "boolean" || typeof arg === "boolean" ||
@ -170,17 +170,17 @@ function internalBuildStringFromArgs(args: Array<any>): any {
} }
return result.join(" "); return result.join(" ");
} }
export function logSection(name: any, color: any): any { export function logSection(name, color) {
while (name.length <= 14) { while (name.length <= 14) {
name = " " + name + " "; name = " " + name + " ";
} }
name = name.padEnd(19, " "); name = name.padEnd(19, " ");
const lineCss: any = "letter-spacing: -3px; color: " + color + "; font-size: 6px; background: #eee; color: #eee;"; const lineCss = "letter-spacing: -3px; color: " + color + "; font-size: 6px; background: #eee; color: #eee;";
const line: any = "%c----------------------------"; const line = "%c----------------------------";
console.log("\n" + line + " %c" + name + " " + line + "\n", lineCss, "color: " + color, lineCss); console.log("\n" + line + " %c" + name + " " + line + "\n", lineCss, "color: " + color, lineCss);
} }
function extractHandleContext(handle: any): any { function extractHandleContext(handle) {
let context: any = handle || "unknown"; let context = handle || "unknown";
if (handle && handle.constructor && handle.constructor.name) { if (handle && handle.constructor && handle.constructor.name) {
@ -195,11 +195,11 @@ function extractHandleContext(handle: any): any {
} }
return context + ""; return context + "";
} }
function logInternal(handle: any, consoleMethod: any, args: any): any { function logInternal(handle, consoleMethod, args) {
const context: any = extractHandleContext(handle).padEnd(20, " "); const context = extractHandleContext(handle).padEnd(20, " ");
const labelColor: any = handle && handle.LOG_LABEL_COLOR ? handle.LOG_LABEL_COLOR : "#aaa"; const labelColor = handle && handle.LOG_LABEL_COLOR ? handle.LOG_LABEL_COLOR : "#aaa";
if (G_IS_DEV && globalConfig.debug.logTimestamps) { if (G_IS_DEV && globalConfig.debug.logTimestamps) {
const timestamp: any = "⏱ %c" + (Math.floor(performance.now()) + "").padEnd(6, " ") + ""; const timestamp = "⏱ %c" + (Math.floor(performance.now()) + "").padEnd(6, " ") + "";
consoleMethod.call(console, timestamp + " %c" + context, "color: #7f7;", "color: " + labelColor + ";", ...args); consoleMethod.call(console, timestamp + " %c" + context, "color: #7f7;", "color: " + labelColor + ";", ...args);
} }
else { else {

View File

@ -7,45 +7,45 @@
// http://pieroxy.net/blog/pages/lz-string/testing.html // http://pieroxy.net/blog/pages/lz-string/testing.html
// //
// LZ-based compression algorithm, version 1.4.4 // LZ-based compression algorithm, version 1.4.4
const fromCharCode: any = String.fromCharCode; const fromCharCode = String.fromCharCode;
const hasOwnProperty: any = Object.prototype.hasOwnProperty; const hasOwnProperty = Object.prototype.hasOwnProperty;
const keyStrUriSafe: any = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$"; const keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
const baseReverseDic: any = {}; const baseReverseDic = {};
function getBaseValue(alphabet: any, character: any): any { function getBaseValue(alphabet, character) {
if (!baseReverseDic[alphabet]) { if (!baseReverseDic[alphabet]) {
baseReverseDic[alphabet] = {}; baseReverseDic[alphabet] = {};
for (let i: any = 0; i < alphabet.length; i++) { for (let i = 0; i < alphabet.length; i++) {
baseReverseDic[alphabet][alphabet.charAt(i)] = i; baseReverseDic[alphabet][alphabet.charAt(i)] = i;
} }
} }
return baseReverseDic[alphabet][character]; return baseReverseDic[alphabet][character];
} }
//compress into uint8array (UCS-2 big endian format) //compress into uint8array (UCS-2 big endian format)
export function compressU8(uncompressed: any): any { export function compressU8(uncompressed) {
let compressed: any = compress(uncompressed); let compressed = compress(uncompressed);
let buf: any = new Uint8Array(compressed.length * 2); // 2 bytes per character let buf = new Uint8Array(compressed.length * 2); // 2 bytes per character
for (let i: any = 0, TotalLen: any = compressed.length; i < TotalLen; i++) { for (let i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
let current_value: any = compressed.charCodeAt(i); let current_value = compressed.charCodeAt(i);
buf[i * 2] = current_value >>> 8; buf[i * 2] = current_value >>> 8;
buf[i * 2 + 1] = current_value % 256; buf[i * 2 + 1] = current_value % 256;
} }
return buf; return buf;
} }
// Compreses with header // Compreses with header
export function compressU8WHeader(uncompressed: string, header: number): any { export function compressU8WHeader(uncompressed: string, header: number) {
let compressed: any = compress(uncompressed); let compressed = compress(uncompressed);
let buf: any = new Uint8Array(2 + compressed.length * 2); // 2 bytes per character let buf = new Uint8Array(2 + compressed.length * 2); // 2 bytes per character
buf[0] = header >>> 8; buf[0] = header >>> 8;
buf[1] = header % 256; buf[1] = header % 256;
for (let i: any = 0, TotalLen: any = compressed.length; i < TotalLen; i++) { for (let i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
let current_value: any = compressed.charCodeAt(i); let current_value = compressed.charCodeAt(i);
buf[2 + i * 2] = current_value >>> 8; buf[2 + i * 2] = current_value >>> 8;
buf[2 + i * 2 + 1] = current_value % 256; buf[2 + i * 2 + 1] = current_value % 256;
} }
return buf; return buf;
} }
//decompress from uint8array (UCS-2 big endian format) //decompress from uint8array (UCS-2 big endian format)
export function decompressU8WHeader(compressed: Uint8Array): any { export function decompressU8WHeader(compressed: Uint8Array) {
// let buf = new Array(compressed.length / 2); // 2 bytes per character // let buf = new Array(compressed.length / 2); // 2 bytes per character
// for (let i = 0, TotalLen = buf.length; i < TotalLen; i++) { // for (let i = 0, TotalLen = buf.length; i < TotalLen; i++) {
// buf[i] = compressed[i * 2] * 256 + compressed[i * 2 + 1]; // buf[i] = compressed[i * 2] * 256 + compressed[i * 2 + 1];
@ -54,42 +54,42 @@ export function decompressU8WHeader(compressed: Uint8Array): any {
// buf.forEach(function (c) { // buf.forEach(function (c) {
// result.push(fromCharCode(c)); // result.push(fromCharCode(c));
// }); // });
let result: any = []; let result = [];
for (let i: any = 2, n: any = compressed.length; i < n; i += 2) { for (let i = 2, n = compressed.length; i < n; i += 2) {
const code: any = compressed[i] * 256 + compressed[i + 1]; const code = compressed[i] * 256 + compressed[i + 1];
result.push(fromCharCode(code)); result.push(fromCharCode(code));
} }
return decompress(result.join("")); return decompress(result.join(""));
} }
//compress into a string that is already URI encoded //compress into a string that is already URI encoded
export function compressX64(input: any): any { export function compressX64(input) {
if (input == null) if (input == null)
return ""; return "";
return _compress(input, 6, function (a: any): any { return _compress(input, 6, function (a) {
return keyStrUriSafe.charAt(a); return keyStrUriSafe.charAt(a);
}); });
} }
//decompress from an output of compressToEncodedURIComponent //decompress from an output of compressToEncodedURIComponent
export function decompressX64(input: any): any { export function decompressX64(input) {
if (input == null) if (input == null)
return ""; return "";
if (input == "") if (input == "")
return null; return null;
input = input.replace(/ /g, "+"); input = input.replace(/ /g, "+");
return _decompress(input.length, 32, function (index: any): any { return _decompress(input.length, 32, function (index) {
return getBaseValue(keyStrUriSafe, input.charAt(index)); return getBaseValue(keyStrUriSafe, input.charAt(index));
}); });
} }
function compress(uncompressed: any): any { function compress(uncompressed) {
return _compress(uncompressed, 16, function (a: any): any { return _compress(uncompressed, 16, function (a) {
return fromCharCode(a); return fromCharCode(a);
}); });
} }
function _compress(uncompressed: any, bitsPerChar: any, getCharFromInt: any): any { function _compress(uncompressed, bitsPerChar, getCharFromInt) {
if (uncompressed == null) if (uncompressed == null)
return ""; return "";
let i: any, value: any, context_dictionary: any = {}, context_dictionaryToCreate: any = {}, context_c: any = "", context_wc: any = "", context_w: any = "", context_enlargeIn: any = 2, // Compensate for the first entry which should not count let i, value, context_dictionary = {}, context_dictionaryToCreate = {}, context_c = "", context_wc = "", context_w = "", context_enlargeIn = 2, // Compensate for the first entry which should not count
context_dictSize: any = 3, context_numBits: any = 2, context_data: any = [], context_data_val: any = 0, context_data_position: any = 0, ii: any; context_dictSize = 3, context_numBits = 2, context_data = [], context_data_val = 0, context_data_position = 0, ii;
for (ii = 0; ii < uncompressed.length; ii += 1) { for (ii = 0; ii < uncompressed.length; ii += 1) {
context_c = uncompressed.charAt(ii); context_c = uncompressed.charAt(ii);
if (!hasOwnProperty.call(context_dictionary, context_c)) { if (!hasOwnProperty.call(context_dictionary, context_c)) {
@ -300,17 +300,17 @@ function _compress(uncompressed: any, bitsPerChar: any, getCharFromInt: any): an
} }
return context_data.join(""); return context_data.join("");
} }
function decompress(compressed: any): any { function decompress(compressed) {
if (compressed == null) if (compressed == null)
return ""; return "";
if (compressed == "") if (compressed == "")
return null; return null;
return _decompress(compressed.length, 32768, function (index: any): any { return _decompress(compressed.length, 32768, function (index) {
return compressed.charCodeAt(index); return compressed.charCodeAt(index);
}); });
} }
function _decompress(length: any, resetValue: any, getNextValue: any): any { function _decompress(length, resetValue, getNextValue) {
let dictionary: any = [], next: any, enlargeIn: any = 4, dictSize: any = 4, numBits: any = 3, entry: any = "", result: any = [], i: any, w: any, bits: any, resb: any, maxpower: any, power: any, c: any, data: any = { val: getNextValue(0), position: resetValue, index: 1 }; let dictionary = [], next, enlargeIn = 4, dictSize = 4, numBits = 3, entry = "", result = [], i, w, bits, resb, maxpower, power, c, data = { val: getNextValue(0), position: resetValue, index: 1 };
for (i = 0; i < 3; i += 1) { for (i = 0; i < 3; i += 1) {
dictionary[i] = i; dictionary[i] = i;
} }

View File

@ -21,9 +21,9 @@ import { T } from "../translations";
* *
* *************************************************** * ***************************************************
*/ */
const kbEnter: any = 13; const kbEnter = 13;
const kbCancel: any = 27; const kbCancel = 27;
const logger: any = createLogger("dialogs"); const logger = createLogger("dialogs");
/** /**
* Basic text based dialog * Basic text based dialog
*/ */
@ -48,11 +48,11 @@ export class Dialog {
*/ */
constructor({ app, title, contentHTML, buttons, type = "info", closeButton = false }) { constructor({ app, title, contentHTML, buttons, type = "info", closeButton = false }) {
for (let i: any = 0; i < buttons.length; ++i) { for (let i = 0; i < buttons.length; ++i) {
if (G_IS_DEV && globalConfig.debug.disableTimedButtons) { if (G_IS_DEV && globalConfig.debug.disableTimedButtons) {
this.buttonIds[i] = this.buttonIds[i].replace(":timeout", ""); this.buttonIds[i] = this.buttonIds[i].replace(":timeout", "");
} }
const buttonId: any = this.buttonIds[i].split(":")[0]; const buttonId = this.buttonIds[i].split(":")[0];
this.buttonSignals[buttonId] = new Signal(); this.buttonSignals[buttonId] = new Signal();
} }
this.inputReciever.keydown.add(this.handleKeydown, this); this.inputReciever.keydown.add(this.handleKeydown, this);
@ -65,7 +65,7 @@ export class Dialog {
shift: boolean; shift: boolean;
alt: boolean; alt: boolean;
ctrl: boolean; ctrl: boolean;
}): any { }) {
if (keyCode === kbEnter && this.enterHandler) { if (keyCode === kbEnter && this.enterHandler) {
this.internalButtonHandler(this.enterHandler); this.internalButtonHandler(this.enterHandler);
return STOP_PROPAGATION; return STOP_PROPAGATION;
@ -75,15 +75,15 @@ export class Dialog {
return STOP_PROPAGATION; return STOP_PROPAGATION;
} }
} }
internalButtonHandler(id: any, ...payload: any): any { internalButtonHandler(id, ...payload) {
this.app.inputMgr.popReciever(this.inputReciever); this.app.inputMgr.popReciever(this.inputReciever);
if (id !== "close-button") { if (id !== "close-button") {
this.buttonSignals[id].dispatch(...payload); this.buttonSignals[id].dispatch(...payload);
} }
this.closeRequested.dispatch(); this.closeRequested.dispatch();
} }
createElement(): any { createElement() {
const elem: any = document.createElement("div"); const elem = document.createElement("div");
elem.classList.add("ingameDialog"); elem.classList.add("ingameDialog");
this.dialogElem = document.createElement("div"); this.dialogElem = document.createElement("div");
this.dialogElem.classList.add("dialogInner"); this.dialogElem.classList.add("dialogInner");
@ -91,45 +91,45 @@ export class Dialog {
this.dialogElem.classList.add(this.type); this.dialogElem.classList.add(this.type);
} }
elem.appendChild(this.dialogElem); elem.appendChild(this.dialogElem);
const title: any = document.createElement("h1"); const title = document.createElement("h1");
title.innerText = this.title; title.innerText = this.title;
title.classList.add("title"); title.classList.add("title");
this.dialogElem.appendChild(title); this.dialogElem.appendChild(title);
if (this.closeButton) { if (this.closeButton) {
this.dialogElem.classList.add("hasCloseButton"); this.dialogElem.classList.add("hasCloseButton");
const closeBtn: any = document.createElement("button"); const closeBtn = document.createElement("button");
closeBtn.classList.add("closeButton"); closeBtn.classList.add("closeButton");
this.trackClicks(closeBtn, (): any => this.internalButtonHandler("close-button"), { this.trackClicks(closeBtn, () => this.internalButtonHandler("close-button"), {
applyCssClass: "pressedSmallElement", applyCssClass: "pressedSmallElement",
}); });
title.appendChild(closeBtn); title.appendChild(closeBtn);
this.inputReciever.backButton.add((): any => this.internalButtonHandler("close-button")); this.inputReciever.backButton.add(() => this.internalButtonHandler("close-button"));
} }
const content: any = document.createElement("div"); const content = document.createElement("div");
content.classList.add("content"); content.classList.add("content");
content.innerHTML = this.contentHTML; content.innerHTML = this.contentHTML;
this.dialogElem.appendChild(content); this.dialogElem.appendChild(content);
if (this.buttonIds.length > 0) { if (this.buttonIds.length > 0) {
const buttons: any = document.createElement("div"); const buttons = document.createElement("div");
buttons.classList.add("buttons"); buttons.classList.add("buttons");
// Create buttons // Create buttons
for (let i: any = 0; i < this.buttonIds.length; ++i) { for (let i = 0; i < this.buttonIds.length; ++i) {
const [buttonId, buttonStyle, rawParams]: any = this.buttonIds[i].split(":"); const [buttonId, buttonStyle, rawParams] = this.buttonIds[i].split(":");
const button: any = document.createElement("button"); const button = document.createElement("button");
button.classList.add("button"); button.classList.add("button");
button.classList.add("styledButton"); button.classList.add("styledButton");
button.classList.add(buttonStyle); button.classList.add(buttonStyle);
button.innerText = T.dialogs.buttons[buttonId]; button.innerText = T.dialogs.buttons[buttonId];
const params: any = (rawParams || "").split("/"); const params = (rawParams || "").split("/");
const useTimeout: any = params.indexOf("timeout") >= 0; const useTimeout = params.indexOf("timeout") >= 0;
const isEnter: any = params.indexOf("enter") >= 0; const isEnter = params.indexOf("enter") >= 0;
const isEscape: any = params.indexOf("escape") >= 0; const isEscape = params.indexOf("escape") >= 0;
if (isEscape && this.closeButton) { if (isEscape && this.closeButton) {
logger.warn("Showing dialog with close button, and additional cancel button"); logger.warn("Showing dialog with close button, and additional cancel button");
} }
if (useTimeout) { if (useTimeout) {
button.classList.add("timedButton"); button.classList.add("timedButton");
const timeout: any = setTimeout((): any => { const timeout = setTimeout(() => {
button.classList.remove("timedButton"); button.classList.remove("timedButton");
arrayDeleteValue(this.timeouts, timeout); arrayDeleteValue(this.timeouts, timeout);
}, 1000); }, 1000);
@ -138,7 +138,7 @@ export class Dialog {
if (isEnter || isEscape) { if (isEnter || isEscape) {
// if (this.app.settings.getShowKeyboardShortcuts()) { // if (this.app.settings.getShowKeyboardShortcuts()) {
// Show keybinding // Show keybinding
const spacer: any = document.createElement("code"); const spacer = document.createElement("code");
spacer.classList.add("keybinding"); spacer.classList.add("keybinding");
spacer.innerHTML = getStringForKeyCode(isEnter ? kbEnter : kbCancel); spacer.innerHTML = getStringForKeyCode(isEnter ? kbEnter : kbCancel);
button.appendChild(spacer); button.appendChild(spacer);
@ -150,7 +150,7 @@ export class Dialog {
this.escapeHandler = buttonId; this.escapeHandler = buttonId;
} }
} }
this.trackClicks(button, (): any => this.internalButtonHandler(buttonId)); this.trackClicks(button, () => this.internalButtonHandler(buttonId));
buttons.appendChild(button); buttons.appendChild(button);
} }
this.dialogElem.appendChild(buttons); this.dialogElem.appendChild(buttons);
@ -162,10 +162,10 @@ export class Dialog {
this.app.inputMgr.pushReciever(this.inputReciever); this.app.inputMgr.pushReciever(this.inputReciever);
return this.element; return this.element;
} }
setIndex(index: any): any { setIndex(index) {
this.element.style.zIndex = index; this.element.style.zIndex = index;
} }
destroy(): any { destroy() {
if (!this.element) { if (!this.element) {
assert(false, "Tried to destroy dialog twice"); assert(false, "Tried to destroy dialog twice");
return; return;
@ -174,21 +174,21 @@ export class Dialog {
// dispatched to the modal dialogs, it will not call the internalButtonHandler, // dispatched to the modal dialogs, it will not call the internalButtonHandler,
// and thus our receiver stays attached the whole time // and thus our receiver stays attached the whole time
this.app.inputMgr.destroyReceiver(this.inputReciever); this.app.inputMgr.destroyReceiver(this.inputReciever);
for (let i: any = 0; i < this.clickDetectors.length; ++i) { for (let i = 0; i < this.clickDetectors.length; ++i) {
this.clickDetectors[i].cleanup(); this.clickDetectors[i].cleanup();
} }
this.clickDetectors = []; this.clickDetectors = [];
this.element.remove(); this.element.remove();
this.element = null; this.element = null;
for (let i: any = 0; i < this.timeouts.length; ++i) { for (let i = 0; i < this.timeouts.length; ++i) {
clearTimeout(this.timeouts[i]); clearTimeout(this.timeouts[i]);
} }
this.timeouts = []; this.timeouts = [];
} }
hide(): any { hide() {
this.element.classList.remove("visible"); this.element.classList.remove("visible");
} }
show(): any { show() {
this.element.classList.add("visible"); this.element.classList.add("visible");
} }
/** /**
@ -196,7 +196,7 @@ export class Dialog {
* {} * {}
*/ */
trackClicks(elem: Element, handler: function():void, args: import("./click_detector").ClickDetectorConstructorArgs= = {}): ClickDetector { trackClicks(elem: Element, handler: function():void, args: import("./click_detector").ClickDetectorConstructorArgs= = {}): ClickDetector {
const detector: any = new ClickDetector(elem, args); const detector = new ClickDetector(elem, args);
detector.click.add(handler, this); detector.click.add(handler, this);
this.clickDetectors.push(detector); this.clickDetectors.push(detector);
return detector; return detector;
@ -220,18 +220,18 @@ export class DialogLoading extends Dialog {
this.inputReciever.backButton.removeAll(); this.inputReciever.backButton.removeAll();
this.inputReciever.context = "dialog-loading"; this.inputReciever.context = "dialog-loading";
} }
createElement(): any { createElement() {
const elem: any = document.createElement("div"); const elem = document.createElement("div");
elem.classList.add("ingameDialog"); elem.classList.add("ingameDialog");
elem.classList.add("loadingDialog"); elem.classList.add("loadingDialog");
this.element = elem; this.element = elem;
if (this.text) { if (this.text) {
const text: any = document.createElement("div"); const text = document.createElement("div");
text.classList.add("text"); text.classList.add("text");
text.innerText = this.text; text.innerText = this.text;
elem.appendChild(text); elem.appendChild(text);
} }
const loader: any = document.createElement("div"); const loader = document.createElement("div");
loader.classList.add("prefab_LoadingTextWithAnim"); loader.classList.add("prefab_LoadingTextWithAnim");
loader.classList.add("loadingIndicator"); loader.classList.add("loadingIndicator");
elem.appendChild(loader); elem.appendChild(loader);
@ -244,10 +244,10 @@ export class DialogOptionChooser extends Dialog {
public initialOption = options.active; public initialOption = options.active;
constructor({ app, title, options }) { constructor({ app, title, options }) {
let html: any = "<div class='optionParent'>"; let html = "<div class='optionParent'>";
options.options.forEach(({ value, text, desc = null, iconPrefix = null }: any): any => { options.options.forEach(({ value, text, desc = null, iconPrefix = null }) => {
const descHtml: any = desc ? `<span class="desc">${desc}</span>` : ""; const descHtml = desc ? `<span class="desc">${desc}</span>` : "";
let iconHtml: any = iconPrefix ? `<span class="icon icon-${iconPrefix}-${value}"></span>` : ""; let iconHtml = iconPrefix ? `<span class="icon icon-${iconPrefix}-${value}"></span>` : "";
html += ` html += `
<div class='option ${value === options.active ? "active" : ""} ${iconPrefix ? "hasIcon" : ""}' data-optionvalue='${value}'> <div class='option ${value === options.active ? "active" : ""} ${iconPrefix ? "hasIcon" : ""}' data-optionvalue='${value}'>
${iconHtml} ${iconHtml}
@ -267,17 +267,17 @@ export class DialogOptionChooser extends Dialog {
}); });
this.buttonSignals.optionSelected = new Signal(); this.buttonSignals.optionSelected = new Signal();
} }
createElement(): any { createElement() {
const div: any = super.createElement(); const div = super.createElement();
this.dialogElem.classList.add("optionChooserDialog"); this.dialogElem.classList.add("optionChooserDialog");
div.querySelectorAll("[data-optionvalue]").forEach((handle: any): any => { div.querySelectorAll("[data-optionvalue]").forEach(handle => {
const value: any = handle.getAttribute("data-optionvalue"); const value = handle.getAttribute("data-optionvalue");
if (!handle) { if (!handle) {
logger.error("Failed to bind option value in dialog:", value); logger.error("Failed to bind option value in dialog:", value);
return; return;
} }
// Need click detector here to forward elements, otherwise scrolling does not work // Need click detector here to forward elements, otherwise scrolling does not work
const detector: any = new ClickDetector(handle, { const detector = new ClickDetector(handle, {
consumeEvents: false, consumeEvents: false,
preventDefault: false, preventDefault: false,
clickSound: null, clickSound: null,
@ -286,8 +286,8 @@ export class DialogOptionChooser extends Dialog {
}); });
this.clickDetectors.push(detector); this.clickDetectors.push(detector);
if (value !== this.initialOption) { if (value !== this.initialOption) {
detector.click.add((): any => { detector.click.add(() => {
const selected: any = div.querySelector(".option.active"); const selected = div.querySelector(".option.active");
if (selected) { if (selected) {
selected.classList.remove("active"); selected.classList.remove("active");
} }
@ -309,9 +309,9 @@ export class DialogWithForm extends Dialog {
public enterHandler = confirmButtonId; public enterHandler = confirmButtonId;
constructor({ app, title, desc, formElements, buttons = ["cancel", "ok:good"], confirmButtonId = "ok", closeButton = true, }) { constructor({ app, title, desc, formElements, buttons = ["cancel", "ok:good"], confirmButtonId = "ok", closeButton = true, }) {
let html: any = ""; let html = "";
html += desc + "<br>"; html += desc + "<br>";
for (let i: any = 0; i < formElements.length; ++i) { for (let i = 0; i < formElements.length; ++i) {
html += formElements[i].getHtml(); html += formElements[i].getHtml();
} }
super({ super({
@ -323,11 +323,11 @@ export class DialogWithForm extends Dialog {
closeButton, closeButton,
}); });
} }
internalButtonHandler(id: any, ...payload: any): any { internalButtonHandler(id, ...payload) {
if (id === this.confirmButtonId) { if (id === this.confirmButtonId) {
if (this.hasAnyInvalid()) { if (this.hasAnyInvalid()) {
this.dialogElem.classList.remove("errorShake"); this.dialogElem.classList.remove("errorShake");
waitNextFrame().then((): any => { waitNextFrame().then(() => {
if (this.dialogElem) { if (this.dialogElem) {
this.dialogElem.classList.add("errorShake"); this.dialogElem.classList.add("errorShake");
} }
@ -338,23 +338,23 @@ export class DialogWithForm extends Dialog {
} }
super.internalButtonHandler(id, payload); super.internalButtonHandler(id, payload);
} }
hasAnyInvalid(): any { hasAnyInvalid() {
for (let i: any = 0; i < this.formElements.length; ++i) { for (let i = 0; i < this.formElements.length; ++i) {
if (!this.formElements[i].isValid()) { if (!this.formElements[i].isValid()) {
return true; return true;
} }
} }
return false; return false;
} }
createElement(): any { createElement() {
const div: any = super.createElement(); const div = super.createElement();
for (let i: any = 0; i < this.formElements.length; ++i) { for (let i = 0; i < this.formElements.length; ++i) {
const elem: any = this.formElements[i]; const elem = this.formElements[i];
elem.bindEvents(div, this.clickDetectors); elem.bindEvents(div, this.clickDetectors);
// elem.valueChosen.add(this.closeRequested.dispatch, this.closeRequested); // elem.valueChosen.add(this.closeRequested.dispatch, this.closeRequested);
elem.valueChosen.add(this.valueChosen.dispatch, this.valueChosen); elem.valueChosen.add(this.valueChosen.dispatch, this.valueChosen);
} }
waitNextFrame().then((): any => { waitNextFrame().then(() => {
this.formElements[this.formElements.length - 1].focus(); this.formElements[this.formElements.length - 1].focus();
}); });
return div; return div;

View File

@ -18,18 +18,18 @@ export class FormElement {
constructor(id, label) { constructor(id, label) {
} }
getHtml(): any { getHtml() {
abstract; abstract;
return ""; return "";
} }
getFormElement(parent: any): any { getFormElement(parent) {
return parent.querySelector("[data-formId='" + this.id + "']"); return parent.querySelector("[data-formId='" + this.id + "']");
} }
bindEvents(parent: any, clickTrackers: any): any { bindEvents(parent, clickTrackers) {
abstract; abstract;
} }
focus(): any { } focus() { }
isValid(): any { isValid() {
return true; return true;
} }
/** {} */ /** {} */
@ -47,10 +47,10 @@ export class FormElementInput extends FormElement {
constructor({ id, label = null, placeholder, defaultValue = "", inputType = "text", validator = null }) { constructor({ id, label = null, placeholder, defaultValue = "", inputType = "text", validator = null }) {
super(id, label); super(id, label);
} }
getHtml(): any { getHtml() {
let classes: any = []; let classes = [];
let inputType: any = "text"; let inputType = "text";
let maxlength: any = 256; let maxlength = 256;
switch (this.inputType) { switch (this.inputType) {
case "text": { case "text": {
classes.push("input-text"); classes.push("input-text");
@ -85,25 +85,25 @@ export class FormElementInput extends FormElement {
</div> </div>
`; `;
} }
bindEvents(parent: any, clickTrackers: any): any { bindEvents(parent, clickTrackers) {
this.element = this.getFormElement(parent); this.element = this.getFormElement(parent);
this.element.addEventListener("input", (event: any): any => this.updateErrorState()); this.element.addEventListener("input", event => this.updateErrorState());
this.updateErrorState(); this.updateErrorState();
} }
updateErrorState(): any { updateErrorState() {
this.element.classList.toggle("errored", !this.isValid()); this.element.classList.toggle("errored", !this.isValid());
} }
isValid(): any { isValid() {
return !this.validator || this.validator(this.element.value); return !this.validator || this.validator(this.element.value);
} }
getValue(): any { getValue() {
return this.element.value; return this.element.value;
} }
setValue(value: any): any { setValue(value) {
this.element.value = value; this.element.value = value;
this.updateErrorState(); this.updateErrorState();
} }
focus(): any { focus() {
this.element.focus(); this.element.focus();
this.element.select(); this.element.select();
} }
@ -116,7 +116,7 @@ export class FormElementCheckbox extends FormElement {
constructor({ id, label, defaultValue = true }) { constructor({ id, label, defaultValue = true }) {
super(id, label); super(id, label);
} }
getHtml(): any { getHtml() {
return ` return `
<div class="formElement checkBoxFormElem"> <div class="formElement checkBoxFormElem">
${this.label ? `<label>${this.label}</label>` : ""} ${this.label ? `<label>${this.label}</label>` : ""}
@ -126,23 +126,23 @@ export class FormElementCheckbox extends FormElement {
</div> </div>
`; `;
} }
bindEvents(parent: any, clickTrackers: any): any { bindEvents(parent, clickTrackers) {
this.element = this.getFormElement(parent); this.element = this.getFormElement(parent);
const detector: any = new ClickDetector(this.element, { const detector = new ClickDetector(this.element, {
consumeEvents: false, consumeEvents: false,
preventDefault: false, preventDefault: false,
}); });
clickTrackers.push(detector); clickTrackers.push(detector);
detector.click.add(this.toggle, this); detector.click.add(this.toggle, this);
} }
getValue(): any { getValue() {
return this.value; return this.value;
} }
toggle(): any { toggle() {
this.value = !this.value; this.value = !this.value;
this.element.classList.toggle("checked", this.value); this.element.classList.toggle("checked", this.value);
} }
focus(parent: any): any { } focus(parent) { }
} }
export class FormElementItemChooser extends FormElement { export class FormElementItemChooser extends FormElement {
public items = items; public items = items;
@ -152,8 +152,8 @@ export class FormElementItemChooser extends FormElement {
constructor({ id, label, items = [] }) { constructor({ id, label, items = [] }) {
super(id, label); super(id, label);
} }
getHtml(): any { getHtml() {
let classes: any = []; let classes = [];
return ` return `
<div class="formElement"> <div class="formElement">
${this.label ? `<label>${this.label}</label>` : ""} ${this.label ? `<label>${this.label}</label>` : ""}
@ -161,29 +161,29 @@ export class FormElementItemChooser extends FormElement {
</div> </div>
`; `;
} }
bindEvents(parent: HTMLElement, clickTrackers: Array<ClickDetector>): any { bindEvents(parent: HTMLElement, clickTrackers: Array<ClickDetector>) {
this.element = this.getFormElement(parent); this.element = this.getFormElement(parent);
for (let i: any = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item: any = this.items[i]; const item = this.items[i];
const canvas: any = document.createElement("canvas"); const canvas = document.createElement("canvas");
canvas.width = 128; canvas.width = 128;
canvas.height = 128; canvas.height = 128;
const context: any = canvas.getContext("2d"); const context = canvas.getContext("2d");
item.drawFullSizeOnCanvas(context, 128); item.drawFullSizeOnCanvas(context, 128);
this.element.appendChild(canvas); this.element.appendChild(canvas);
const detector: any = new ClickDetector(canvas, {}); const detector = new ClickDetector(canvas, {});
clickTrackers.push(detector); clickTrackers.push(detector);
detector.click.add((): any => { detector.click.add(() => {
this.chosenItem = item; this.chosenItem = item;
this.valueChosen.dispatch(item); this.valueChosen.dispatch(item);
}); });
} }
} }
isValid(): any { isValid() {
return true; return true;
} }
getValue(): any { getValue() {
return null; return null;
} }
focus(): any { } focus() { }
} }

View File

@ -1,18 +1,18 @@
function mathPolyfills(): any { function mathPolyfills() {
// Converts from degrees to radians. // Converts from degrees to radians.
Math.radians = function (degrees: any): any { Math.radians = function (degrees) {
return (degrees * Math.PI) / 180.0; return (degrees * Math.PI) / 180.0;
}; };
// Converts from radians to degrees. // Converts from radians to degrees.
Math.degrees = function (radians: any): any { Math.degrees = function (radians) {
return (radians * 180.0) / Math.PI; return (radians * 180.0) / Math.PI;
}; };
} }
function stringPolyfills(): any { function stringPolyfills() {
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
if (!String.prototype.padStart) { if (!String.prototype.padStart) {
String.prototype.padStart = function padStart(targetLength: any, padString: any): any { String.prototype.padStart = function padStart(targetLength, padString) {
targetLength = targetLength >> 0; //truncate if number, or convert non-number to 0; targetLength = targetLength >> 0; //truncate if number, or convert non-number to 0;
padString = String(typeof padString !== "undefined" ? padString : " "); padString = String(typeof padString !== "undefined" ? padString : " ");
if (this.length >= targetLength) { if (this.length >= targetLength) {
@ -30,7 +30,7 @@ function stringPolyfills(): any {
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
if (!String.prototype.padEnd) { if (!String.prototype.padEnd) {
String.prototype.padEnd = function padEnd(targetLength: any, padString: any): any { String.prototype.padEnd = function padEnd(targetLength, padString) {
targetLength = targetLength >> 0; //floor if number or convert non-number to 0; targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
padString = String(typeof padString !== "undefined" ? padString : " "); padString = String(typeof padString !== "undefined" ? padString : " ");
if (this.length > targetLength) { if (this.length > targetLength) {
@ -46,33 +46,33 @@ function stringPolyfills(): any {
}; };
} }
} }
function objectPolyfills(): any { function objectPolyfills() {
// https://github.com/tc39/proposal-object-values-entries/blob/master/polyfill.js // https://github.com/tc39/proposal-object-values-entries/blob/master/polyfill.js
// @ts-ignore // @ts-ignore
const reduce: any = Function.bind.call(Function.call, Array.prototype.reduce); const reduce = Function.bind.call(Function.call, Array.prototype.reduce);
// @ts-ignore // @ts-ignore
const isEnumerable: any = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable); const isEnumerable = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable);
// @ts-ignore // @ts-ignore
const concat: any = Function.bind.call(Function.call, Array.prototype.concat); const concat = Function.bind.call(Function.call, Array.prototype.concat);
const keys: any = Reflect.ownKeys; const keys = Reflect.ownKeys;
// @ts-ignore // @ts-ignore
if (!Object.values) { if (!Object.values) {
// @ts-ignore // @ts-ignore
Object.values = function values(O: any): any { Object.values = function values(O) {
return reduce(keys(O), (v: any, k: any): any => concat(v, typeof k === "string" && isEnumerable(O, k) ? [O[k]] : []), []); return reduce(keys(O), (v, k) => concat(v, typeof k === "string" && isEnumerable(O, k) ? [O[k]] : []), []);
}; };
} }
if (!Object.entries) { if (!Object.entries) {
// @ts-ignore // @ts-ignore
Object.entries = function entries(O: any): any { Object.entries = function entries(O) {
return reduce(keys(O), (e: any, k: any): any => concat(e, typeof k === "string" && isEnumerable(O, k) ? [[k, O[k]]] : []), []); return reduce(keys(O), (e, k) => concat(e, typeof k === "string" && isEnumerable(O, k) ? [[k, O[k]]] : []), []);
}; };
} }
} }
function domPolyfills(): any { 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: any): any { (function (arr) {
arr.forEach(function (item: any): any { arr.forEach(function (item) {
if (item.hasOwnProperty("remove")) { if (item.hasOwnProperty("remove")) {
return; return;
} }
@ -80,22 +80,22 @@ function domPolyfills(): any {
configurable: true, configurable: true,
enumerable: true, enumerable: true,
writable: true, writable: true,
value: function remove(): any { value: function remove() {
this.parentNode.removeChild(this); this.parentNode.removeChild(this);
}, },
}); });
}); });
})([Element.prototype, CharacterData.prototype, DocumentType.prototype]); })([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
} }
function initPolyfills(): any { function initPolyfills() {
mathPolyfills(); mathPolyfills();
stringPolyfills(); stringPolyfills();
objectPolyfills(); objectPolyfills();
domPolyfills(); domPolyfills();
} }
function initExtensions(): any { function initExtensions() {
String.prototype.replaceAll = function (search: any, replacement: any): any { String.prototype.replaceAll = function (search, replacement) {
var target: any = this; var target = this;
return target.split(search).join(replacement); return target.split(search).join(replacement);
}; };
} }

View File

@ -1,6 +1,6 @@
const queryString: any = require("query-string"); const queryString = require("query-string");
const options: any = queryString.parse(location.search); const options = queryString.parse(location.search);
export let queryParamOptions: any = { export let queryParamOptions = {
embedProvider: null, embedProvider: null,
abtVariant: null, abtVariant: null,
campaign: null, campaign: null,

View File

@ -10,9 +10,9 @@ import { ExplainedResult } from "./explained_result";
import { decompressX64, compressX64 } from "./lzstring"; import { decompressX64, compressX64 } from "./lzstring";
import { asyncCompressor, compressionPrefix } from "./async_compression"; import { asyncCompressor, compressionPrefix } from "./async_compression";
import { compressObject, decompressObject } from "../savegame/savegame_compressor"; import { compressObject, decompressObject } from "../savegame/savegame_compressor";
const debounce: any = require("debounce-promise"); const debounce = require("debounce-promise");
const logger: any = createLogger("read_write_proxy"); const logger = createLogger("read_write_proxy");
const salt: any = accessNestedPropertyReverse(globalConfig, ["file", "info"]); const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]);
// 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 {
public app: Application = app; public app: Application = app;
@ -23,47 +23,47 @@ export class ReadWriteProxy {
constructor(app, filename) { constructor(app, filename) {
// TODO: EXTREMELY HACKY! To verify we need to do this a step later // TODO: EXTREMELY HACKY! To verify we need to do this a step later
if (G_IS_DEV && IS_DEBUG) { if (G_IS_DEV && IS_DEBUG) {
setTimeout((): any => { setTimeout(() => {
assert(this.verify(this.getDefaultData()).result, "Verify() failed for default data: " + this.verify(this.getDefaultData()).reason); assert(this.verify(this.getDefaultData()).result, "Verify() failed for default data: " + this.verify(this.getDefaultData()).reason);
}); });
} }
} }
// -- Methods to override // -- Methods to override
/** {} */ /** {} */
verify(data: any): ExplainedResult { verify(data): ExplainedResult {
abstract; abstract;
return ExplainedResult.bad(); return ExplainedResult.bad();
} }
// Should return the default data // Should return the default data
getDefaultData(): any { getDefaultData() {
abstract; abstract;
return {}; return {};
} }
// Should return the current version as an integer // Should return the current version as an integer
getCurrentVersion(): any { getCurrentVersion() {
abstract; abstract;
return 0; return 0;
} }
// Should migrate the data (Modify in place) // Should migrate the data (Modify in place)
/** {} */ /** {} */
migrate(data: any): ExplainedResult { migrate(data): ExplainedResult {
abstract; abstract;
return ExplainedResult.bad(); return ExplainedResult.bad();
} }
// -- / Methods // -- / Methods
// Resets whole data, returns promise // Resets whole data, returns promise
resetEverythingAsync(): any { resetEverythingAsync() {
logger.warn("Reset data to default"); logger.warn("Reset data to default");
this.currentData = this.getDefaultData(); this.currentData = this.getDefaultData();
return this.writeAsync(); return this.writeAsync();
} }
static serializeObject(obj: object): any { static serializeObject(obj: object) {
const jsonString: any = JSON.stringify(compressObject(obj)); const jsonString = JSON.stringify(compressObject(obj));
const checksum: any = computeCrc(jsonString + salt); const checksum = computeCrc(jsonString + salt);
return compressionPrefix + compressX64(checksum + jsonString); return compressionPrefix + compressX64(checksum + jsonString);
} }
static deserializeObject(text: object): any { static deserializeObject(text: object) {
const decompressed: any = decompressX64(text.substr(compressionPrefix.length)); const decompressed = decompressX64(text.substr(compressionPrefix.length));
if (!decompressed) { if (!decompressed) {
// LZ string decompression failure // LZ string decompression failure
throw new Error("bad-content / decompression-failed"); throw new Error("bad-content / decompression-failed");
@ -73,17 +73,17 @@ export class ReadWriteProxy {
throw new Error("bad-content / payload-too-small"); throw new Error("bad-content / payload-too-small");
} }
// Compare stored checksum with actual checksum // Compare stored checksum with actual checksum
const checksum: any = decompressed.substring(0, 40); const checksum = decompressed.substring(0, 40);
const jsonString: any = decompressed.substr(40); const jsonString = decompressed.substr(40);
const desiredChecksum: any = checksum.startsWith(CRC_PREFIX) const desiredChecksum = checksum.startsWith(CRC_PREFIX)
? computeCrc(jsonString + salt) ? computeCrc(jsonString + salt)
: sha1(jsonString + salt); : sha1(jsonString + salt);
if (desiredChecksum !== checksum) { if (desiredChecksum !== checksum) {
// Checksum mismatch // Checksum mismatch
throw new Error("bad-content / checksum-mismatch"); throw new Error("bad-content / checksum-mismatch");
} }
const parsed: any = JSON.parse(jsonString); const parsed = JSON.parse(jsonString);
const decoded: any = decompressObject(parsed); const decoded = decompressObject(parsed);
return decoded; return decoded;
} }
/** /**
@ -92,7 +92,7 @@ export class ReadWriteProxy {
* {} * {}
*/ */
writeAsync(): Promise<void> { writeAsync(): Promise<void> {
const verifyResult: any = this.internalVerifyEntry(this.currentData); const verifyResult = this.internalVerifyEntry(this.currentData);
if (!verifyResult.result) { if (!verifyResult.result) {
logger.error("Tried to write invalid data to", this.filename, "reason:", verifyResult.reason); logger.error("Tried to write invalid data to", this.filename, "reason:", verifyResult.reason);
return Promise.reject(verifyResult.reason); return Promise.reject(verifyResult.reason);
@ -106,24 +106,24 @@ export class ReadWriteProxy {
doWriteAsync(): Promise<void> { doWriteAsync(): Promise<void> {
return asyncCompressor return asyncCompressor
.compressObjectAsync(this.currentData) .compressObjectAsync(this.currentData)
.then((compressed: any): any => { .then(compressed => {
return this.app.storage.writeFileAsync(this.filename, compressed); return this.app.storage.writeFileAsync(this.filename, compressed);
}) })
.then((): any => { .then(() => {
logger.log("📄 Wrote", this.filename); logger.log("📄 Wrote", this.filename);
}) })
.catch((err: any): any => { .catch(err => {
logger.error("Failed to write", this.filename, ":", err); logger.error("Failed to write", this.filename, ":", err);
throw err; throw err;
}); });
} }
// Reads the data asynchronously, fails if verify() fails // Reads the data asynchronously, fails if verify() fails
readAsync(): any { readAsync() {
// Start read request // Start read request
return (this.app.storage return (this.app.storage
.readFileAsync(this.filename) .readFileAsync(this.filename)
// Check for errors during read // Check for errors during read
.catch((err: any): any => { .catch(err => {
if (err === FILE_NOT_FOUND) { if (err === FILE_NOT_FOUND) {
logger.log("File not found, using default data"); logger.log("File not found, using default data");
// File not found or unreadable, assume default file // File not found or unreadable, assume default file
@ -133,13 +133,13 @@ export class ReadWriteProxy {
}) })
// Decrypt data (if its encrypted) // Decrypt data (if its encrypted)
// @ts-ignore // @ts-ignore
.then((rawData: any): any => { .then(rawData => {
if (rawData == null) { if (rawData == null) {
// So, the file has not been found, use default data // So, the file has not been found, use default data
return JSON.stringify(compressObject(this.getDefaultData())); return JSON.stringify(compressObject(this.getDefaultData()));
} }
if (rawData.startsWith(compressionPrefix)) { if (rawData.startsWith(compressionPrefix)) {
const decompressed: any = decompressX64(rawData.substr(compressionPrefix.length)); const decompressed = decompressX64(rawData.substr(compressionPrefix.length));
if (!decompressed) { if (!decompressed) {
// LZ string decompression failure // LZ string decompression failure
return Promise.reject("bad-content / decompression-failed"); return Promise.reject("bad-content / decompression-failed");
@ -149,9 +149,9 @@ export class ReadWriteProxy {
return Promise.reject("bad-content / payload-too-small"); return Promise.reject("bad-content / payload-too-small");
} }
// Compare stored checksum with actual checksum // Compare stored checksum with actual checksum
const checksum: any = decompressed.substring(0, 40); const checksum = decompressed.substring(0, 40);
const jsonString: any = decompressed.substr(40); const jsonString = decompressed.substr(40);
const desiredChecksum: any = checksum.startsWith(CRC_PREFIX) const desiredChecksum = checksum.startsWith(CRC_PREFIX)
? computeCrc(jsonString + salt) ? computeCrc(jsonString + salt)
: sha1(jsonString + salt); : sha1(jsonString + salt);
if (desiredChecksum !== checksum) { if (desiredChecksum !== checksum) {
@ -168,33 +168,33 @@ export class ReadWriteProxy {
return rawData; return rawData;
}) })
// Parse JSON, this could throw but that's fine // Parse JSON, this could throw but that's fine
.then((res: any): any => { .then(res => {
try { try {
return JSON.parse(res); return JSON.parse(res);
} }
catch (ex: any) { catch (ex) {
logger.error("Failed to parse file content of", this.filename, ":", ex, "(content was:", res, ")"); logger.error("Failed to parse file content of", this.filename, ":", ex, "(content was:", res, ")");
throw new Error("invalid-serialized-data"); throw new Error("invalid-serialized-data");
} }
}) })
// Decompress // Decompress
.then((compressed: any): any => decompressObject(compressed)) .then(compressed => decompressObject(compressed))
// Verify basic structure // Verify basic structure
.then((contents: any): any => { .then(contents => {
const result: any = this.internalVerifyBasicStructure(contents); const result = this.internalVerifyBasicStructure(contents);
if (!result.isGood()) { if (!result.isGood()) {
return Promise.reject("verify-failed: " + result.reason); return Promise.reject("verify-failed: " + result.reason);
} }
return contents; return contents;
}) })
// Check version and migrate if required // Check version and migrate if required
.then((contents: any): any => { .then(contents => {
if (contents.version > this.getCurrentVersion()) { if (contents.version > this.getCurrentVersion()) {
return Promise.reject("stored-data-is-newer"); return Promise.reject("stored-data-is-newer");
} }
if (contents.version < this.getCurrentVersion()) { if (contents.version < this.getCurrentVersion()) {
logger.log("Trying to migrate data object from version", contents.version, "to", this.getCurrentVersion()); logger.log("Trying to migrate data object from version", contents.version, "to", this.getCurrentVersion());
const migrationResult: any = this.migrate(contents); // modify in place const migrationResult = this.migrate(contents); // modify in place
if (migrationResult.isBad()) { if (migrationResult.isBad()) {
return Promise.reject("migration-failed: " + migrationResult.reason); return Promise.reject("migration-failed: " + migrationResult.reason);
} }
@ -202,8 +202,8 @@ export class ReadWriteProxy {
return contents; return contents;
}) })
// Verify // Verify
.then((contents: any): any => { .then(contents => {
const verifyResult: any = this.internalVerifyEntry(contents); const verifyResult = this.internalVerifyEntry(contents);
if (!verifyResult.result) { if (!verifyResult.result) {
logger.error("Read invalid data from", this.filename, "reason:", verifyResult.reason, "contents:", contents); logger.error("Read invalid data from", this.filename, "reason:", verifyResult.reason, "contents:", contents);
return Promise.reject("invalid-data: " + verifyResult.reason); return Promise.reject("invalid-data: " + verifyResult.reason);
@ -211,13 +211,13 @@ export class ReadWriteProxy {
return contents; return contents;
}) })
// Store // Store
.then((contents: any): any => { .then(contents => {
this.currentData = contents; this.currentData = contents;
logger.log("📄 Read data with version", this.currentData.version, "from", this.filename); logger.log("📄 Read data with version", this.currentData.version, "from", this.filename);
return contents; return contents;
}) })
// Catchall // Catchall
.catch((err: any): any => { .catch(err => {
return Promise.reject("Failed to read " + this.filename + ": " + err); return Promise.reject("Failed to read " + this.filename + ": " + err);
})); }));
} }
@ -230,7 +230,7 @@ export class ReadWriteProxy {
} }
// Internal // Internal
/** {} */ /** {} */
internalVerifyBasicStructure(data: any): ExplainedResult { internalVerifyBasicStructure(data): ExplainedResult {
if (!data) { if (!data) {
return ExplainedResult.bad("Data is empty"); return ExplainedResult.bad("Data is empty");
} }
@ -240,11 +240,11 @@ export class ReadWriteProxy {
return ExplainedResult.good(); return ExplainedResult.good();
} }
/** {} */ /** {} */
internalVerifyEntry(data: any): ExplainedResult { internalVerifyEntry(data): ExplainedResult {
if (data.version !== this.getCurrentVersion()) { if (data.version !== this.getCurrentVersion()) {
return ExplainedResult.bad("Version mismatch, got " + data.version + " and expected " + this.getCurrentVersion()); return ExplainedResult.bad("Version mismatch, got " + data.version + " and expected " + this.getCurrentVersion());
} }
const verifyStructureError: any = this.internalVerifyBasicStructure(data); const verifyStructureError = this.internalVerifyBasicStructure(data);
if (!verifyStructureError.isGood()) { if (!verifyStructureError.isGood()) {
return verifyStructureError; return verifyStructureError;
} }

View File

@ -12,29 +12,29 @@ export class Rectangle {
/** /**
* Creates a rectangle from top right bottom and left offsets * Creates a rectangle from top right bottom and left offsets
*/ */
static fromTRBL(top: number, right: number, bottom: number, left: number): any { static fromTRBL(top: number, right: number, bottom: number, left: number) {
return new Rectangle(left, top, right - left, bottom - top); return new Rectangle(left, top, right - left, bottom - top);
} }
/** /**
* Constructs a new square rectangle * Constructs a new square rectangle
*/ */
static fromSquare(x: number, y: number, size: number): any { static fromSquare(x: number, y: number, size: number) {
return new Rectangle(x, y, size, size); return new Rectangle(x, y, size, size);
} }
static fromTwoPoints(p1: Vector, p2: Vector): any { static fromTwoPoints(p1: Vector, p2: Vector) {
const left: any = Math.min(p1.x, p2.x); const left = Math.min(p1.x, p2.x);
const top: any = Math.min(p1.y, p2.y); const top = Math.min(p1.y, p2.y);
const right: any = Math.max(p1.x, p2.x); const right = Math.max(p1.x, p2.x);
const bottom: any = Math.max(p1.y, p2.y); const bottom = Math.max(p1.y, p2.y);
return new Rectangle(left, top, right - left, bottom - top); return new Rectangle(left, top, right - left, bottom - top);
} }
static centered(width: number, height: number): any { static centered(width: number, height: number) {
return new Rectangle(-Math.ceil(width / 2), -Math.ceil(height / 2), width, height); return new Rectangle(-Math.ceil(width / 2), -Math.ceil(height / 2), width, height);
} }
/** /**
* Returns if a intersects b * Returns if a intersects b
*/ */
static intersects(a: Rectangle, b: Rectangle): any { static intersects(a: Rectangle, b: Rectangle) {
return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom; return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom;
} }
/** /**
@ -54,7 +54,7 @@ export class Rectangle {
/** /**
* Returns if this rectangle is equal to the other while taking an epsilon into account * Returns if this rectangle is equal to the other while taking an epsilon into account
*/ */
equalsEpsilon(other: Rectangle, epsilon: number): any { equalsEpsilon(other: Rectangle, epsilon: number) {
return (epsilonCompare(this.x, other.x, epsilon) && return (epsilonCompare(this.x, other.x, epsilon) &&
epsilonCompare(this.y, other.y, epsilon) && epsilonCompare(this.y, other.y, epsilon) &&
epsilonCompare(this.w, other.w, epsilon) && epsilonCompare(this.w, other.w, epsilon) &&
@ -106,28 +106,28 @@ export class Rectangle {
/** /**
* Sets the right side of the rect without moving it * Sets the right side of the rect without moving it
*/ */
setRight(right: number): any { setRight(right: number) {
this.w = right - this.x; this.w = right - this.x;
} }
/** /**
* Sets the bottom side of the rect without moving it * Sets the bottom side of the rect without moving it
*/ */
setBottom(bottom: number): any { setBottom(bottom: number) {
this.h = bottom - this.y; this.h = bottom - this.y;
} }
/** /**
* Sets the top side of the rect without scaling it * Sets the top side of the rect without scaling it
*/ */
setTop(top: number): any { setTop(top: number) {
const bottom: any = this.bottom(); const bottom = this.bottom();
this.y = top; this.y = top;
this.setBottom(bottom); this.setBottom(bottom);
} }
/** /**
* Sets the left side of the rect without scaling it * Sets the left side of the rect without scaling it
*/ */
setLeft(left: number): any { setLeft(left: number) {
const right: any = this.right(); const right = this.right();
this.x = left; this.x = left;
this.setRight(right); this.setRight(right);
} }
@ -148,14 +148,14 @@ export class Rectangle {
/** /**
* Moves the rectangle by the given parameters * Moves the rectangle by the given parameters
*/ */
moveBy(x: number, y: number): any { moveBy(x: number, y: number) {
this.x += x; this.x += x;
this.y += y; this.y += y;
} }
/** /**
* Moves the rectangle by the given vector * Moves the rectangle by the given vector
*/ */
moveByVector(vec: Vector): any { moveByVector(vec: Vector) {
this.x += vec.x; this.x += vec.x;
this.y += vec.y; this.y += vec.y;
} }
@ -163,7 +163,7 @@ export class Rectangle {
* Scales every parameter (w, h, x, y) by the given factor. Useful to transform from world to * Scales every parameter (w, h, x, y) by the given factor. Useful to transform from world to
* tile space and vice versa * tile space and vice versa
*/ */
allScaled(factor: number): any { allScaled(factor: number) {
return new Rectangle(this.x * factor, this.y * factor, this.w * factor, this.h * factor); return new Rectangle(this.x * factor, this.y * factor, this.w * factor, this.h * factor);
} }
/** /**
@ -212,10 +212,10 @@ export class Rectangle {
* {} * {}
*/ */
getIntersection(rect: Rectangle): Rectangle | null { getIntersection(rect: Rectangle): Rectangle | null {
const left: any = Math.max(this.x, rect.x); const left = Math.max(this.x, rect.x);
const top: any = Math.max(this.y, rect.y); const top = Math.max(this.y, rect.y);
const right: any = Math.min(this.x + this.w, rect.x + rect.w); const right = Math.min(this.x + this.w, rect.x + rect.w);
const bottom: any = Math.min(this.y + this.h, rect.y + rect.h); const bottom = Math.min(this.y + this.h, rect.y + rect.h);
if (right <= left || bottom <= top) { if (right <= left || bottom <= top) {
return null; return null;
} }
@ -224,14 +224,14 @@ export class Rectangle {
/** /**
* Returns whether the rectangle fully intersects the given rectangle * Returns whether the rectangle fully intersects the given rectangle
*/ */
intersectsFully(rect: Rectangle): any { intersectsFully(rect: Rectangle) {
const intersection: any = this.getIntersection(rect); const intersection = this.getIntersection(rect);
return intersection && Math.abs(intersection.w * intersection.h - rect.w * rect.h) < 0.001; return intersection && Math.abs(intersection.w * intersection.h - rect.w * rect.h) < 0.001;
} }
/** /**
* Returns the union of this rectangle with another * Returns the union of this rectangle with another
*/ */
getUnion(rect: Rectangle): any { getUnion(rect: Rectangle) {
if (this.isEmpty()) { if (this.isEmpty()) {
// If this is rect is empty, return the other one // If this is rect is empty, return the other one
return rect.clone(); return rect.clone();
@ -241,16 +241,16 @@ export class Rectangle {
return this.clone(); return this.clone();
} }
// Find contained area // Find contained area
const left: any = Math.min(this.x, rect.x); const left = Math.min(this.x, rect.x);
const top: any = Math.min(this.y, rect.y); const top = Math.min(this.y, rect.y);
const right: any = Math.max(this.right(), rect.right()); const right = Math.max(this.right(), rect.right());
const bottom: any = Math.max(this.bottom(), rect.bottom()); const bottom = Math.max(this.bottom(), rect.bottom());
return Rectangle.fromTRBL(top, right, bottom, left); return Rectangle.fromTRBL(top, right, bottom, left);
} }
/** /**
* Good for caching stuff * Good for caching stuff
*/ */
toCompareableString(): any { toCompareableString() {
return (round2Digits(this.x) + return (round2Digits(this.x) +
"/" + "/" +
round2Digits(this.y) + round2Digits(this.y) +
@ -262,7 +262,7 @@ export class Rectangle {
/** /**
* Good for printing stuff * Good for printing stuff
*/ */
toString(): any { toString() {
return ("[x:" + return ("[x:" +
round2Digits(this.x) + round2Digits(this.x) +
"| y:" + "| y:" +

View File

@ -1,8 +1,8 @@
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { fastArrayDeleteValueIfContained } from "./utils"; import { fastArrayDeleteValueIfContained } from "./utils";
const logger: any = createLogger("request_channel"); const logger = createLogger("request_channel");
// Thrown when a request is aborted // Thrown when a request is aborted
export const PROMISE_ABORTED: any = "promise-aborted"; export const PROMISE_ABORTED = "promise-aborted";
export class RequestChannel { export class RequestChannel {
public pendingPromises: Array<Promise> = []; public pendingPromises: Array<Promise> = [];
@ -14,9 +14,9 @@ export class RequestChannel {
*/ */
watch(promise: Promise<any>): Promise<any> { watch(promise: Promise<any>): Promise<any> {
// log(this, "Added new promise:", promise, "(pending =", this.pendingPromises.length, ")"); // log(this, "Added new promise:", promise, "(pending =", this.pendingPromises.length, ")");
let cancelled: any = false; let cancelled = false;
const wrappedPromise: any = new Promise((resolve: any, reject: any): any => { const wrappedPromise = new Promise((resolve, reject) => {
promise.then((result: any): any => { promise.then(result => {
// Remove from pending promises // Remove from pending promises
fastArrayDeleteValueIfContained(this.pendingPromises, wrappedPromise); fastArrayDeleteValueIfContained(this.pendingPromises, wrappedPromise);
// If not cancelled, resolve promise with same payload // If not cancelled, resolve promise with same payload
@ -27,7 +27,7 @@ export class RequestChannel {
logger.warn("Not resolving because promise got cancelled"); logger.warn("Not resolving because promise got cancelled");
// reject.call(this, PROMISE_ABORTED); // reject.call(this, PROMISE_ABORTED);
} }
}, (err: any): any => { }, err => {
// Remove from pending promises // Remove from pending promises
fastArrayDeleteValueIfContained(this.pendingPromises, wrappedPromise); fastArrayDeleteValueIfContained(this.pendingPromises, wrappedPromise);
// If not cancelled, reject promise with same payload // If not cancelled, reject promise with same payload
@ -42,17 +42,17 @@ export class RequestChannel {
}); });
// Add cancel handler // Add cancel handler
// @ts-ignore // @ts-ignore
wrappedPromise.cancel = function (): any { wrappedPromise.cancel = function () {
cancelled = true; cancelled = true;
}; };
this.pendingPromises.push(wrappedPromise); this.pendingPromises.push(wrappedPromise);
return wrappedPromise; return wrappedPromise;
} }
cancelAll(): any { cancelAll() {
if (this.pendingPromises.length > 0) { if (this.pendingPromises.length > 0) {
logger.log("Cancel all pending promises (", this.pendingPromises.length, ")"); logger.log("Cancel all pending promises (", this.pendingPromises.length, ")");
} }
for (let i: any = 0; i < this.pendingPromises.length; ++i) { for (let i = 0; i < this.pendingPromises.length; ++i) {
// @ts-ignore // @ts-ignore
this.pendingPromises[i].cancel(); this.pendingPromises[i].cancel();
} }

View File

@ -11,23 +11,23 @@ export class RestrictionManager extends ReadWriteProxy {
super(app, "restriction-flags.bin"); super(app, "restriction-flags.bin");
} }
// -- RW Proxy Impl // -- RW Proxy Impl
verify(data: any): any { verify(data: any) {
return ExplainedResult.good(); return ExplainedResult.good();
} }
getDefaultData(): any { getDefaultData() {
return { return {
version: this.getCurrentVersion(), version: this.getCurrentVersion(),
}; };
} }
getCurrentVersion(): any { getCurrentVersion() {
return 1; return 1;
} }
migrate(data: any): any { migrate(data: any) {
return ExplainedResult.good(); return ExplainedResult.good();
} }
initialize(): any { initialize() {
return this.readAsync(); return this.readAsync();
} }
// -- End RW Proxy Impl // -- End RW Proxy Impl

View File

@ -1,11 +1,11 @@
// ALEA RNG // ALEA RNG
function Mash(): any { function Mash() {
var n: any = 0xefc8249d; var n = 0xefc8249d;
return function (data: any): any { return function (data) {
data = data.toString(); data = data.toString();
for (var i: any = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
n += data.charCodeAt(i); n += data.charCodeAt(i);
var h: any = 0.02519603282416938 * n; var h = 0.02519603282416938 * n;
n = h >>> 0; n = h >>> 0;
h -= n; h -= n;
h *= n; h *= n;
@ -16,13 +16,13 @@ function Mash(): any {
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
}; };
} }
function makeNewRng(seed: number | string): any { function makeNewRng(seed: number | string) {
// Johannes Baagøe <baagoe@baagoe.com>, 2010 // Johannes Baagøe <baagoe@baagoe.com>, 2010
var c: any = 1; var c = 1;
var mash: any = Mash(); var mash = Mash();
let s0: any = mash(" "); let s0 = mash(" ");
let s1: any = mash(" "); let s1 = mash(" ");
let s2: any = mash(" "); let s2 = mash(" ");
s0 -= mash(seed); s0 -= mash(seed);
if (s0 < 0) { if (s0 < 0) {
s0 += 1; s0 += 1;
@ -36,16 +36,16 @@ function makeNewRng(seed: number | string): any {
s2 += 1; s2 += 1;
} }
mash = null; mash = null;
var random: any = function (): any { var random = function () {
var t: any = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
s0 = s1; s0 = s1;
s1 = s2; s1 = s2;
return (s2 = t - (c = t | 0)); return (s2 = t - (c = t | 0));
}; };
random.exportState = function (): any { random.exportState = function () {
return [s0, s1, s2, c]; return [s0, s1, s2, c];
}; };
random.importState = function (i: any): any { random.importState = function (i) {
s0 = +i[0] || 0; s0 = +i[0] || 0;
s1 = +i[1] || 0; s1 = +i[1] || 0;
s2 = +i[2] || 0; s2 = +i[2] || 0;
@ -61,7 +61,7 @@ export class RandomNumberGenerator {
/** /**
* Re-seeds the generator * Re-seeds the generator
*/ */
reseed(seed: number | string): any { reseed(seed: number | string) {
this.internalRng = makeNewRng(seed || Math.random()); this.internalRng = makeNewRng(seed || Math.random());
} }
/** /**
@ -73,8 +73,8 @@ export class RandomNumberGenerator {
/** /**
* Random choice of an array * Random choice of an array
*/ */
choice(array: array): any { choice(array: array) {
const index: any = this.nextIntRange(0, array.length); const index = this.nextIntRange(0, array.length);
return array[index]; return array[index];
} }
/** /**
@ -96,7 +96,7 @@ export class RandomNumberGenerator {
/** /**
* Updates the seed * Updates the seed
*/ */
setSeed(seed: number): any { setSeed(seed: number) {
this.internalRng = makeNewRng(seed); this.internalRng = makeNewRng(seed);
} }
} }

View File

@ -1,18 +1,18 @@
import { createHash } from "rusha"; import { createHash } from "rusha";
import crc32 from "crc/crc32"; import crc32 from "crc/crc32";
import { decompressX64 } from "./lzstring"; import { decompressX64 } from "./lzstring";
export function sha1(str: any): any { export function sha1(str) {
return createHash().update(str).digest("hex"); return createHash().update(str).digest("hex");
} }
// Window.location.host // Window.location.host
export function getNameOfProvider(): any { export function getNameOfProvider() {
return window[decompressX64("DYewxghgLgliB2Q")][decompressX64("BYewzgLgdghgtgUyA")]; return window[decompressX64("DYewxghgLgliB2Q")][decompressX64("BYewzgLgdghgtgUyA")];
} }
// Distinguish legacy crc prefixes // Distinguish legacy crc prefixes
export const CRC_PREFIX: any = "crc32".padEnd(32, "-"); export const CRC_PREFIX = "crc32".padEnd(32, "-");
/** /**
* Computes the crc for a given string * Computes the crc for a given string
*/ */
export function computeCrc(str: string): any { export function computeCrc(str: string) {
return CRC_PREFIX + crc32(str).toString(16).padStart(8, "0"); return CRC_PREFIX + crc32(str).toString(16).padStart(8, "0");
} }

View File

@ -1,4 +1,4 @@
export const STOP_PROPAGATION: any = "stop_propagation"; export const STOP_PROPAGATION = "stop_propagation";
export class Signal { export class Signal {
public receivers = []; public receivers = [];
public modifyCount = 0; public modifyCount = 0;
@ -8,7 +8,7 @@ export class Signal {
/** /**
* Adds a new signal listener * Adds a new signal listener
*/ */
add(receiver: function, scope: object = null): any { add(receiver: function, scope: object = null) {
assert(receiver, "receiver is null"); assert(receiver, "receiver is null");
this.receivers.push({ receiver, scope }); this.receivers.push({ receiver, scope });
++this.modifyCount; ++this.modifyCount;
@ -16,7 +16,7 @@ export class Signal {
/** /**
* Adds a new signal listener * Adds a new signal listener
*/ */
addToTop(receiver: function, scope: object = null): any { addToTop(receiver: function, scope: object = null) {
assert(receiver, "receiver is null"); assert(receiver, "receiver is null");
this.receivers.unshift({ receiver, scope }); this.receivers.unshift({ receiver, scope });
++this.modifyCount; ++this.modifyCount;
@ -25,11 +25,11 @@ export class Signal {
* Dispatches the signal * Dispatches the signal
* @param {} payload * @param {} payload
*/ */
dispatch(): any { dispatch() {
const modifyState: any = this.modifyCount; const modifyState = this.modifyCount;
const n: any = this.receivers.length; const n = this.receivers.length;
for (let i: any = 0; i < n; ++i) { for (let i = 0; i < n; ++i) {
const { receiver, scope }: any = this.receivers[i]; const { receiver, scope } = this.receivers[i];
if (receiver.apply(scope, arguments) === STOP_PROPAGATION) { if (receiver.apply(scope, arguments) === STOP_PROPAGATION) {
return STOP_PROPAGATION; return STOP_PROPAGATION;
} }
@ -42,10 +42,10 @@ export class Signal {
/** /**
* Removes a receiver * Removes a receiver
*/ */
remove(receiver: function): any { remove(receiver: function) {
let index: any = null; let index = null;
const n: any = this.receivers.length; const n = this.receivers.length;
for (let i: any = 0; i < n; ++i) { for (let i = 0; i < n; ++i) {
if (this.receivers[i].receiver === receiver) { if (this.receivers[i].receiver === receiver) {
index = i; index = i;
break; break;
@ -58,7 +58,7 @@ export class Signal {
/** /**
* Removes all receivers * Removes all receivers
*/ */
removeAll(): any { removeAll() {
this.receivers = []; this.receivers = [];
++this.modifyCount; ++this.modifyCount;
} }

View File

@ -1,5 +1,5 @@
import { createLogger } from "./logging"; import { createLogger } from "./logging";
const logger: any = createLogger("singleton_factory"); const logger = createLogger("singleton_factory");
// simple factory pattern // simple factory pattern
export class SingletonFactory { export class SingletonFactory {
public id = id; public id = id;
@ -8,14 +8,14 @@ export class SingletonFactory {
constructor(id) { constructor(id) {
} }
getId(): any { getId() {
return this.id; return this.id;
} }
register(classHandle: any): any { register(classHandle) {
// First, construct instance // First, construct instance
const instance: any = new classHandle(); const instance = new classHandle();
// Extract id // Extract id
const id: any = instance.getId(); const id = instance.getId();
assert(id, "Factory: Invalid id for class " + classHandle.name + ": " + id); assert(id, "Factory: Invalid id for class " + classHandle.name + ": " + id);
// Check duplicates // Check duplicates
assert(!this.idToEntry[id], "Duplicate factory entry for " + id); assert(!this.idToEntry[id], "Duplicate factory entry for " + id);
@ -35,7 +35,7 @@ export class SingletonFactory {
* {} * {}
*/ */
findById(id: string): object { findById(id: string): object {
const entry: any = this.idToEntry[id]; const entry = this.idToEntry[id];
if (!entry) { if (!entry) {
logger.error("Object with id", id, "is not registered!"); logger.error("Object with id", id, "is not registered!");
assert(false, "Factory: Object with id '" + id + "' is not registered!"); assert(false, "Factory: Object with id '" + id + "' is not registered!");
@ -49,7 +49,7 @@ export class SingletonFactory {
* {} * {}
*/ */
findByClass(classHandle: object): object { findByClass(classHandle: object): object {
for (let i: any = 0; i < this.entries.length; ++i) { for (let i = 0; i < this.entries.length; ++i) {
if (this.entries[i] instanceof classHandle) { if (this.entries[i] instanceof classHandle) {
return this.entries[i]; return this.entries[i];
} }

View File

@ -1,9 +1,9 @@
import { DrawParameters } from "./draw_parameters"; import { DrawParameters } from "./draw_parameters";
import { Rectangle } from "./rectangle"; import { Rectangle } from "./rectangle";
import { round3Digits } from "./utils"; import { round3Digits } from "./utils";
export const ORIGINAL_SPRITE_SCALE: any = "0.75"; export const ORIGINAL_SPRITE_SCALE = "0.75";
export const FULL_CLIP_RECT: any = new Rectangle(0, 0, 1, 1); export const FULL_CLIP_RECT = new Rectangle(0, 0, 1, 1);
const EXTRUDE: any = 0.1; const EXTRUDE = 0.1;
export class BaseSprite { export class BaseSprite {
/** /**
* Returns the raw handle * Returns the raw handle
@ -17,7 +17,7 @@ export class BaseSprite {
/** /**
* Draws the sprite * Draws the sprite
*/ */
draw(context: CanvasRenderingContext2D, x: number, y: number, w: number, h: number): any { draw(context: CanvasRenderingContext2D, x: number, y: number, w: number, h: number) {
// eslint-disable-line no-unused-vars // eslint-disable-line no-unused-vars
abstract; abstract;
} }
@ -49,18 +49,18 @@ export class AtlasSprite extends BaseSprite {
constructor(spriteName = "sprite") { constructor(spriteName = "sprite") {
super(); super();
} }
getRawTexture(): any { getRawTexture() {
return this.linksByResolution[ORIGINAL_SPRITE_SCALE].atlas; return this.linksByResolution[ORIGINAL_SPRITE_SCALE].atlas;
} }
/** /**
* Draws the sprite onto a regular context using no contexts * Draws the sprite onto a regular context using no contexts
* @see {BaseSprite.draw} * @see {BaseSprite.draw}
*/ */
draw(context: any, x: any, y: any, w: any, h: any): any { draw(context, x, y, w, h) {
if (G_IS_DEV) { if (G_IS_DEV) {
assert(context instanceof CanvasRenderingContext2D, "Not a valid context"); assert(context instanceof CanvasRenderingContext2D, "Not a valid context");
} }
const link: any = this.linksByResolution[ORIGINAL_SPRITE_SCALE]; const link = this.linksByResolution[ORIGINAL_SPRITE_SCALE];
if (!link) { if (!link) {
throw new Error("draw: Link for " + throw new Error("draw: Link for " +
this.spriteName + this.spriteName +
@ -70,30 +70,30 @@ export class AtlasSprite extends BaseSprite {
Object.keys(this.linksByResolution) + Object.keys(this.linksByResolution) +
")"); ")");
} }
const width: any = w || link.w; const width = w || link.w;
const height: any = h || link.h; const height = h || link.h;
const scaleW: any = width / link.w; const scaleW = width / link.w;
const scaleH: any = height / link.h; const scaleH = height / link.h;
context.drawImage(link.atlas, link.packedX, link.packedY, link.packedW, link.packedH, x + link.packOffsetX * scaleW, y + link.packOffsetY * scaleH, link.packedW * scaleW, link.packedH * scaleH); context.drawImage(link.atlas, link.packedX, link.packedY, link.packedW, link.packedH, x + link.packOffsetX * scaleW, y + link.packOffsetY * scaleH, link.packedW * scaleW, link.packedH * scaleH);
} }
drawCachedCentered(parameters: DrawParameters, x: number, y: number, size: number, clipping: boolean= = true): any { drawCachedCentered(parameters: DrawParameters, x: number, y: number, size: number, clipping: boolean= = true) {
this.drawCached(parameters, x - size / 2, y - size / 2, size, size, clipping); this.drawCached(parameters, x - size / 2, y - size / 2, size, size, clipping);
} }
drawCentered(context: CanvasRenderingContext2D, x: number, y: number, size: number): any { drawCentered(context: CanvasRenderingContext2D, x: number, y: number, size: number) {
this.draw(context, x - size / 2, y - size / 2, size, size); this.draw(context, x - size / 2, y - size / 2, size, size);
} }
/** /**
* Draws the sprite * Draws the sprite
*/ */
drawCached(parameters: DrawParameters, x: number, y: number, w: number = null, h: number = null, clipping: boolean= = true): any { drawCached(parameters: DrawParameters, x: number, y: number, w: number = null, h: number = null, clipping: boolean= = true) {
if (G_IS_DEV) { if (G_IS_DEV) {
assert(parameters instanceof DrawParameters, "Not a valid context"); assert(parameters instanceof DrawParameters, "Not a valid context");
assert(!!w && w > 0, "Not a valid width:" + w); assert(!!w && w > 0, "Not a valid width:" + w);
assert(!!h && h > 0, "Not a valid height:" + h); assert(!!h && h > 0, "Not a valid height:" + h);
} }
const visibleRect: any = parameters.visibleRect; const visibleRect = parameters.visibleRect;
const scale: any = parameters.desiredAtlasScale; const scale = parameters.desiredAtlasScale;
const link: any = this.linksByResolution[scale]; const link = this.linksByResolution[scale];
if (!link) { if (!link) {
throw new Error("drawCached: Link for " + throw new Error("drawCached: Link for " +
this.spriteName + this.spriteName +
@ -103,19 +103,19 @@ export class AtlasSprite extends BaseSprite {
Object.keys(this.linksByResolution) + Object.keys(this.linksByResolution) +
")"); ")");
} }
const scaleW: any = w / link.w; const scaleW = w / link.w;
const scaleH: any = h / link.h; const scaleH = h / link.h;
let destX: any = x + link.packOffsetX * scaleW; let destX = x + link.packOffsetX * scaleW;
let destY: any = y + link.packOffsetY * scaleH; let destY = y + link.packOffsetY * scaleH;
let destW: any = link.packedW * scaleW; let destW = link.packedW * scaleW;
let destH: any = link.packedH * scaleH; let destH = link.packedH * scaleH;
let srcX: any = link.packedX; let srcX = link.packedX;
let srcY: any = link.packedY; let srcY = link.packedY;
let srcW: any = link.packedW; let srcW = link.packedW;
let srcH: any = link.packedH; let srcH = link.packedH;
let intersection: any = null; let intersection = null;
if (clipping) { if (clipping) {
const rect: any = new Rectangle(destX, destY, destW, destH); const rect = new Rectangle(destX, destY, destW, destH);
intersection = rect.getIntersection(visibleRect); intersection = rect.getIntersection(visibleRect);
if (!intersection) { if (!intersection) {
return; return;
@ -140,15 +140,15 @@ export class AtlasSprite extends BaseSprite {
/** /**
* Draws a subset of the sprite. Does NO culling * Draws a subset of the sprite. Does NO culling
*/ */
drawCachedWithClipRect(parameters: DrawParameters, x: number, y: number, w: number = null, h: number = null, clipRect: Rectangle= = FULL_CLIP_RECT): any { drawCachedWithClipRect(parameters: DrawParameters, x: number, y: number, w: number = null, h: number = null, clipRect: Rectangle= = FULL_CLIP_RECT) {
if (G_IS_DEV) { if (G_IS_DEV) {
assert(parameters instanceof DrawParameters, "Not a valid context"); assert(parameters instanceof DrawParameters, "Not a valid context");
assert(!!w && w > 0, "Not a valid width:" + w); assert(!!w && w > 0, "Not a valid width:" + w);
assert(!!h && h > 0, "Not a valid height:" + h); assert(!!h && h > 0, "Not a valid height:" + h);
assert(clipRect, "No clip rect given!"); assert(clipRect, "No clip rect given!");
} }
const scale: any = parameters.desiredAtlasScale; const scale = parameters.desiredAtlasScale;
const link: any = this.linksByResolution[scale]; const link = this.linksByResolution[scale];
if (!link) { if (!link) {
throw new Error("drawCachedWithClipRect: Link for " + throw new Error("drawCachedWithClipRect: Link for " +
this.spriteName + this.spriteName +
@ -158,16 +158,16 @@ export class AtlasSprite extends BaseSprite {
Object.keys(this.linksByResolution) + Object.keys(this.linksByResolution) +
")"); ")");
} }
const scaleW: any = w / link.w; const scaleW = w / link.w;
const scaleH: any = h / link.h; const scaleH = h / link.h;
let destX: any = x + link.packOffsetX * scaleW + clipRect.x * w; let destX = x + link.packOffsetX * scaleW + clipRect.x * w;
let destY: any = y + link.packOffsetY * scaleH + clipRect.y * h; let destY = y + link.packOffsetY * scaleH + clipRect.y * h;
let destW: any = link.packedW * scaleW * clipRect.w; let destW = link.packedW * scaleW * clipRect.w;
let destH: any = link.packedH * scaleH * clipRect.h; let destH = link.packedH * scaleH * clipRect.h;
let srcX: any = link.packedX + clipRect.x * link.packedW; let srcX = link.packedX + clipRect.x * link.packedW;
let srcY: any = link.packedY + clipRect.y * link.packedH; let srcY = link.packedY + clipRect.y * link.packedH;
let srcW: any = link.packedW * clipRect.w; let srcW = link.packedW * clipRect.w;
let srcH: any = link.packedH * clipRect.h; let srcH = link.packedH * clipRect.h;
parameters.context.drawImage(link.atlas, parameters.context.drawImage(link.atlas,
// atlas src pos // atlas src pos
srcX, srcY, srcX, srcY,
@ -179,15 +179,15 @@ export class AtlasSprite extends BaseSprite {
/** /**
* Renders into an html element * Renders into an html element
*/ */
renderToHTMLElement(element: HTMLElement, w: number = 1, h: number = 1): any { renderToHTMLElement(element: HTMLElement, w: number = 1, h: number = 1) {
element.style.position = "relative"; element.style.position = "relative";
element.innerHTML = this.getAsHTML(w, h); element.innerHTML = this.getAsHTML(w, h);
} }
/** /**
* Returns the html to render as icon * Returns the html to render as icon
*/ */
getAsHTML(w: number, h: number): any { getAsHTML(w: number, h: number) {
const link: any = this.linksByResolution["0.5"]; const link = this.linksByResolution["0.5"];
if (!link) { if (!link) {
throw new Error("getAsHTML: Link for " + throw new Error("getAsHTML: Link for " +
this.spriteName + this.spriteName +
@ -197,30 +197,30 @@ export class AtlasSprite extends BaseSprite {
")"); ")");
} }
// Find out how much we have to scale it so that it fits // Find out how much we have to scale it so that it fits
const scaleX: any = w / link.w; const scaleX = w / link.w;
const scaleY: any = h / link.h; const scaleY = h / link.h;
// Find out how big the scaled atlas is // Find out how big the scaled atlas is
const atlasW: any = link.atlas.width * scaleX; const atlasW = link.atlas.width * scaleX;
const atlasH: any = link.atlas.height * scaleY; const atlasH = link.atlas.height * scaleY;
// @ts-ignore // @ts-ignore
const srcSafe: any = link.atlas.src.replaceAll("\\", "/"); const srcSafe = link.atlas.src.replaceAll("\\", "/");
// Find out how big we render the sprite // Find out how big we render the sprite
const widthAbsolute: any = scaleX * link.packedW; const widthAbsolute = scaleX * link.packedW;
const heightAbsolute: any = scaleY * link.packedH; const heightAbsolute = scaleY * link.packedH;
// Compute the position in the relative container // Compute the position in the relative container
const leftRelative: any = (link.packOffsetX * scaleX) / w; const leftRelative = (link.packOffsetX * scaleX) / w;
const topRelative: any = (link.packOffsetY * scaleY) / h; const topRelative = (link.packOffsetY * scaleY) / h;
const widthRelative: any = widthAbsolute / w; const widthRelative = widthAbsolute / w;
const heightRelative: any = heightAbsolute / h; const heightRelative = heightAbsolute / h;
// Scale the atlas relative to the width and height of the element // Scale the atlas relative to the width and height of the element
const bgW: any = atlasW / widthAbsolute; const bgW = atlasW / widthAbsolute;
const bgH: any = atlasH / heightAbsolute; const bgH = atlasH / heightAbsolute;
// Figure out what the position of the atlas is // Figure out what the position of the atlas is
const bgX: any = link.packedX * scaleX; const bgX = link.packedX * scaleX;
const bgY: any = link.packedY * scaleY; const bgY = link.packedY * scaleY;
// Fuck you, whoever thought its a good idea to make background-position work like it does now // Fuck you, whoever thought its a good idea to make background-position work like it does now
const bgXRelative: any = -bgX / (widthAbsolute - atlasW); const bgXRelative = -bgX / (widthAbsolute - atlasW);
const bgYRelative: any = -bgY / (heightAbsolute - atlasH); const bgYRelative = -bgY / (heightAbsolute - atlasH);
return ` return `
<span class="spritesheetImage" style=" <span class="spritesheetImage" style="
background-image: url('${srcSafe}'); background-image: url('${srcSafe}');
@ -243,14 +243,14 @@ export class RegularSprite extends BaseSprite {
constructor(sprite, w, h) { constructor(sprite, w, h) {
super(); super();
} }
getRawTexture(): any { getRawTexture() {
return this.sprite; return this.sprite;
} }
/** /**
* Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing * Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing
* images into buffers * images into buffers
*/ */
draw(context: CanvasRenderingContext2D, x: number, y: number, w: number, h: number): any { draw(context: CanvasRenderingContext2D, x: number, y: number, w: number, h: number) {
assert(context, "No context given"); assert(context, "No context given");
assert(x !== undefined, "No x given"); assert(x !== undefined, "No x given");
assert(y !== undefined, "No y given"); assert(y !== undefined, "No y given");
@ -262,7 +262,7 @@ export class RegularSprite extends BaseSprite {
* Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing * Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing
* images into buffers * images into buffers
*/ */
drawCentered(context: CanvasRenderingContext2D, x: number, y: number, w: number, h: number): any { drawCentered(context: CanvasRenderingContext2D, x: number, y: number, w: number, h: number) {
assert(context, "No context given"); assert(context, "No context given");
assert(x !== undefined, "No x given"); assert(x !== undefined, "No x given");
assert(y !== undefined, "No y given"); assert(y !== undefined, "No y given");

View File

@ -3,7 +3,7 @@ import { Entity } from "../game/entity";
import { globalConfig } from "./config"; import { globalConfig } from "./config";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { Rectangle } from "./rectangle"; import { Rectangle } from "./rectangle";
const logger: any = createLogger("stale_areas"); const logger = createLogger("stale_areas");
export class StaleAreaDetector { export class StaleAreaDetector {
public root = root; public root = root;
public name = name; public name = name;
@ -15,7 +15,7 @@ export class StaleAreaDetector {
/** /**
* Invalidates the given area * Invalidates the given area
*/ */
invalidate(area: Rectangle): any { invalidate(area: Rectangle) {
// logger.log(this.name, "invalidated", area.toString()); // logger.log(this.name, "invalidated", area.toString());
if (this.staleArea) { if (this.staleArea) {
this.staleArea = this.staleArea.getUnion(area); this.staleArea = this.staleArea.getUnion(area);
@ -28,20 +28,20 @@ export class StaleAreaDetector {
* Makes this detector recompute the area of an entity whenever * Makes this detector recompute the area of an entity whenever
* it changes in any way * it changes in any way
*/ */
recomputeOnComponentsChanged(components: Array<typeof Component>, tilesAround: number): any { recomputeOnComponentsChanged(components: Array<typeof Component>, tilesAround: number) {
const componentIds: any = components.map((component: any): any => component.getId()); const componentIds = components.map(component => component.getId());
/** /**
* Internal checker method * Internal checker method
*/ */
const checker: any = (entity: Entity): any => { const checker = (entity: Entity) => {
if (!this.root.gameInitialized) { if (!this.root.gameInitialized) {
return; return;
} }
// Check for all components // Check for all components
for (let i: any = 0; i < componentIds.length; ++i) { for (let i = 0; i < componentIds.length; ++i) {
if (entity.components[componentIds[i]]) { if (entity.components[componentIds[i]]) {
// Entity is relevant, compute affected area // Entity is relevant, compute affected area
const area: any = entity.components.StaticMapEntity.getTileSpaceBounds().expandedInAllDirections(tilesAround); const area = entity.components.StaticMapEntity.getTileSpaceBounds().expandedInAllDirections(tilesAround);
this.invalidate(area); this.invalidate(area);
return; return;
} }
@ -56,7 +56,7 @@ export class StaleAreaDetector {
/** /**
* Updates the stale area * Updates the stale area
*/ */
update(): any { update() {
if (this.staleArea) { if (this.staleArea) {
if (G_IS_DEV && globalConfig.debug.renderChanges) { if (G_IS_DEV && globalConfig.debug.renderChanges) {
logger.log(this.name, "is recomputing", this.staleArea.toString()); logger.log(this.name, "is recomputing", this.staleArea.toString());

View File

@ -5,7 +5,7 @@ import { GameState } from "./game_state";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { waitNextFrame, removeAllChildren } from "./utils"; import { waitNextFrame, removeAllChildren } from "./utils";
import { MOD_SIGNALS } from "../mods/mod_signals"; import { MOD_SIGNALS } from "../mods/mod_signals";
const logger: any = createLogger("state_manager"); const logger = createLogger("state_manager");
/** /**
* This is the main state machine which drives the game states. * This is the main state machine which drives the game states.
*/ */
@ -21,18 +21,18 @@ export class StateManager {
/** /**
* Registers a new state class, should be a GameState derived class * Registers a new state class, should be a GameState derived class
*/ */
register(stateClass: object): any { register(stateClass: object) {
// Create a dummy to retrieve the key // Create a dummy to retrieve the key
const dummy: any = new stateClass(); const dummy = new stateClass();
assert(dummy instanceof GameState, "Not a state!"); assert(dummy instanceof GameState, "Not a state!");
const key: any = dummy.getKey(); const key = dummy.getKey();
assert(!this.stateClasses[key], `State '${key}' is already registered!`); assert(!this.stateClasses[key], `State '${key}' is already registered!`);
this.stateClasses[key] = stateClass; this.stateClasses[key] = stateClass;
} }
/** /**
* Constructs a new state or returns the instance from the cache * Constructs a new state or returns the instance from the cache
*/ */
constructState(key: string): any { constructState(key: string) {
if (this.stateClasses[key]) { if (this.stateClasses[key]) {
return new this.stateClasses[key](); return new this.stateClasses[key]();
} }
@ -41,7 +41,7 @@ export class StateManager {
/** /**
* Moves to a given state * Moves to a given state
*/ */
moveToState(key: string, payload: any = {}): any { moveToState(key: string, payload = {}) {
if (window.APP_ERROR_OCCURED) { if (window.APP_ERROR_OCCURED) {
console.warn("Skipping state transition because of application crash"); console.warn("Skipping state transition because of application crash");
return; return;
@ -53,7 +53,7 @@ export class StateManager {
} }
this.currentState.internalLeaveCallback(); this.currentState.internalLeaveCallback();
// Remove all references // Remove all references
for (const stateKey: any in this.currentState) { for (const stateKey in this.currentState) {
if (this.currentState.hasOwnProperty(stateKey)) { if (this.currentState.hasOwnProperty(stateKey)) {
delete this.currentState[stateKey]; delete this.currentState[stateKey];
} }
@ -71,13 +71,13 @@ export class StateManager {
if (this.currentState.getRemovePreviousContent()) { if (this.currentState.getRemovePreviousContent()) {
document.body.innerHTML = this.currentState.internalGetFullHtml(); document.body.innerHTML = this.currentState.internalGetFullHtml();
} }
const dialogParent: any = document.createElement("div"); const dialogParent = document.createElement("div");
dialogParent.classList.add("modalDialogParent"); dialogParent.classList.add("modalDialogParent");
document.body.appendChild(dialogParent); document.body.appendChild(dialogParent);
try { try {
this.currentState.internalEnterCallback(payload); this.currentState.internalEnterCallback(payload);
} }
catch (ex: any) { catch (ex) {
console.error(ex); console.error(ex);
throw ex; throw ex;
} }
@ -88,7 +88,7 @@ export class StateManager {
key, key,
}, key); }, key);
MOD_SIGNALS.stateEntered.dispatch(this.currentState); MOD_SIGNALS.stateEntered.dispatch(this.currentState);
waitNextFrame().then((): any => { waitNextFrame().then(() => {
document.body.classList.add("arrived"); document.body.classList.add("arrived");
}); });
return true; return true;

View File

@ -1,45 +1,45 @@
import { T } from "../translations"; import { T } from "../translations";
import { openStandaloneLink } from "./config"; import { openStandaloneLink } from "./config";
export let WEB_STEAM_SSO_AUTHENTICATED: any = false; export let WEB_STEAM_SSO_AUTHENTICATED = false;
export async function authorizeViaSSOToken(app: any, dialogs: any): any { export async function authorizeViaSSOToken(app, dialogs) {
if (G_IS_STANDALONE) { if (G_IS_STANDALONE) {
return; return;
} }
if (window.location.search.includes("sso_logout_silent")) { if (window.location.search.includes("sso_logout_silent")) {
window.localStorage.setItem("steam_sso_auth_token", ""); window.localStorage.setItem("steam_sso_auth_token", "");
window.location.replace("/"); window.location.replace("/");
return new Promise((): any => null); return new Promise(() => null);
} }
if (window.location.search.includes("sso_logout")) { if (window.location.search.includes("sso_logout")) {
const { ok }: any = dialogs.showWarning(T.dialogs.steamSsoError.title, T.dialogs.steamSsoError.desc); const { ok } = dialogs.showWarning(T.dialogs.steamSsoError.title, T.dialogs.steamSsoError.desc);
window.localStorage.setItem("steam_sso_auth_token", ""); window.localStorage.setItem("steam_sso_auth_token", "");
ok.add((): any => window.location.replace("/")); ok.add(() => window.location.replace("/"));
return new Promise((): any => null); return new Promise(() => null);
} }
if (window.location.search.includes("steam_sso_no_ownership")) { if (window.location.search.includes("steam_sso_no_ownership")) {
const { ok, getStandalone }: any = dialogs.showWarning(T.dialogs.steamSsoNoOwnership.title, T.dialogs.steamSsoNoOwnership.desc, ["ok", "getStandalone:good"]); const { ok, getStandalone } = dialogs.showWarning(T.dialogs.steamSsoNoOwnership.title, T.dialogs.steamSsoNoOwnership.desc, ["ok", "getStandalone:good"]);
window.localStorage.setItem("steam_sso_auth_token", ""); window.localStorage.setItem("steam_sso_auth_token", "");
getStandalone.add((): any => { getStandalone.add(() => {
openStandaloneLink(app, "sso_ownership"); openStandaloneLink(app, "sso_ownership");
window.location.replace("/"); window.location.replace("/");
}); });
ok.add((): any => window.location.replace("/")); ok.add(() => window.location.replace("/"));
return new Promise((): any => null); return new Promise(() => null);
} }
const token: any = window.localStorage.getItem("steam_sso_auth_token"); const token = window.localStorage.getItem("steam_sso_auth_token");
if (!token) { if (!token) {
return Promise.resolve(); return Promise.resolve();
} }
const apiUrl: any = app.clientApi.getEndpoint(); const apiUrl = app.clientApi.getEndpoint();
console.warn("Authorizing via token:", token); console.warn("Authorizing via token:", token);
const verify: any = async (): any => { const verify = async () => {
const token: any = window.localStorage.getItem("steam_sso_auth_token"); const token = window.localStorage.getItem("steam_sso_auth_token");
if (!token) { if (!token) {
window.location.replace("?sso_logout"); window.location.replace("?sso_logout");
return; return;
} }
try { try {
const response: any = await Promise.race([ const response = await Promise.race([
fetch(apiUrl + "/v1/sso/refresh", { fetch(apiUrl + "/v1/sso/refresh", {
method: "POST", method: "POST",
body: token, body: token,
@ -47,11 +47,11 @@ export async function authorizeViaSSOToken(app: any, dialogs: any): any {
"x-api-key": "d5c54aaa491f200709afff082c153ef2", "x-api-key": "d5c54aaa491f200709afff082c153ef2",
}, },
}), }),
new Promise((resolve: any, reject: any): any => { new Promise((resolve, reject) => {
setTimeout((): any => reject("timeout exceeded"), 20000); setTimeout(() => reject("timeout exceeded"), 20000);
}), }),
]); ]);
const responseText: any = await response.json(); const responseText = await response.json();
if (!responseText.token) { if (!responseText.token) {
console.warn("Failed to register"); console.warn("Failed to register");
window.localStorage.setItem("steam_sso_auth_token", ""); window.localStorage.setItem("steam_sso_auth_token", "");
@ -62,11 +62,11 @@ export async function authorizeViaSSOToken(app: any, dialogs: any): any {
app.clientApi.token = responseText.token; app.clientApi.token = responseText.token;
WEB_STEAM_SSO_AUTHENTICATED = true; WEB_STEAM_SSO_AUTHENTICATED = true;
} }
catch (ex: any) { catch (ex) {
console.warn("Auth failure", ex); console.warn("Auth failure", ex);
window.localStorage.setItem("steam_sso_auth_token", ""); window.localStorage.setItem("steam_sso_auth_token", "");
window.location.replace("/"); window.location.replace("/");
return new Promise((): any => null); return new Promise(() => null);
} }
}; };
await verify(); await verify();

View File

@ -22,7 +22,7 @@ export class TextualGameState extends GameState {
/** /**
* Should return the states HTML content. * Should return the states HTML content.
*/ */
getMainContentHTML(): any { getMainContentHTML() {
return ""; return "";
} }
/** /**
@ -38,7 +38,7 @@ export class TextualGameState extends GameState {
* Back button handler, can be overridden. Per default it goes back to the main menu, * Back button handler, can be overridden. Per default it goes back to the main menu,
* or if coming from the game it moves back to the game again. * or if coming from the game it moves back to the game again.
*/ */
onBackButton(): any { onBackButton() {
if (this.backToStateId) { if (this.backToStateId) {
this.moveToState(this.backToStateId, this.backToStatePayload); this.moveToState(this.backToStateId, this.backToStatePayload);
} }
@ -49,13 +49,13 @@ export class TextualGameState extends GameState {
/** /**
* Returns the default state to go back to * Returns the default state to go back to
*/ */
getDefaultPreviousState(): any { getDefaultPreviousState() {
return "MainMenuState"; return "MainMenuState";
} }
/** /**
* Goes to a new state, telling him to go back to this state later * Goes to a new state, telling him to go back to this state later
*/ */
moveToStateAddGoBack(stateId: string): any { moveToStateAddGoBack(stateId: string) {
this.moveToState(stateId, { this.moveToState(stateId, {
backToStateId: this.key, backToStateId: this.key,
backToStatePayload: { backToStatePayload: {
@ -68,9 +68,9 @@ export class TextualGameState extends GameState {
* Removes all click detectors, except the one on the back button. Useful when regenerating * Removes all click detectors, except the one on the back button. Useful when regenerating
* content. * content.
*/ */
clearClickDetectorsExceptHeader(): any { clearClickDetectorsExceptHeader() {
for (let i: any = 0; i < this.clickDetectors.length; ++i) { for (let i = 0; i < this.clickDetectors.length; ++i) {
const detector: any = this.clickDetectors[i]; const detector = this.clickDetectors[i];
if (detector.element === this.headerElement) { if (detector.element === this.headerElement) {
continue; continue;
} }
@ -82,8 +82,8 @@ export class TextualGameState extends GameState {
/** /**
* Overrides the GameState implementation to provide our own html * Overrides the GameState implementation to provide our own html
*/ */
internalGetFullHtml(): any { internalGetFullHtml() {
let headerHtml: any = ""; let headerHtml = "";
if (this.getStateHeaderTitle()) { if (this.getStateHeaderTitle()) {
headerHtml = ` headerHtml = `
<div class="headerBar"> <div class="headerBar">
@ -103,14 +103,14 @@ export class TextualGameState extends GameState {
/** /**
* Overrides the GameState leave callback to cleanup stuff * Overrides the GameState leave callback to cleanup stuff
*/ */
internalLeaveCallback(): any { internalLeaveCallback() {
super.internalLeaveCallback(); super.internalLeaveCallback();
this.dialogs.cleanup(); this.dialogs.cleanup();
} }
/** /**
* Overrides the GameState enter callback to setup required stuff * Overrides the GameState enter callback to setup required stuff
*/ */
internalEnterCallback(payload: any): any { internalEnterCallback(payload: any) {
super.internalEnterCallback(payload, false); super.internalEnterCallback(payload, false);
if (payload.backToStateId) { if (payload.backToStateId) {
this.backToStateId = payload.backToStateId; this.backToStateId = payload.backToStateId;
@ -126,7 +126,7 @@ export class TextualGameState extends GameState {
this.trackClicks(this.headerElement, this.onBackButton); this.trackClicks(this.headerElement, this.onBackButton);
} }
this.dialogs = new HUDModalDialogs(null, this.app); this.dialogs = new HUDModalDialogs(null, this.app);
const dialogsElement: any = document.body.querySelector(".modalDialogParent"); const dialogsElement = document.body.querySelector(".modalDialogParent");
this.dialogs.initializeToElement(dialogsElement); this.dialogs.initializeToElement(dialogsElement);
this.onEnter(payload); this.onEnter(payload);
} }

View File

@ -9,10 +9,10 @@ export class TrackedState {
} }
} }
} }
set(value: any, changeHandler: any = null, changeScope: any = null): any { set(value, changeHandler = null, changeScope = null) {
if (value !== this.lastSeenValue) { if (value !== this.lastSeenValue) {
// Copy value since the changeHandler call could actually modify our lastSeenValue // Copy value since the changeHandler call could actually modify our lastSeenValue
const valueCopy: any = value; const valueCopy = value;
this.lastSeenValue = value; this.lastSeenValue = value;
if (changeHandler) { if (changeHandler) {
if (changeScope) { if (changeScope) {
@ -30,10 +30,10 @@ export class TrackedState {
} }
} }
} }
setSilent(value: any): any { setSilent(value) {
this.lastSeenValue = value; this.lastSeenValue = value;
} }
get(): any { get() {
return this.lastSeenValue; return this.lastSeenValue;
} }
} }

View File

@ -1,7 +1,7 @@
import { T } from "../translations"; import { T } from "../translations";
import { rando } from "@nastyox/rando.js"; import { rando } from "@nastyox/rando.js";
import { WEB_STEAM_SSO_AUTHENTICATED } from "./steam_sso"; import { WEB_STEAM_SSO_AUTHENTICATED } from "./steam_sso";
const bigNumberSuffixTranslationKeys: any = ["thousands", "millions", "billions", "trillions"]; const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"];
/** /**
* Returns a platform name * Returns a platform name
* {} * {}
@ -20,8 +20,8 @@ export function getPlatformName(): "android" | "browser" | "ios" | "standalone"
* {} * {}
*/ */
export function make2DUndefinedArray(w: number, h: number): Array<Array<any>> { export function make2DUndefinedArray(w: number, h: number): Array<Array<any>> {
const result: any = new Array(w); const result = new Array(w);
for (let x: any = 0; x < w; ++x) { for (let x = 0; x < w; ++x) {
result[x] = new Array(h); result[x] = new Array(h);
} }
return result; return result;
@ -29,21 +29,21 @@ export function make2DUndefinedArray(w: number, h: number): Array<Array<any>> {
/** /**
* Creates a new map (an empty object without any props) * Creates a new map (an empty object without any props)
*/ */
export function newEmptyMap(): any { export function newEmptyMap() {
return Object.create(null); return Object.create(null);
} }
/** /**
* Returns a random integer in the range [start,end] * Returns a random integer in the range [start,end]
*/ */
export function randomInt(start: number, end: number): any { export function randomInt(start: number, end: number) {
return rando(start, end); return rando(start, end);
} }
/** /**
* Access an object in a very annoying way, used for obsfuscation. * Access an object in a very annoying way, used for obsfuscation.
*/ */
export function accessNestedPropertyReverse(obj: any, keys: Array<string>): any { export function accessNestedPropertyReverse(obj: any, keys: Array<string>) {
let result: any = obj; let result = obj;
for (let i: any = keys.length - 1; i >= 0; --i) { for (let i = keys.length - 1; i >= 0; --i) {
result = result[keys[i]]; result = result[keys[i]];
} }
return result; return result;
@ -59,14 +59,14 @@ export function randomChoice(arr: T[]): T {
/** /**
* Deletes from an array by swapping with the last element * Deletes from an array by swapping with the last element
*/ */
export function fastArrayDelete(array: Array<any>, index: number): any { export function fastArrayDelete(array: Array<any>, index: number) {
if (index < 0 || index >= array.length) { if (index < 0 || index >= array.length) {
throw new Error("Out of bounds"); throw new Error("Out of bounds");
} }
// When the element is not the last element // When the element is not the last element
if (index !== array.length - 1) { if (index !== array.length - 1) {
// Get the last element, and swap it with the one we want to delete // Get the last element, and swap it with the one we want to delete
const last: any = array[array.length - 1]; const last = array[array.length - 1];
array[index] = last; array[index] = last;
} }
// Finally remove the last element // Finally remove the last element
@ -76,11 +76,11 @@ export function fastArrayDelete(array: Array<any>, index: number): any {
* Deletes from an array by swapping with the last element. Searches * Deletes from an array by swapping with the last element. Searches
* for the value in the array first * for the value in the array first
*/ */
export function fastArrayDeleteValue(array: Array<any>, value: any): any { export function fastArrayDeleteValue(array: Array<any>, value: any) {
if (array == null) { if (array == null) {
throw new Error("Tried to delete from non array!"); throw new Error("Tried to delete from non array!");
} }
const index: any = array.indexOf(value); const index = array.indexOf(value);
if (index < 0) { if (index < 0) {
console.error("Value", value, "not contained in array:", array, "!"); console.error("Value", value, "not contained in array:", array, "!");
return value; return value;
@ -90,11 +90,11 @@ export function fastArrayDeleteValue(array: Array<any>, value: any): any {
/** /**
* @see fastArrayDeleteValue * @see fastArrayDeleteValue
*/ */
export function fastArrayDeleteValueIfContained(array: Array<any>, value: any): any { export function fastArrayDeleteValueIfContained(array: Array<any>, value: any) {
if (array == null) { if (array == null) {
throw new Error("Tried to delete from non array!"); throw new Error("Tried to delete from non array!");
} }
const index: any = array.indexOf(value); const index = array.indexOf(value);
if (index < 0) { if (index < 0) {
return value; return value;
} }
@ -103,7 +103,7 @@ export function fastArrayDeleteValueIfContained(array: Array<any>, value: any):
/** /**
* Deletes from an array at the given index * Deletes from an array at the given index
*/ */
export function arrayDelete(array: Array<any>, index: number): any { export function arrayDelete(array: Array<any>, index: number) {
if (index < 0 || index >= array.length) { if (index < 0 || index >= array.length) {
throw new Error("Out of bounds"); throw new Error("Out of bounds");
} }
@ -112,11 +112,11 @@ export function arrayDelete(array: Array<any>, index: number): any {
/** /**
* Deletes the given value from an array * Deletes the given value from an array
*/ */
export function arrayDeleteValue(array: Array<any>, value: any): any { export function arrayDeleteValue(array: Array<any>, value: any) {
if (array == null) { if (array == null) {
throw new Error("Tried to delete from non array!"); throw new Error("Tried to delete from non array!");
} }
const index: any = array.indexOf(value); const index = array.indexOf(value);
if (index < 0) { if (index < 0) {
console.error("Value", value, "not contained in array:", array, "!"); console.error("Value", value, "not contained in array:", array, "!");
return value; return value;
@ -127,26 +127,26 @@ export function arrayDeleteValue(array: Array<any>, value: any): any {
* Compare two floats for epsilon equality * Compare two floats for epsilon equality
* {} * {}
*/ */
export function epsilonCompare(a: number, b: number, epsilon: any = 1e-5): boolean { export function epsilonCompare(a: number, b: number, epsilon = 1e-5): boolean {
return Math.abs(a - b) < epsilon; return Math.abs(a - b) < epsilon;
} }
/** /**
* Interpolates two numbers * Interpolates two numbers
*/ */
export function lerp(a: number, b: number, x: number): any { export function lerp(a: number, b: number, x: number) {
return a * (1 - x) + b * x; return a * (1 - x) + b * x;
} }
/** /**
* Finds a value which is nice to display, e.g. 15669 -> 15000. Also handles fractional stuff * Finds a value which is nice to display, e.g. 15669 -> 15000. Also handles fractional stuff
*/ */
export function findNiceValue(num: number): any { export function findNiceValue(num: number) {
if (num > 1e8) { if (num > 1e8) {
return num; return num;
} }
if (num < 0.00001) { if (num < 0.00001) {
return 0; return 0;
} }
let roundAmount: any = 1; let roundAmount = 1;
if (num > 50000) { if (num > 50000) {
roundAmount = 10000; roundAmount = 10000;
} }
@ -168,7 +168,7 @@ export function findNiceValue(num: number): any {
else if (num > 20) { else if (num > 20) {
roundAmount = 5; roundAmount = 5;
} }
const niceValue: any = Math.floor(num / roundAmount) * roundAmount; const niceValue = Math.floor(num / roundAmount) * roundAmount;
if (num >= 10) { if (num >= 10) {
return Math.round(niceValue); return Math.round(niceValue);
} }
@ -181,7 +181,7 @@ export function findNiceValue(num: number): any {
* Finds a nice integer value * Finds a nice integer value
* @see findNiceValue * @see findNiceValue
*/ */
export function findNiceIntegerValue(num: number): any { export function findNiceIntegerValue(num: number) {
return Math.ceil(findNiceValue(num)); return Math.ceil(findNiceValue(num));
} }
/** /**
@ -189,7 +189,7 @@ export function findNiceIntegerValue(num: number): any {
* {} * {}
*/ */
export function formatBigNumber(num: number, separator: string= = T.global.decimalSeparator): string { export function formatBigNumber(num: number, separator: string= = T.global.decimalSeparator): string {
const sign: any = num < 0 ? "-" : ""; const sign = num < 0 ? "-" : "";
num = Math.abs(num); num = Math.abs(num);
if (num > 1e54) { if (num > 1e54) {
return sign + T.global.infinite; return sign + T.global.infinite;
@ -205,17 +205,17 @@ export function formatBigNumber(num: number, separator: string= = T.global.decim
return sign + "" + num; return sign + "" + num;
} }
else { else {
let leadingDigits: any = num; let leadingDigits = num;
let suffix: any = ""; let suffix = "";
for (let suffixIndex: any = 0; suffixIndex < bigNumberSuffixTranslationKeys.length; ++suffixIndex) { for (let suffixIndex = 0; suffixIndex < bigNumberSuffixTranslationKeys.length; ++suffixIndex) {
leadingDigits = leadingDigits / 1000; leadingDigits = leadingDigits / 1000;
suffix = T.global.suffix[bigNumberSuffixTranslationKeys[suffixIndex]]; suffix = T.global.suffix[bigNumberSuffixTranslationKeys[suffixIndex]];
if (leadingDigits < 1000) { if (leadingDigits < 1000) {
break; break;
} }
} }
const leadingDigitsRounded: any = round1Digit(leadingDigits); const leadingDigitsRounded = round1Digit(leadingDigits);
const leadingDigitsNoTrailingDecimal: any = leadingDigitsRounded const leadingDigitsNoTrailingDecimal = leadingDigitsRounded
.toString() .toString()
.replace(".0", "") .replace(".0", "")
.replace(".", separator); .replace(".", separator);
@ -233,8 +233,8 @@ export function formatBigNumberFull(num: number, divider: string= = T.global.tho
if (num > 1e54) { if (num > 1e54) {
return T.global.infinite; return T.global.infinite;
} }
let rest: any = num; let rest = num;
let out: any = ""; let out = "";
while (rest >= 1000) { while (rest >= 1000) {
out = (rest % 1000).toString().padStart(3, "0") + divider + out; out = (rest % 1000).toString().padStart(3, "0") + divider + out;
rest = Math.floor(rest / 1000); rest = Math.floor(rest / 1000);
@ -247,9 +247,9 @@ export function formatBigNumberFull(num: number, divider: string= = T.global.tho
* {} * {}
*/ */
export function waitNextFrame(): Promise<void> { export function waitNextFrame(): Promise<void> {
return new Promise(function (resolve: any): any { return new Promise(function (resolve) {
window.requestAnimationFrame(function (): any { window.requestAnimationFrame(function () {
window.requestAnimationFrame(function (): any { window.requestAnimationFrame(function () {
resolve(); resolve();
}); });
}); });
@ -286,18 +286,18 @@ export function round4Digits(n: number): number {
/** /**
* Clamps a value between [min, max] * Clamps a value between [min, max]
*/ */
export function clamp(v: number, minimum: number= = 0, maximum: number= = 1): any { export function clamp(v: number, minimum: number= = 0, maximum: number= = 1) {
return Math.max(minimum, Math.min(maximum, v)); return Math.max(minimum, Math.min(maximum, v));
} }
/** /**
* Helper method to create a new div element * Helper method to create a new div element
*/ */
export function makeDivElement(id: string= = null, classes: Array<string>= = [], innerHTML: string= = ""): any { export function makeDivElement(id: string= = null, classes: Array<string>= = [], innerHTML: string= = "") {
const div: any = document.createElement("div"); const div = document.createElement("div");
if (id) { if (id) {
div.id = id; div.id = id;
} }
for (let i: any = 0; i < classes.length; ++i) { for (let i = 0; i < classes.length; ++i) {
div.classList.add(classes[i]); div.classList.add(classes[i]);
} }
div.innerHTML = innerHTML; div.innerHTML = innerHTML;
@ -306,17 +306,17 @@ export function makeDivElement(id: string= = null, classes: Array<string>= = [],
/** /**
* Helper method to create a new div * Helper method to create a new div
*/ */
export function makeDiv(parent: Element, id: string= = null, classes: Array<string>= = [], innerHTML: string= = ""): any { export function makeDiv(parent: Element, id: string= = null, classes: Array<string>= = [], innerHTML: string= = "") {
const div: any = makeDivElement(id, classes, innerHTML); const div = makeDivElement(id, classes, innerHTML);
parent.appendChild(div); parent.appendChild(div);
return div; return div;
} }
/** /**
* Helper method to create a new button element * Helper method to create a new button element
*/ */
export function makeButtonElement(classes: Array<string>= = [], innerHTML: string= = ""): any { export function makeButtonElement(classes: Array<string>= = [], innerHTML: string= = "") {
const element: any = document.createElement("button"); const element = document.createElement("button");
for (let i: any = 0; i < classes.length; ++i) { for (let i = 0; i < classes.length; ++i) {
element.classList.add(classes[i]); element.classList.add(classes[i]);
} }
element.classList.add("styledButton"); element.classList.add("styledButton");
@ -326,17 +326,17 @@ export function makeButtonElement(classes: Array<string>= = [], innerHTML: strin
/** /**
* Helper method to create a new button * Helper method to create a new button
*/ */
export function makeButton(parent: Element, classes: Array<string>= = [], innerHTML: string= = ""): any { export function makeButton(parent: Element, classes: Array<string>= = [], innerHTML: string= = "") {
const element: any = makeButtonElement(classes, innerHTML); const element = makeButtonElement(classes, innerHTML);
parent.appendChild(element); parent.appendChild(element);
return element; return element;
} }
/** /**
* Removes all children of the given element * Removes all children of the given element
*/ */
export function removeAllChildren(elem: Element): any { export function removeAllChildren(elem: Element) {
if (elem) { if (elem) {
var range: any = document.createRange(); var range = document.createRange();
range.selectNodeContents(elem); range.selectNodeContents(elem);
range.deleteContents(); range.deleteContents();
} }
@ -344,7 +344,7 @@ export function removeAllChildren(elem: Element): any {
/** /**
* Returns if the game supports this browser * Returns if the game supports this browser
*/ */
export function isSupportedBrowser(): any { export function isSupportedBrowser() {
// please note, // please note,
// that IE11 now returns undefined again for window.chrome // that IE11 now returns undefined again for window.chrome
// and new Opera 30 outputs true for window.chrome // and new Opera 30 outputs true for window.chrome
@ -356,12 +356,12 @@ export function isSupportedBrowser(): any {
return true; return true;
} }
// @ts-ignore // @ts-ignore
var isChromium: any = window.chrome; var isChromium = window.chrome;
var winNav: any = window.navigator; var winNav = window.navigator;
var vendorName: any = winNav.vendor; var vendorName = winNav.vendor;
// @ts-ignore // @ts-ignore
var isIEedge: any = winNav.userAgent.indexOf("Edge") > -1; var isIEedge = winNav.userAgent.indexOf("Edge") > -1;
var isIOSChrome: any = winNav.userAgent.match("CriOS"); var isIOSChrome = winNav.userAgent.match("CriOS");
if (isIOSChrome) { if (isIOSChrome) {
// is Google Chrome on IOS // is Google Chrome on IOS
return false; return false;
@ -383,10 +383,10 @@ export function isSupportedBrowser(): any {
* {} * {}
*/ */
export function formatSecondsToTimeAgo(secs: number): string { export function formatSecondsToTimeAgo(secs: number): string {
const seconds: any = Math.floor(secs); const seconds = Math.floor(secs);
const minutes: any = Math.floor(seconds / 60); const minutes = Math.floor(seconds / 60);
const hours: any = Math.floor(minutes / 60); const hours = Math.floor(minutes / 60);
const days: any = Math.floor(hours / 24); const days = Math.floor(hours / 24);
if (seconds < 60) { if (seconds < 60) {
if (seconds === 1) { if (seconds === 1) {
return T.global.time.oneSecondAgo; return T.global.time.oneSecondAgo;
@ -417,34 +417,34 @@ export function formatSecondsToTimeAgo(secs: number): string {
* {} * {}
*/ */
export function formatSeconds(secs: number): string { export function formatSeconds(secs: number): string {
const trans: any = T.global.time; const trans = T.global.time;
secs = Math.ceil(secs); secs = Math.ceil(secs);
if (secs < 60) { if (secs < 60) {
return trans.secondsShort.replace("<seconds>", "" + secs); return trans.secondsShort.replace("<seconds>", "" + secs);
} }
else if (secs < 60 * 60) { else if (secs < 60 * 60) {
const minutes: any = Math.floor(secs / 60); const minutes = Math.floor(secs / 60);
const seconds: any = secs % 60; const seconds = secs % 60;
return trans.minutesAndSecondsShort return trans.minutesAndSecondsShort
.replace("<seconds>", "" + seconds) .replace("<seconds>", "" + seconds)
.replace("<minutes>", "" + minutes); .replace("<minutes>", "" + minutes);
} }
else { else {
const hours: any = Math.floor(secs / 3600); const hours = Math.floor(secs / 3600);
const minutes: any = Math.floor(secs / 60) % 60; const minutes = Math.floor(secs / 60) % 60;
return trans.hoursAndMinutesShort.replace("<minutes>", "" + minutes).replace("<hours>", "" + hours); return trans.hoursAndMinutesShort.replace("<minutes>", "" + minutes).replace("<hours>", "" + hours);
} }
} }
/** /**
* Formats a number like 2.51 to "2.5" * Formats a number like 2.51 to "2.5"
*/ */
export function round1DigitLocalized(speed: number, separator: string= = T.global.decimalSeparator): any { export function round1DigitLocalized(speed: number, separator: string= = T.global.decimalSeparator) {
return round1Digit(speed).toString().replace(".", separator); return round1Digit(speed).toString().replace(".", separator);
} }
/** /**
* Formats a number like 2.51 to "2.51 items / s" * Formats a number like 2.51 to "2.51 items / s"
*/ */
export function formatItemsPerSecond(speed: number, double: boolean= = false, separator: string= = T.global.decimalSeparator): any { export function formatItemsPerSecond(speed: number, double: boolean= = false, separator: string= = T.global.decimalSeparator) {
return ((speed === 1.0 return ((speed === 1.0
? T.ingame.buildingPlacement.infoTexts.oneItemPerSecond ? T.ingame.buildingPlacement.infoTexts.oneItemPerSecond
: T.ingame.buildingPlacement.infoTexts.itemsPerSecond.replace("<x>", round2Digits(speed).toString().replace(".", separator))) + (double ? " " + T.ingame.buildingPlacement.infoTexts.itemsPerSecondDouble : "")); : T.ingame.buildingPlacement.infoTexts.itemsPerSecond.replace("<x>", round2Digits(speed).toString().replace(".", separator))) + (double ? " " + T.ingame.buildingPlacement.infoTexts.itemsPerSecondDouble : ""));
@ -462,7 +462,7 @@ export function formatItemsPerSecond(speed: number, double: boolean= = false, se
* 7 mu * 7 mu
* 8 ru * 8 ru
*/ */
export function rotateFlatMatrix3x3(flatMatrix: Array<number>): any { export function rotateFlatMatrix3x3(flatMatrix: Array<number>) {
return [ return [
flatMatrix[6], flatMatrix[6],
flatMatrix[3], flatMatrix[3],
@ -480,7 +480,7 @@ export function rotateFlatMatrix3x3(flatMatrix: Array<number>): any {
* {} * {}
*/ */
export function generateMatrixRotations(originalMatrix: Array<number>): Object<number, Array<number>> { export function generateMatrixRotations(originalMatrix: Array<number>): Object<number, Array<number>> {
const result: any = { const result = {
0: originalMatrix, 0: originalMatrix,
}; };
originalMatrix = rotateFlatMatrix3x3(originalMatrix); originalMatrix = rotateFlatMatrix3x3(originalMatrix);
@ -496,8 +496,8 @@ export function generateMatrixRotations(originalMatrix: Array<number>): Object<n
* Rotates a directional object * Rotates a directional object
* {} * {}
*/ */
export function rotateDirectionalObject(obj: DirectionalObject, rotation: any): DirectionalObject { export function rotateDirectionalObject(obj: DirectionalObject, rotation): DirectionalObject {
const queue: any = [obj.top, obj.right, obj.bottom, obj.left]; const queue = [obj.top, obj.right, obj.bottom, obj.left];
while (rotation !== 0) { while (rotation !== 0) {
rotation -= 90; rotation -= 90;
queue.push(queue.shift()); queue.push(queue.shift());
@ -512,7 +512,7 @@ export function rotateDirectionalObject(obj: DirectionalObject, rotation: any):
/** /**
* Modulo which works for negative numbers * Modulo which works for negative numbers
*/ */
export function safeModulo(n: number, m: number): any { export function safeModulo(n: number, m: number) {
return ((n % m) + m) % m; return ((n % m) + m) % m;
} }
/** /**
@ -525,7 +525,7 @@ export function smoothPulse(time: number): number {
/** /**
* Fills in a <link> tag * Fills in a <link> tag
*/ */
export function fillInLinkIntoTranslation(translation: string, link: string): any { export function fillInLinkIntoTranslation(translation: string, link: string) {
return translation return translation
.replace("<link>", "<a href='" + link + "' target='_blank'>") .replace("<link>", "<a href='" + link + "' target='_blank'>")
.replace("</link>", "</a>"); .replace("</link>", "</a>");
@ -533,8 +533,8 @@ export function fillInLinkIntoTranslation(translation: string, link: string): an
/** /**
* Generates a file download * Generates a file download
*/ */
export function generateFileDownload(filename: string, text: string): any { export function generateFileDownload(filename: string, text: string) {
var element: any = document.createElement("a"); var 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);
element.style.display = "none"; element.style.display = "none";
@ -545,17 +545,17 @@ export function generateFileDownload(filename: string, text: string): any {
/** /**
* Starts a file chooser * Starts a file chooser
*/ */
export function startFileChoose(acceptedType: string = ".bin"): any { export function startFileChoose(acceptedType: string = ".bin") {
var input: any = document.createElement("input"); var input = document.createElement("input");
input.type = "file"; input.type = "file";
input.accept = acceptedType; input.accept = acceptedType;
return new Promise((resolve: any): any => { return new Promise(resolve => {
input.onchange = (_: any): any => resolve(input.files[0]); input.onchange = _ => resolve(input.files[0]);
input.click(); input.click();
}); });
} }
const MAX_ROMAN_NUMBER: any = 49; const MAX_ROMAN_NUMBER = 49;
const romanLiteralsCache: any = ["0"]; const romanLiteralsCache = ["0"];
/** /**
* *
* {} * {}
@ -568,7 +568,7 @@ export function getRomanNumber(number: number): string {
if (number > MAX_ROMAN_NUMBER) { if (number > MAX_ROMAN_NUMBER) {
return String(number); return String(number);
} }
function formatDigit(digit: any, unit: any, quintuple: any, decuple: any): any { function formatDigit(digit, unit, quintuple, decuple) {
switch (digit) { switch (digit) {
case 0: case 0:
return ""; return "";
@ -587,26 +587,26 @@ export function getRomanNumber(number: number): string {
return quintuple + formatDigit(digit - 5, unit, quintuple, decuple); return quintuple + formatDigit(digit - 5, unit, quintuple, decuple);
} }
} }
let thousands: any = Math.floor(number / 1000); let thousands = Math.floor(number / 1000);
let thousandsPart: any = ""; let thousandsPart = "";
while (thousands > 0) { while (thousands > 0) {
thousandsPart += "M"; thousandsPart += "M";
thousands -= 1; thousands -= 1;
} }
const hundreds: any = Math.floor((number % 1000) / 100); const hundreds = Math.floor((number % 1000) / 100);
const hundredsPart: any = formatDigit(hundreds, "C", "D", "M"); const hundredsPart = formatDigit(hundreds, "C", "D", "M");
const tens: any = Math.floor((number % 100) / 10); const tens = Math.floor((number % 100) / 10);
const tensPart: any = formatDigit(tens, "X", "L", "C"); const tensPart = formatDigit(tens, "X", "L", "C");
const units: any = number % 10; const units = number % 10;
const unitsPart: any = formatDigit(units, "I", "V", "X"); const unitsPart = formatDigit(units, "I", "V", "X");
const formatted: any = thousandsPart + hundredsPart + tensPart + unitsPart; const formatted = thousandsPart + hundredsPart + tensPart + unitsPart;
romanLiteralsCache[number] = formatted; romanLiteralsCache[number] = formatted;
return formatted; return formatted;
} }
/** /**
* Returns the appropriate logo sprite path * Returns the appropriate logo sprite path
*/ */
export function getLogoSprite(): any { export function getLogoSprite() {
if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) { if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) {
return "logo.png"; return "logo.png";
} }
@ -618,10 +618,10 @@ export function getLogoSprite(): any {
/** /**
* Rejects a promise after X ms * Rejects a promise after X ms
*/ */
export function timeoutPromise(promise: Promise, timeout: any = 30000): any { export function timeoutPromise(promise: Promise, timeout = 30000) {
return Promise.race([ return Promise.race([
new Promise((resolve: any, reject: any): any => { new Promise((resolve, reject) => {
setTimeout((): any => reject("timeout of " + timeout + " ms exceeded"), timeout); setTimeout(() => reject("timeout of " + timeout + " ms exceeded"), timeout);
}), }),
promise, promise,
]); ]);

View File

@ -1,11 +1,11 @@
import { globalConfig } from "./config"; import { globalConfig } from "./config";
import { safeModulo } from "./utils"; import { safeModulo } from "./utils";
const tileSize: any = globalConfig.tileSize; const tileSize = globalConfig.tileSize;
const halfTileSize: any = globalConfig.halfTileSize; const halfTileSize = globalConfig.halfTileSize;
/** /**
* @enum {string} * @enum {string}
*/ */
export const enumDirection: any = { export const enumDirection = {
top: "top", top: "top",
right: "right", right: "right",
bottom: "bottom", bottom: "bottom",
@ -14,7 +14,7 @@ export const enumDirection: any = {
/** /**
* @enum {string} * @enum {string}
*/ */
export const enumInvertedDirections: any = { export const enumInvertedDirections = {
[enumDirection.top]: enumDirection.bottom, [enumDirection.top]: enumDirection.bottom,
[enumDirection.right]: enumDirection.left, [enumDirection.right]: enumDirection.left,
[enumDirection.bottom]: enumDirection.top, [enumDirection.bottom]: enumDirection.top,
@ -23,7 +23,7 @@ export const enumInvertedDirections: any = {
/** /**
* @enum {number} * @enum {number}
*/ */
export const enumDirectionToAngle: any = { export const enumDirectionToAngle = {
[enumDirection.top]: 0, [enumDirection.top]: 0,
[enumDirection.right]: 90, [enumDirection.right]: 90,
[enumDirection.bottom]: 180, [enumDirection.bottom]: 180,
@ -32,7 +32,7 @@ export const enumDirectionToAngle: any = {
/** /**
* @enum {enumDirection} * @enum {enumDirection}
*/ */
export const enumAngleToDirection: any = { export const enumAngleToDirection = {
0: enumDirection.top, 0: enumDirection.top,
90: enumDirection.right, 90: enumDirection.right,
180: enumDirection.bottom, 180: enumDirection.bottom,
@ -224,8 +224,8 @@ export class Vector {
* {} * {}
*/ */
distanceSquare(v: Vector): number { distanceSquare(v: Vector): number {
const dx: any = this.x - v.x; const dx = this.x - v.x;
const dy: any = this.y - v.y; const dy = this.y - v.y;
return dx * dx + dy * dy; return dx * dx + dy * dy;
} }
/** /**
@ -240,8 +240,8 @@ export class Vector {
* {} * {}
*/ */
centerPoint(v: Vector): Vector { centerPoint(v: Vector): Vector {
const cx: any = this.x + v.x; const cx = this.x + v.x;
const cy: any = this.y + v.y; const cy = this.y + v.y;
return new Vector(cx / 2, cy / 2); return new Vector(cx / 2, cy / 2);
} }
/** /**
@ -305,7 +305,7 @@ export class Vector {
* {} * {}
*/ */
normalize(): Vector { normalize(): Vector {
const len: any = Math.max(1e-5, Math.hypot(this.x, this.y)); const len = Math.max(1e-5, Math.hypot(this.x, this.y));
return new Vector(this.x / len, this.y / len); return new Vector(this.x / len, this.y / len);
} }
/** /**
@ -313,7 +313,7 @@ export class Vector {
* {} * {}
*/ */
normalizeIfGreaterOne(): Vector { normalizeIfGreaterOne(): Vector {
const len: any = Math.max(1, Math.hypot(this.x, this.y)); const len = Math.max(1, Math.hypot(this.x, this.y));
return new Vector(this.x / len, this.y / len); return new Vector(this.x / len, this.y / len);
} }
/** /**
@ -321,9 +321,9 @@ export class Vector {
* {} * {}
*/ */
normalizedDirection(v: Vector): Vector { normalizedDirection(v: Vector): Vector {
const dx: any = v.x - this.x; const dx = v.x - this.x;
const dy: any = v.y - this.y; const dy = v.y - this.y;
const len: any = Math.max(1e-5, Math.hypot(dx, dy)); const len = Math.max(1e-5, Math.hypot(dx, dy));
return new Vector(dx / len, dy / len); return new Vector(dx / len, dy / len);
} }
/** /**
@ -359,8 +359,8 @@ export class Vector {
* {} new vector * {} new vector
*/ */
rotated(angle: number): Vector { rotated(angle: number): Vector {
const sin: any = Math.sin(angle); const sin = Math.sin(angle);
const cos: any = Math.cos(angle); const cos = Math.cos(angle);
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);
} }
/** /**
@ -380,7 +380,7 @@ export class Vector {
case 90: { case 90: {
// sin = 1; // sin = 1;
// cos = 0; // cos = 0;
const x: any = this.x; const x = this.x;
this.x = -this.y; this.x = -this.y;
this.y = x; this.y = x;
return this; return this;
@ -395,7 +395,7 @@ export class Vector {
case 270: { case 270: {
// sin = -1 // sin = -1
// cos = 0 // cos = 0
const x: any = this.x; const x = this.x;
this.x = this.y; this.x = this.y;
this.y = -x; this.y = -x;
return this; return this;
@ -504,7 +504,7 @@ export class Vector {
* Compares both vectors for epsilon equality * Compares both vectors for epsilon equality
* {} * {}
*/ */
equalsEpsilon(v: Vector, epsilon: any = 1e-5): Boolean { equalsEpsilon(v: Vector, epsilon = 1e-5): Boolean {
return Math.abs(this.x - v.x) < 1e-5 && Math.abs(this.y - v.y) < epsilon; return Math.abs(this.x - v.x) < 1e-5 && Math.abs(this.y - v.y) < epsilon;
} }
/** /**
@ -524,7 +524,7 @@ export class Vector {
/** /**
* Creates a simple representation of the vector * Creates a simple representation of the vector
*/ */
serializeSimple(): any { serializeSimple() {
return { x: this.x, y: this.y }; return { x: this.x, y: this.y };
} }
/** /**
@ -538,8 +538,8 @@ export class Vector {
* {} * {}
*/ */
static deserializeTileFromInt(i: number): Vector { static deserializeTileFromInt(i: number): Vector {
const x: any = i % 256; const x = i % 256;
const y: any = Math.floor(i / 256); const y = Math.floor(i / 256);
return new Vector(x, y); return new Vector(x, y);
} }
/** /**
@ -562,14 +562,14 @@ export class Vector {
/** /**
* Interpolates two vectors, for a = 0, returns v1 and for a = 1 return v2, otherwise interpolate * Interpolates two vectors, for a = 0, returns v1 and for a = 1 return v2, otherwise interpolate
*/ */
export function mixVector(v1: Vector, v2: Vector, a: number): any { export function mixVector(v1: Vector, v2: Vector, a: number) {
return new Vector(v1.x * (1 - a) + v2.x * a, v1.y * (1 - a) + v2.y * a); return new Vector(v1.x * (1 - a) + v2.x * a, v1.y * (1 - a) + v2.y * a);
} }
/** /**
* Mapping from string direction to actual vector * Mapping from string direction to actual vector
* @enum {Vector} * @enum {Vector}
*/ */
export const enumDirectionToVector: any = { export const enumDirectionToVector = {
top: new Vector(0, -1), top: new Vector(0, -1),
right: new Vector(1, 0), right: new Vector(1, 0),
bottom: new Vector(0, 1), bottom: new Vector(0, 1),

View File

@ -6,9 +6,9 @@ import { globalConfig } from "../core/config";
import { createLogger } from "../core/logging"; import { createLogger } from "../core/logging";
import { ACHIEVEMENTS } from "../platform/achievement_provider"; import { ACHIEVEMENTS } from "../platform/achievement_provider";
import { getBuildingDataFromCode } from "./building_codes"; import { getBuildingDataFromCode } from "./building_codes";
const logger: any = createLogger("achievement_proxy"); const logger = createLogger("achievement_proxy");
const ROTATER: any = "rotater"; const ROTATER = "rotater";
const DEFAULT: any = "default"; const DEFAULT = "default";
export class AchievementProxy { export class AchievementProxy {
public root = root; public root = root;
public provider = this.root.app.achievementProvider; public provider = this.root.app.achievementProvider;
@ -24,7 +24,7 @@ export class AchievementProxy {
} }
this.root.signals.postLoadHook.add(this.onLoad, this); this.root.signals.postLoadHook.add(this.onLoad, this);
} }
onLoad(): any { onLoad() {
if (!this.root.gameMode.hasAchievements()) { if (!this.root.gameMode.hasAchievements()) {
logger.log("Disabling achievements because game mode does not have achievements"); logger.log("Disabling achievements because game mode does not have achievements");
this.disabled = true; this.disabled = true;
@ -32,17 +32,17 @@ export class AchievementProxy {
} }
this.provider this.provider
.onLoad(this.root) .onLoad(this.root)
.then((): any => { .then(() => {
this.disabled = false; this.disabled = false;
logger.log("Recieving achievement signals"); logger.log("Recieving achievement signals");
this.initialize(); this.initialize();
}) })
.catch((err: any): any => { .catch(err => {
this.disabled = true; this.disabled = true;
logger.error("Ignoring achievement signals", err); logger.error("Ignoring achievement signals", err);
}); });
} }
initialize(): any { initialize() {
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.darkMode, null); this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.darkMode, null);
if (this.has(ACHIEVEMENTS.mam)) { if (this.has(ACHIEVEMENTS.mam)) {
this.root.signals.entityAdded.add(this.onMamFailure, this); this.root.signals.entityAdded.add(this.onMamFailure, this);
@ -54,11 +54,11 @@ export class AchievementProxy {
} }
this.startSlice(); this.startSlice();
} }
startSlice(): any { startSlice() {
this.sliceTime = this.root.time.now(); this.sliceTime = this.root.time.now();
this.root.signals.bulkAchievementCheck.dispatch(ACHIEVEMENTS.storeShape, this.sliceTime, ACHIEVEMENTS.throughputBp25, this.sliceTime, ACHIEVEMENTS.throughputBp50, this.sliceTime, ACHIEVEMENTS.throughputLogo25, this.sliceTime, ACHIEVEMENTS.throughputLogo50, this.sliceTime, ACHIEVEMENTS.throughputRocket10, this.sliceTime, ACHIEVEMENTS.throughputRocket20, this.sliceTime, ACHIEVEMENTS.play1h, this.sliceTime, ACHIEVEMENTS.play10h, this.sliceTime, ACHIEVEMENTS.play20h, this.sliceTime); this.root.signals.bulkAchievementCheck.dispatch(ACHIEVEMENTS.storeShape, this.sliceTime, ACHIEVEMENTS.throughputBp25, this.sliceTime, ACHIEVEMENTS.throughputBp50, this.sliceTime, ACHIEVEMENTS.throughputLogo25, this.sliceTime, ACHIEVEMENTS.throughputLogo50, this.sliceTime, ACHIEVEMENTS.throughputRocket10, this.sliceTime, ACHIEVEMENTS.throughputRocket20, this.sliceTime, ACHIEVEMENTS.play1h, this.sliceTime, ACHIEVEMENTS.play10h, this.sliceTime, ACHIEVEMENTS.play20h, this.sliceTime);
} }
update(): any { update() {
if (this.disabled) { if (this.disabled) {
return; return;
} }
@ -75,11 +75,11 @@ export class AchievementProxy {
} }
return this.provider.collection.map.has(key); return this.provider.collection.map.has(key);
} }
onEntityAdded(entity: Entity): any { onEntityAdded(entity: Entity) {
if (!entity.components.StaticMapEntity) { if (!entity.components.StaticMapEntity) {
return; return;
} }
const building: any = getBuildingDataFromCode(entity.components.StaticMapEntity.code); const building = getBuildingDataFromCode(entity.components.StaticMapEntity.code);
if (building.metaInstance.id !== ROTATER) { if (building.metaInstance.id !== ROTATER) {
return; return;
} }
@ -89,7 +89,7 @@ export class AchievementProxy {
this.root.savegame.currentData.stats.usedInverseRotater = true; this.root.savegame.currentData.stats.usedInverseRotater = true;
this.root.signals.entityAdded.remove(this.onEntityAdded); this.root.signals.entityAdded.remove(this.onEntityAdded);
} }
onStoryGoalCompleted(level: number): any { onStoryGoalCompleted(level: number) {
if (level > 26) { if (level > 26) {
this.root.signals.entityAdded.add(this.onMamFailure, this); this.root.signals.entityAdded.add(this.onMamFailure, this);
this.root.signals.entityDestroyed.add(this.onMamFailure, this); this.root.signals.entityDestroyed.add(this.onMamFailure, this);
@ -98,7 +98,7 @@ export class AchievementProxy {
// reset on every level // reset on every level
this.root.savegame.currentData.stats.failedMam = false; this.root.savegame.currentData.stats.failedMam = false;
} }
onMamFailure(): any { onMamFailure() {
this.root.savegame.currentData.stats.failedMam = true; this.root.savegame.currentData.stats.failedMam = true;
} }
} }

View File

@ -5,11 +5,11 @@ import { GameRoot } from "./root";
/** /**
* @enum {number} * @enum {number}
*/ */
export const enumSavePriority: any = { export const enumSavePriority = {
regular: 2, regular: 2,
asap: 100, asap: 100,
}; };
const logger: any = createLogger("autosave"); const logger = createLogger("autosave");
export class AutomaticSave { export class AutomaticSave {
public root: GameRoot = root; public root: GameRoot = root;
public saveImportance = enumSavePriority.regular; public saveImportance = enumSavePriority.regular;
@ -17,30 +17,30 @@ export class AutomaticSave {
constructor(root) { constructor(root) {
} }
setSaveImportance(importance: any): any { setSaveImportance(importance) {
this.saveImportance = Math.max(this.saveImportance, importance); this.saveImportance = Math.max(this.saveImportance, importance);
} }
doSave(): any { doSave() {
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
return; return;
} }
this.root.gameState.doSave(); this.root.gameState.doSave();
this.saveImportance = enumSavePriority.regular; this.saveImportance = enumSavePriority.regular;
} }
update(): any { update() {
if (!this.root.gameInitialized) { if (!this.root.gameInitialized) {
// Bad idea // Bad idea
return; return;
} }
const saveInterval: any = this.root.app.settings.getAutosaveIntervalSeconds(); const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds();
if (!saveInterval) { if (!saveInterval) {
// Disabled // Disabled
return; return;
} }
// Check when the last save was, but make sure that if it fails, we don't spam // Check when the last save was, but make sure that if it fails, we don't spam
const lastSaveTime: any = Math.max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate()); const lastSaveTime = Math.max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate());
const secondsSinceLastSave: any = (Date.now() - lastSaveTime) / 1000.0; const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0;
let shouldSave: any = false; let shouldSave = false;
switch (this.saveImportance) { switch (this.saveImportance) {
case enumSavePriority.asap: case enumSavePriority.asap:
// High always should save // High always should save

View File

@ -10,7 +10,7 @@ export class BaseItem extends BasicSerializableObject {
constructor() { constructor() {
super(); super();
} }
static getId(): any { static getId() {
return "base_item"; return "base_item";
} }
/** {} */ /** {} */
@ -54,13 +54,13 @@ export class BaseItem extends BasicSerializableObject {
* Draws the item to a canvas * Draws the item to a canvas
* @abstract * @abstract
*/ */
drawFullSizeOnCanvas(context: CanvasRenderingContext2D, size: number): any { drawFullSizeOnCanvas(context: CanvasRenderingContext2D, size: number) {
abstract; abstract;
} }
/** /**
* Draws the item at the given position * Draws the item at the given position
*/ */
drawItemCenteredClipped(x: number, y: number, parameters: DrawParameters, diameter: number= = globalConfig.defaultItemDiameter): any { drawItemCenteredClipped(x: number, y: number, parameters: DrawParameters, diameter: number= = globalConfig.defaultItemDiameter) {
if (parameters.visibleRect.containsCircle(x, y, diameter / 2)) { if (parameters.visibleRect.containsCircle(x, y, diameter / 2)) {
this.drawItemCenteredImpl(x, y, parameters, diameter); this.drawItemCenteredImpl(x, y, parameters, diameter);
} }
@ -69,10 +69,10 @@ export class BaseItem extends BasicSerializableObject {
* INTERNAL * INTERNAL
* @abstract * @abstract
*/ */
drawItemCenteredImpl(x: number, y: number, parameters: DrawParameters, diameter: number= = globalConfig.defaultItemDiameter): any { drawItemCenteredImpl(x: number, y: number, parameters: DrawParameters, diameter: number= = globalConfig.defaultItemDiameter) {
abstract; abstract;
} }
getBackgroundColorAsResource(): any { getBackgroundColorAsResource() {
abstract; abstract;
return ""; return "";
} }

View File

@ -11,17 +11,17 @@ import { BaseItem } from "./base_item";
import { Entity } from "./entity"; import { Entity } from "./entity";
import { typeItemSingleton } from "./item_resolver"; import { typeItemSingleton } from "./item_resolver";
import { GameRoot } from "./root"; import { GameRoot } from "./root";
const logger: any = createLogger("belt_path"); const logger = createLogger("belt_path");
// Helpers for more semantic access into interleaved arrays // Helpers for more semantic access into interleaved arrays
const DEBUG: any = G_IS_DEV && false; const DEBUG = G_IS_DEV && false;
/** /**
* Stores a path of belts, used for optimizing performance * Stores a path of belts, used for optimizing performance
*/ */
export class BeltPath extends BasicSerializableObject { export class BeltPath extends BasicSerializableObject {
static getId(): any { static getId() {
return "BeltPath"; return "BeltPath";
} }
static getSchema(): any { static getSchema() {
return { return {
entityPath: types.array(types.entity), entityPath: types.array(types.entity),
items: types.array(types.pair(types.ufloat, typeItemSingleton)), items: types.array(types.pair(types.ufloat, typeItemSingleton)),
@ -35,10 +35,10 @@ export class BeltPath extends BasicSerializableObject {
static fromSerialized(root: GameRoot, data: Object): BeltPath | string { static fromSerialized(root: GameRoot, data: Object): BeltPath | string {
// Create fake object which looks like a belt path but skips the constructor // Create fake object which looks like a belt path but skips the constructor
const fakeObject: any = (Object.create(BeltPath.prototype) as BeltPath); const fakeObject = Object.create(BeltPath.prototype) as BeltPath);
fakeObject.root = root; fakeObject.root = root;
// Deserialize the data // Deserialize the data
const errorCodeDeserialize: any = fakeObject.deserialize(data); const errorCodeDeserialize = fakeObject.deserialize(data);
if (errorCodeDeserialize) { if (errorCodeDeserialize) {
return errorCodeDeserialize; return errorCodeDeserialize;
} }
@ -68,7 +68,7 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Initializes the path by computing the properties which are not saved * Initializes the path by computing the properties which are not saved
*/ */
init(computeSpacing: boolean = true): any { init(computeSpacing: boolean = true) {
this.onPathChanged(); this.onPathChanged();
this.totalLength = this.computeTotalLength(); this.totalLength = this.computeTotalLength();
if (computeSpacing) { if (computeSpacing) {
@ -79,14 +79,14 @@ export class BeltPath extends BasicSerializableObject {
*/ */
this.worldBounds = this.computeBounds(); this.worldBounds = this.computeBounds();
// Connect the belts // Connect the belts
for (let i: any = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
this.entityPath[i].components.Belt.assignedPath = this; this.entityPath[i].components.Belt.assignedPath = this;
} }
} }
/** /**
* Clears all items * Clears all items
*/ */
clearAllItems(): any { clearAllItems() {
this.items = []; this.items = [];
this.spacingToFirstItem = this.totalLength; this.spacingToFirstItem = this.totalLength;
this.numCompressedItemsAfterFirstItem = 0; this.numCompressedItemsAfterFirstItem = 0;
@ -101,15 +101,15 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Tries to accept the item * Tries to accept the item
*/ */
tryAcceptItem(item: BaseItem): any { tryAcceptItem(item: BaseItem) {
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) { if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
// So, since we already need one tick to accept this item we will add this directly. // So, since we already need one tick to accept this item we will add this directly.
const beltProgressPerTick: any = this.root.hubGoals.getBeltBaseSpeed() * const beltProgressPerTick = this.root.hubGoals.getBeltBaseSpeed() *
this.root.dynamicTickrate.deltaSeconds * this.root.dynamicTickrate.deltaSeconds *
globalConfig.itemSpacingOnBelts; globalConfig.itemSpacingOnBelts;
// First, compute how much progress we can make *at max* // First, compute how much progress we can make *at max*
const maxProgress: any = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts); const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts);
const initialProgress: any = Math.min(maxProgress, beltProgressPerTick); const initialProgress = Math.min(maxProgress, beltProgressPerTick);
this.items.unshift([this.spacingToFirstItem - initialProgress, item]); this.items.unshift([this.spacingToFirstItem - initialProgress, item]);
this.spacingToFirstItem = initialProgress; this.spacingToFirstItem = initialProgress;
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
@ -132,10 +132,10 @@ export class BeltPath extends BasicSerializableObject {
* {} * {}
*/ */
computeBounds(): Rectangle { computeBounds(): Rectangle {
let bounds: any = this.entityPath[0].components.StaticMapEntity.getTileSpaceBounds(); let bounds = this.entityPath[0].components.StaticMapEntity.getTileSpaceBounds();
for (let i: any = 1; i < this.entityPath.length; ++i) { for (let i = 1; i < this.entityPath.length; ++i) {
const staticComp: any = this.entityPath[i].components.StaticMapEntity; const staticComp = this.entityPath[i].components.StaticMapEntity;
const otherBounds: any = staticComp.getTileSpaceBounds(); const otherBounds = staticComp.getTileSpaceBounds();
bounds = bounds.getUnion(otherBounds); bounds = bounds.getUnion(otherBounds);
} }
return bounds.allScaled(globalConfig.tileSize); return bounds.allScaled(globalConfig.tileSize);
@ -143,7 +143,7 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Recomputes cache variables once the path was changed * Recomputes cache variables once the path was changed
*/ */
onPathChanged(): any { onPathChanged() {
this.boundAcceptor = this.computeAcceptingEntityAndSlot().acceptor; this.boundAcceptor = this.computeAcceptingEntityAndSlot().acceptor;
/** /**
* How many items past the first item are compressed * How many items past the first item are compressed
@ -153,7 +153,7 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Called by the belt system when the surroundings changed * Called by the belt system when the surroundings changed
*/ */
onSurroundingsChanged(): any { onSurroundingsChanged() {
this.onPathChanged(); this.onPathChanged();
} }
/** /**
@ -165,34 +165,34 @@ export class BeltPath extends BasicSerializableObject {
entity?: Entity; entity?: Entity;
} { } {
DEBUG && !debug_Silent && logger.log("Recomputing acceptor target"); DEBUG && !debug_Silent && logger.log("Recomputing acceptor target");
const lastEntity: any = this.entityPath[this.entityPath.length - 1]; const lastEntity = this.entityPath[this.entityPath.length - 1];
const lastStatic: any = lastEntity.components.StaticMapEntity; const lastStatic = lastEntity.components.StaticMapEntity;
const lastBeltComp: any = lastEntity.components.Belt; const lastBeltComp = lastEntity.components.Belt;
// Figure out where and into which direction we eject items // Figure out where and into which direction we eject items
const ejectSlotWsTile: any = lastStatic.localTileToWorld(new Vector(0, 0)); const ejectSlotWsTile = lastStatic.localTileToWorld(new Vector(0, 0));
const ejectSlotWsDirection: any = lastStatic.localDirectionToWorld(lastBeltComp.direction); const ejectSlotWsDirection = lastStatic.localDirectionToWorld(lastBeltComp.direction);
const ejectSlotWsDirectionVector: any = enumDirectionToVector[ejectSlotWsDirection]; const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection];
const ejectSlotTargetWsTile: any = ejectSlotWsTile.add(ejectSlotWsDirectionVector); const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector);
// Try to find the given acceptor component to take the item // Try to find the given acceptor component to take the item
const targetEntity: any = this.root.map.getLayerContentXY(ejectSlotTargetWsTile.x, ejectSlotTargetWsTile.y, "regular"); const targetEntity = this.root.map.getLayerContentXY(ejectSlotTargetWsTile.x, ejectSlotTargetWsTile.y, "regular");
if (!targetEntity) { if (!targetEntity) {
return {}; return {};
} }
const noSimplifiedBelts: any = !this.root.app.settings.getAllSettings().simplifiedBelts; const noSimplifiedBelts = !this.root.app.settings.getAllSettings().simplifiedBelts;
DEBUG && !debug_Silent && logger.log(" Found target entity", targetEntity.uid); DEBUG && !debug_Silent && logger.log(" Found target entity", targetEntity.uid);
const targetStaticComp: any = targetEntity.components.StaticMapEntity; const targetStaticComp = targetEntity.components.StaticMapEntity;
const targetBeltComp: any = targetEntity.components.Belt; const targetBeltComp = targetEntity.components.Belt;
// Check for belts (special case) // Check for belts (special case)
if (targetBeltComp) { if (targetBeltComp) {
const beltAcceptingDirection: any = targetStaticComp.localDirectionToWorld(enumDirection.top); const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top);
DEBUG && DEBUG &&
!debug_Silent && !debug_Silent &&
logger.log(" Entity is accepting items from", ejectSlotWsDirection, "vs", beltAcceptingDirection, "Rotation:", targetStaticComp.rotation); logger.log(" Entity is accepting items from", ejectSlotWsDirection, "vs", beltAcceptingDirection, "Rotation:", targetStaticComp.rotation);
if (ejectSlotWsDirection === beltAcceptingDirection) { if (ejectSlotWsDirection === beltAcceptingDirection) {
return { return {
entity: targetEntity, entity: targetEntity,
acceptor: (item: any): any => { acceptor: item => {
const path: any = targetBeltComp.assignedPath; const path = targetBeltComp.assignedPath;
assert(path, "belt has no path"); assert(path, "belt has no path");
return path.tryAcceptItem(item); return path.tryAcceptItem(item);
}, },
@ -200,27 +200,27 @@ export class BeltPath extends BasicSerializableObject {
} }
} }
// Check for item acceptors // Check for item acceptors
const targetAcceptorComp: any = targetEntity.components.ItemAcceptor; const targetAcceptorComp = targetEntity.components.ItemAcceptor;
if (!targetAcceptorComp) { if (!targetAcceptorComp) {
// Entity doesn't accept items // Entity doesn't accept items
return {}; return {};
} }
const ejectingDirection: any = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection); const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection);
const matchingSlot: any = targetAcceptorComp.findMatchingSlot(targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), ejectingDirection); const matchingSlot = targetAcceptorComp.findMatchingSlot(targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), ejectingDirection);
if (!matchingSlot) { if (!matchingSlot) {
// No matching slot found // No matching slot found
return {}; return {};
} }
const matchingSlotIndex: any = matchingSlot.index; const matchingSlotIndex = matchingSlot.index;
const passOver: any = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex); const passOver = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex);
if (!passOver) { if (!passOver) {
return {}; return {};
} }
const matchingDirection: any = enumInvertedDirections[ejectingDirection]; const matchingDirection = enumInvertedDirections[ejectingDirection];
const filter: any = matchingSlot.slot.filter; const filter = matchingSlot.slot.filter;
return { return {
entity: targetEntity, entity: targetEntity,
acceptor: function (item: any, remainingProgress: any = 0.0): any { acceptor: function (item, remainingProgress = 0.0) {
// Check if the acceptor has a filter // Check if the acceptor has a filter
if (filter && item._type !== filter) { if (filter && item._type !== filter) {
return false; return false;
@ -242,13 +242,13 @@ export class BeltPath extends BasicSerializableObject {
* {} * {}
*/ */
computePassOverFunctionWithoutBelts(entity: Entity, matchingSlotIndex: number): (item: BaseItem, slotIndex: number) => boolean | void { computePassOverFunctionWithoutBelts(entity: Entity, matchingSlotIndex: number): (item: BaseItem, slotIndex: number) => boolean | void {
const systems: any = this.root.systemMgr.systems; const systems = this.root.systemMgr.systems;
const hubGoals: any = this.root.hubGoals; const hubGoals = this.root.hubGoals;
// NOTICE: THIS IS COPIED FROM THE ITEM EJECTOR SYSTEM FOR PEROFMANCE REASONS // NOTICE: THIS IS COPIED FROM THE ITEM EJECTOR SYSTEM FOR PEROFMANCE REASONS
const itemProcessorComp: any = entity.components.ItemProcessor; const itemProcessorComp = entity.components.ItemProcessor;
if (itemProcessorComp) { if (itemProcessorComp) {
// Its an item processor .. // Its an item processor ..
return function (item: any): any { return function (item) {
// Check for potential filters // Check for potential filters
if (!systems.itemProcessor.checkRequirements(entity, item, matchingSlotIndex)) { if (!systems.itemProcessor.checkRequirements(entity, item, matchingSlotIndex)) {
return; return;
@ -256,28 +256,28 @@ export class BeltPath extends BasicSerializableObject {
return itemProcessorComp.tryTakeItem(item, matchingSlotIndex); return itemProcessorComp.tryTakeItem(item, matchingSlotIndex);
}; };
} }
const undergroundBeltComp: any = entity.components.UndergroundBelt; const undergroundBeltComp = entity.components.UndergroundBelt;
if (undergroundBeltComp) { if (undergroundBeltComp) {
// Its an underground belt. yay. // Its an underground belt. yay.
return function (item: any): any { return function (item) {
return undergroundBeltComp.tryAcceptExternalItem(item, hubGoals.getUndergroundBeltBaseSpeed()); return undergroundBeltComp.tryAcceptExternalItem(item, hubGoals.getUndergroundBeltBaseSpeed());
}; };
} }
const storageComp: any = entity.components.Storage; const storageComp = entity.components.Storage;
if (storageComp) { if (storageComp) {
// It's a storage // It's a storage
return function (item: any): any { return function (item) {
if (storageComp.canAcceptItem(item)) { if (storageComp.canAcceptItem(item)) {
storageComp.takeItem(item); storageComp.takeItem(item);
return true; return true;
} }
}; };
} }
const filterComp: any = entity.components.Filter; const filterComp = entity.components.Filter;
if (filterComp) { if (filterComp) {
// It's a filter! Unfortunately the filter has to know a lot about it's // It's a filter! Unfortunately the filter has to know a lot about it's
// surrounding state and components, so it can't be within the component itself. // surrounding state and components, so it can't be within the component itself.
return function (item: any): any { return function (item) {
if (systems.filter.tryAcceptItem(entity, matchingSlotIndex, item)) { if (systems.filter.tryAcceptItem(entity, matchingSlotIndex, item)) {
return true; return true;
} }
@ -289,30 +289,30 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Helper to throw an error on mismatch * Helper to throw an error on mismatch
*/ */
debug_failIntegrity(change: string, ...reason: Array<any>): any { debug_failIntegrity(change: string, ...reason: Array<any>) {
throw new Error("belt path invalid (" + change + "): " + reason.map((i: any): any => "" + i).join(" ")); throw new Error("belt path invalid (" + change + "): " + reason.map(i => "" + i).join(" "));
} }
/** /**
* Checks if this path is valid * Checks if this path is valid
*/ */
debug_checkIntegrity(currentChange: any = "change"): any { debug_checkIntegrity(currentChange = "change") {
const fail: any = (...args: any): any => this.debug_failIntegrity(currentChange, ...args); const fail = (...args) => this.debug_failIntegrity(currentChange, ...args);
// Check for empty path // Check for empty path
if (this.entityPath.length === 0) { if (this.entityPath.length === 0) {
return fail("Belt path is empty"); return fail("Belt path is empty");
} }
// Check for mismatching length // Check for mismatching length
const totalLength: any = this.computeTotalLength(); const totalLength = this.computeTotalLength();
if (!epsilonCompare(this.totalLength, totalLength, 0.01)) { if (!epsilonCompare(this.totalLength, totalLength, 0.01)) {
return this.debug_failIntegrity(currentChange, "Total length mismatch, stored =", this.totalLength, "but correct is", totalLength); return this.debug_failIntegrity(currentChange, "Total length mismatch, stored =", this.totalLength, "but correct is", totalLength);
} }
// Check for misconnected entities // Check for misconnected entities
for (let i: any = 0; i < this.entityPath.length - 1; ++i) { for (let i = 0; i < this.entityPath.length - 1; ++i) {
const entity: any = this.entityPath[i]; const entity = this.entityPath[i];
if (entity.destroyed) { if (entity.destroyed) {
return fail("Reference to destroyed entity " + entity.uid); return fail("Reference to destroyed entity " + entity.uid);
} }
const followUp: any = this.root.systemMgr.systems.belt.findFollowUpEntity(entity); const followUp = this.root.systemMgr.systems.belt.findFollowUpEntity(entity);
if (!followUp) { if (!followUp) {
return fail("Follow up entity for the", i, "-th entity (total length", this.entityPath.length, ") was null!"); return fail("Follow up entity for the", i, "-th entity (total length", this.entityPath.length, ") was null!");
} }
@ -332,9 +332,9 @@ export class BeltPath extends BasicSerializableObject {
return fail(currentChange, "Path is empty but spacing to first item (", this.spacingToFirstItem, ") does not equal total length (", this.totalLength, ")"); return fail(currentChange, "Path is empty but spacing to first item (", this.spacingToFirstItem, ") does not equal total length (", this.totalLength, ")");
} }
// Check items etc // Check items etc
let currentPos: any = this.spacingToFirstItem; let currentPos = this.spacingToFirstItem;
for (let i: any = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item: any = this.items[i]; const item = this.items[i];
if (item[0 /* nextDistance */] < 0 || item[0 /* nextDistance */] > this.totalLength + 0.02) { if (item[0 /* nextDistance */] < 0 || item[0 /* nextDistance */] > this.totalLength + 0.02) {
return fail("Item has invalid offset to next item: ", item[0 /* nextDistance */], "(total length:", this.totalLength, ")"); return fail("Item has invalid offset to next item: ", item[0 /* nextDistance */], "(total length:", this.totalLength, ")");
} }
@ -342,21 +342,21 @@ export class BeltPath extends BasicSerializableObject {
} }
// Check the total sum matches // Check the total sum matches
if (!epsilonCompare(currentPos, this.totalLength, 0.01)) { if (!epsilonCompare(currentPos, this.totalLength, 0.01)) {
return fail("total sum (", currentPos, ") of first item spacing (", this.spacingToFirstItem, ") and items does not match total length (", this.totalLength, ") -> items: " + this.items.map((i: any): any => i[0 /* nextDistance */]).join("|")); return fail("total sum (", currentPos, ") of first item spacing (", this.spacingToFirstItem, ") and items does not match total length (", this.totalLength, ") -> items: " + this.items.map(i => i[0 /* nextDistance */]).join("|"));
} }
// Check bounds // Check bounds
const actualBounds: any = this.computeBounds(); const actualBounds = this.computeBounds();
if (!actualBounds.equalsEpsilon(this.worldBounds, 0.01)) { if (!actualBounds.equalsEpsilon(this.worldBounds, 0.01)) {
return fail("Bounds are stale"); return fail("Bounds are stale");
} }
// Check acceptor // Check acceptor
const acceptor: any = this.computeAcceptingEntityAndSlot(true).acceptor; const acceptor = this.computeAcceptingEntityAndSlot(true).acceptor;
if (!!acceptor !== !!this.boundAcceptor) { if (!!acceptor !== !!this.boundAcceptor) {
return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.boundAcceptor); return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.boundAcceptor);
} }
// Check first nonzero offset // Check first nonzero offset
let firstNonzero: any = 0; let firstNonzero = 0;
for (let i: any = this.items.length - 2; i >= 0; --i) { for (let i = this.items.length - 2; i >= 0; --i) {
if (this.items[i][0 /* nextDistance */] < globalConfig.itemSpacingOnBelts + 1e-5) { if (this.items[i][0 /* nextDistance */] < globalConfig.itemSpacingOnBelts + 1e-5) {
++firstNonzero; ++firstNonzero;
} }
@ -378,14 +378,14 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Extends the belt path by the given belt * Extends the belt path by the given belt
*/ */
extendOnEnd(entity: Entity): any { extendOnEnd(entity: Entity) {
DEBUG && logger.log("Extending belt path by entity at", entity.components.StaticMapEntity.origin); DEBUG && logger.log("Extending belt path by entity at", entity.components.StaticMapEntity.origin);
const beltComp: any = entity.components.Belt; const beltComp = entity.components.Belt;
// Append the entity // Append the entity
this.entityPath.push(entity); this.entityPath.push(entity);
this.onPathChanged(); this.onPathChanged();
// Extend the path length // Extend the path length
const additionalLength: any = beltComp.getEffectiveLengthTiles(); const additionalLength = beltComp.getEffectiveLengthTiles();
this.totalLength += additionalLength; this.totalLength += additionalLength;
DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength); DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength);
// If we have no item, just update the distance to the first item // If we have no item, just update the distance to the first item
@ -395,7 +395,7 @@ export class BeltPath extends BasicSerializableObject {
} }
else { else {
// Otherwise, update the next-distance of the last item // Otherwise, update the next-distance of the last item
const lastItem: any = this.items[this.items.length - 1]; const lastItem = this.items[this.items.length - 1];
DEBUG && DEBUG &&
logger.log(" Extended spacing of last item from", lastItem[0 /* nextDistance */], "to", lastItem[0 /* nextDistance */] + additionalLength); logger.log(" Extended spacing of last item from", lastItem[0 /* nextDistance */], "to", lastItem[0 /* nextDistance */] + additionalLength);
lastItem[0 /* nextDistance */] += additionalLength; lastItem[0 /* nextDistance */] += additionalLength;
@ -411,11 +411,11 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Extends the path with the given entity on the beginning * Extends the path with the given entity on the beginning
*/ */
extendOnBeginning(entity: Entity): any { extendOnBeginning(entity: Entity) {
const beltComp: any = entity.components.Belt; const beltComp = entity.components.Belt;
DEBUG && logger.log("Extending the path on the beginning"); DEBUG && logger.log("Extending the path on the beginning");
// All items on that belt are simply lost (for now) // All items on that belt are simply lost (for now)
const length: any = beltComp.getEffectiveLengthTiles(); const length = beltComp.getEffectiveLengthTiles();
// Extend the length of this path // Extend the length of this path
this.totalLength += length; this.totalLength += length;
// Simply adjust the first item spacing cuz we have no items contained // Simply adjust the first item spacing cuz we have no items contained
@ -452,17 +452,17 @@ export class BeltPath extends BasicSerializableObject {
deleteEntityOnPathSplitIntoTwo(entity: Entity): BeltPath { deleteEntityOnPathSplitIntoTwo(entity: Entity): BeltPath {
DEBUG && logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin); DEBUG && logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin);
// First, find where the current path ends // First, find where the current path ends
const beltComp: any = entity.components.Belt; const beltComp = entity.components.Belt;
beltComp.assignedPath = null; beltComp.assignedPath = null;
const entityLength: any = beltComp.getEffectiveLengthTiles(); const entityLength = beltComp.getEffectiveLengthTiles();
assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split"); assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split");
assert(this.entityPath.indexOf(entity) !== 0, "Entity is first"); assert(this.entityPath.indexOf(entity) !== 0, "Entity is first");
assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last"); assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last");
let firstPathEntityCount: any = 0; let firstPathEntityCount = 0;
let firstPathLength: any = 0; let firstPathLength = 0;
let firstPathEndEntity: any = null; let firstPathEndEntity = null;
for (let i: any = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
const otherEntity: any = this.entityPath[i]; const otherEntity = this.entityPath[i];
if (otherEntity === entity) { if (otherEntity === entity) {
DEBUG && logger.log("Found entity at", i, "of length", firstPathLength); DEBUG && logger.log("Found entity at", i, "of length", firstPathLength);
break; break;
@ -474,23 +474,23 @@ export class BeltPath extends BasicSerializableObject {
DEBUG && DEBUG &&
logger.log("First path ends at", firstPathLength, "and entity", firstPathEndEntity.components.StaticMapEntity.origin, "and has", firstPathEntityCount, "entities"); logger.log("First path ends at", firstPathLength, "and entity", firstPathEndEntity.components.StaticMapEntity.origin, "and has", firstPathEntityCount, "entities");
// Compute length of second path // Compute length of second path
const secondPathLength: any = this.totalLength - firstPathLength - entityLength; const secondPathLength = this.totalLength - firstPathLength - entityLength;
const secondPathStart: any = firstPathLength + entityLength; const secondPathStart = firstPathLength + entityLength;
const secondEntities: any = this.entityPath.splice(firstPathEntityCount + 1); const secondEntities = this.entityPath.splice(firstPathEntityCount + 1);
DEBUG && DEBUG &&
logger.log("Second path starts at", secondPathStart, "and has a length of ", secondPathLength, "with", secondEntities.length, "entities"); logger.log("Second path starts at", secondPathStart, "and has a length of ", secondPathLength, "with", secondEntities.length, "entities");
// Remove the last item // Remove the last item
this.entityPath.pop(); this.entityPath.pop();
DEBUG && logger.log("Splitting", this.items.length, "items"); DEBUG && logger.log("Splitting", this.items.length, "items");
DEBUG && DEBUG &&
logger.log("Old items are", this.items.map((i: any): any => i[0 /* nextDistance */])); logger.log("Old items are", this.items.map(i => i[0 /* nextDistance */]));
// Create second path // Create second path
const secondPath: any = new BeltPath(this.root, secondEntities); const secondPath = new BeltPath(this.root, secondEntities);
// Remove all items which are no longer relevant and transfer them to the second path // Remove all items which are no longer relevant and transfer them to the second path
let itemPos: any = this.spacingToFirstItem; let itemPos = this.spacingToFirstItem;
for (let i: any = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item: any = this.items[i]; const item = this.items[i];
const distanceToNext: any = item[0 /* nextDistance */]; const distanceToNext = item[0 /* nextDistance */];
DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next"); DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next");
// Check if this item is past the first path // Check if this item is past the first path
if (itemPos >= firstPathLength) { if (itemPos >= firstPathLength) {
@ -518,7 +518,7 @@ export class BeltPath extends BasicSerializableObject {
else { else {
// Seems this item is on the first path (so all good), so just make sure it doesn't // Seems this item is on the first path (so all good), so just make sure it doesn't
// have a nextDistance which is bigger than the total path length // have a nextDistance which is bigger than the total path length
const clampedDistanceToNext: any = Math.min(itemPos + distanceToNext, firstPathLength) - itemPos; const clampedDistanceToNext = Math.min(itemPos + distanceToNext, firstPathLength) - itemPos;
if (clampedDistanceToNext < distanceToNext) { if (clampedDistanceToNext < distanceToNext) {
DEBUG && DEBUG &&
logger.log("Correcting next distance (first path) from", distanceToNext, "to", clampedDistanceToNext); logger.log("Correcting next distance (first path) from", distanceToNext, "to", clampedDistanceToNext);
@ -529,9 +529,9 @@ export class BeltPath extends BasicSerializableObject {
itemPos += distanceToNext; itemPos += distanceToNext;
} }
DEBUG && DEBUG &&
logger.log("New items are", this.items.map((i: any): any => i[0 /* nextDistance */])); logger.log("New items are", this.items.map(i => i[0 /* nextDistance */]));
DEBUG && DEBUG &&
logger.log("And second path items are", secondPath.items.map((i: any): any => i[0 /* nextDistance */])); logger.log("And second path items are", secondPath.items.map(i => i[0 /* nextDistance */]));
// Adjust our total length // Adjust our total length
this.totalLength = firstPathLength; this.totalLength = firstPathLength;
// Make sure that if we are empty, we set our first distance properly // Make sure that if we are empty, we set our first distance properly
@ -551,11 +551,11 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Deletes the last entity * Deletes the last entity
*/ */
deleteEntityOnEnd(entity: Entity): any { deleteEntityOnEnd(entity: Entity) {
assert(this.entityPath[this.entityPath.length - 1] === entity, "Not actually the last entity (instead " + this.entityPath.indexOf(entity) + ")"); assert(this.entityPath[this.entityPath.length - 1] === entity, "Not actually the last entity (instead " + this.entityPath.indexOf(entity) + ")");
// Ok, first remove the entity // Ok, first remove the entity
const beltComp: any = entity.components.Belt; const beltComp = entity.components.Belt;
const beltLength: any = beltComp.getEffectiveLengthTiles(); const beltLength = beltComp.getEffectiveLengthTiles();
DEBUG && DEBUG &&
logger.log("Deleting last entity on path with length", this.entityPath.length, "(reducing", this.totalLength, " by", beltLength, ")"); logger.log("Deleting last entity on path with length", this.entityPath.length, "(reducing", this.totalLength, " by", beltLength, ")");
this.totalLength -= beltLength; this.totalLength -= beltLength;
@ -572,11 +572,11 @@ export class BeltPath extends BasicSerializableObject {
} }
else { else {
// Ok, make sure we simply drop all items which are no longer contained // Ok, make sure we simply drop all items which are no longer contained
let itemOffset: any = this.spacingToFirstItem; let itemOffset = this.spacingToFirstItem;
let lastItemOffset: any = itemOffset; let lastItemOffset = itemOffset;
DEBUG && logger.log(" Adjusting", this.items.length, "items"); DEBUG && logger.log(" Adjusting", this.items.length, "items");
for (let i: any = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item: any = this.items[i]; const item = this.items[i];
// Get rid of items past this path // Get rid of items past this path
if (itemOffset >= this.totalLength) { if (itemOffset >= this.totalLength) {
DEBUG && logger.log("Dropping item (current index=", i, ")"); DEBUG && logger.log("Dropping item (current index=", i, ")");
@ -592,7 +592,7 @@ export class BeltPath extends BasicSerializableObject {
// If we still have an item, make sure the last item matches // If we still have an item, make sure the last item matches
if (this.items.length > 0) { if (this.items.length > 0) {
// We can easily compute the next distance since we know where the last item is now // We can easily compute the next distance since we know where the last item is now
const lastDistance: any = this.totalLength - lastItemOffset; const lastDistance = this.totalLength - lastItemOffset;
assert(lastDistance >= 0.0, "Last item distance mismatch: " + assert(lastDistance >= 0.0, "Last item distance mismatch: " +
lastDistance + lastDistance +
" -> Total length was " + " -> Total length was " +
@ -619,11 +619,11 @@ export class BeltPath extends BasicSerializableObject {
* Deletes the entity of the start of the path * Deletes the entity of the start of the path
* @see deleteEntityOnEnd * @see deleteEntityOnEnd
*/ */
deleteEntityOnStart(entity: Entity): any { deleteEntityOnStart(entity: Entity) {
assert(entity === this.entityPath[0], "Not actually the start entity (instead " + this.entityPath.indexOf(entity) + ")"); assert(entity === this.entityPath[0], "Not actually the start entity (instead " + this.entityPath.indexOf(entity) + ")");
// Ok, first remove the entity // Ok, first remove the entity
const beltComp: any = entity.components.Belt; const beltComp = entity.components.Belt;
const beltLength: any = beltComp.getEffectiveLengthTiles(); const beltLength = beltComp.getEffectiveLengthTiles();
DEBUG && DEBUG &&
logger.log("Deleting first entity on path with length", this.entityPath.length, "(reducing", this.totalLength, " by", beltLength, ")"); logger.log("Deleting first entity on path with length", this.entityPath.length, "(reducing", this.totalLength, " by", beltLength, ")");
this.totalLength -= beltLength; this.totalLength -= beltLength;
@ -651,11 +651,11 @@ export class BeltPath extends BasicSerializableObject {
DEBUG && DEBUG &&
logger.log(" We have at least one item in the beginning, drop those and adjust spacing (first item @", this.spacingToFirstItem, ") since we removed", beltLength, "length from path"); logger.log(" We have at least one item in the beginning, drop those and adjust spacing (first item @", this.spacingToFirstItem, ") since we removed", beltLength, "length from path");
DEBUG && DEBUG &&
logger.log(" Items:", this.items.map((i: any): any => i[0 /* nextDistance */])); logger.log(" Items:", this.items.map(i => i[0 /* nextDistance */]));
// Find offset to first item // Find offset to first item
let itemOffset: any = this.spacingToFirstItem; let itemOffset = this.spacingToFirstItem;
for (let i: any = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item: any = this.items[i]; const item = this.items[i];
if (itemOffset <= beltLength) { if (itemOffset <= beltLength) {
DEBUG && DEBUG &&
logger.log(" -> Dropping item with index", i, "at", itemOffset, "since it was on the removed belt"); logger.log(" -> Dropping item with index", i, "at", itemOffset, "since it was on the removed belt");
@ -692,28 +692,28 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Extends the path by the given other path * Extends the path by the given other path
*/ */
extendByPath(otherPath: BeltPath): any { extendByPath(otherPath: BeltPath) {
assert(otherPath !== this, "Circular path dependency"); assert(otherPath !== this, "Circular path dependency");
const entities: any = otherPath.entityPath; const entities = otherPath.entityPath;
DEBUG && logger.log("Extending path by other path, starting to add entities"); DEBUG && logger.log("Extending path by other path, starting to add entities");
const oldLength: any = this.totalLength; const oldLength = this.totalLength;
DEBUG && logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength); DEBUG && logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength);
// First, append entities // First, append entities
for (let i: any = 0; i < entities.length; ++i) { for (let i = 0; i < entities.length; ++i) {
const entity: any = entities[i]; const entity = entities[i];
const beltComp: any = entity.components.Belt; const beltComp = entity.components.Belt;
// Add to path and update references // Add to path and update references
this.entityPath.push(entity); this.entityPath.push(entity);
beltComp.assignedPath = this; beltComp.assignedPath = this;
// Update our length // Update our length
const additionalLength: any = beltComp.getEffectiveLengthTiles(); const additionalLength = beltComp.getEffectiveLengthTiles();
this.totalLength += additionalLength; this.totalLength += additionalLength;
} }
DEBUG && DEBUG &&
logger.log(" Path is now", this.entityPath.length, "entities and has a length of", this.totalLength); logger.log(" Path is now", this.entityPath.length, "entities and has a length of", this.totalLength);
// Now, update the distance of our last item // Now, update the distance of our last item
if (this.items.length !== 0) { if (this.items.length !== 0) {
const lastItem: any = this.items[this.items.length - 1]; const lastItem = this.items[this.items.length - 1];
lastItem[0 /* nextDistance */] += otherPath.spacingToFirstItem; lastItem[0 /* nextDistance */] += otherPath.spacingToFirstItem;
DEBUG && DEBUG &&
logger.log(" Add distance to last item, effectively being", lastItem[0 /* nextDistance */], "now"); logger.log(" Add distance to last item, effectively being", lastItem[0 /* nextDistance */], "now");
@ -726,8 +726,8 @@ export class BeltPath extends BasicSerializableObject {
} }
DEBUG && logger.log(" Pushing", otherPath.items.length, "items from other path"); DEBUG && logger.log(" Pushing", otherPath.items.length, "items from other path");
// Aaand push the other paths items // Aaand push the other paths items
for (let i: any = 0; i < otherPath.items.length; ++i) { for (let i = 0; i < otherPath.items.length; ++i) {
const item: any = otherPath.items[i]; const item = otherPath.items[i];
this.items.push([item[0 /* nextDistance */], item[1 /* item */]]); this.items.push([item[0 /* nextDistance */], item[1 /* item */]]);
} }
// Update bounds // Update bounds
@ -742,9 +742,9 @@ export class BeltPath extends BasicSerializableObject {
* {} * {}
*/ */
computeTotalLength(): number { computeTotalLength(): number {
let length: any = 0; let length = 0;
for (let i: any = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
const entity: any = this.entityPath[i]; const entity = this.entityPath[i];
length += entity.components.Belt.getEffectiveLengthTiles(); length += entity.components.Belt.getEffectiveLengthTiles();
} }
return length; return length;
@ -752,7 +752,7 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Performs one tick * Performs one tick
*/ */
update(): any { update() {
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("pre-update"); this.debug_checkIntegrity("pre-update");
} }
@ -761,7 +761,7 @@ export class BeltPath extends BasicSerializableObject {
return; return;
} }
// Divide by item spacing on belts since we use throughput and not speed // Divide by item spacing on belts since we use throughput and not speed
let beltSpeed: any = this.root.hubGoals.getBeltBaseSpeed() * let beltSpeed = this.root.hubGoals.getBeltBaseSpeed() *
this.root.dynamicTickrate.deltaSeconds * this.root.dynamicTickrate.deltaSeconds *
globalConfig.itemSpacingOnBelts; globalConfig.itemSpacingOnBelts;
if (G_IS_DEV && globalConfig.debug.instantBelts) { if (G_IS_DEV && globalConfig.debug.instantBelts) {
@ -769,17 +769,17 @@ export class BeltPath extends BasicSerializableObject {
} }
// Store whether this is the first item we processed, so premature // Store whether this is the first item we processed, so premature
// item ejection is available // item ejection is available
let isFirstItemProcessed: any = true; let isFirstItemProcessed = true;
// Store how much velocity (strictly its distance, not velocity) we have to distribute over all items // Store how much velocity (strictly its distance, not velocity) we have to distribute over all items
let remainingVelocity: any = beltSpeed; let remainingVelocity = beltSpeed;
// Store the last item we processed, so we can skip clashed ones // Store the last item we processed, so we can skip clashed ones
let lastItemProcessed: any; let lastItemProcessed;
for (lastItemProcessed = this.items.length - 1; lastItemProcessed >= 0; --lastItemProcessed) { for (lastItemProcessed = this.items.length - 1; lastItemProcessed >= 0; --lastItemProcessed) {
const nextDistanceAndItem: any = this.items[lastItemProcessed]; const nextDistanceAndItem = this.items[lastItemProcessed];
// Compute how much spacing we need at least // Compute how much spacing we need at least
const minimumSpacing: any = lastItemProcessed === this.items.length - 1 ? 0 : globalConfig.itemSpacingOnBelts; const minimumSpacing = lastItemProcessed === this.items.length - 1 ? 0 : globalConfig.itemSpacingOnBelts;
// Compute how much we can advance // Compute how much we can advance
let clampedProgress: any = nextDistanceAndItem[0 /* nextDistance */] - minimumSpacing; let clampedProgress = nextDistanceAndItem[0 /* nextDistance */] - minimumSpacing;
// Make sure we don't advance more than the remaining velocity has stored // Make sure we don't advance more than the remaining velocity has stored
if (remainingVelocity < clampedProgress) { if (remainingVelocity < clampedProgress) {
clampedProgress = remainingVelocity; clampedProgress = remainingVelocity;
@ -800,18 +800,18 @@ export class BeltPath extends BasicSerializableObject {
// Store how much velocity we "lost" because we bumped the item to the end of the // Store how much velocity we "lost" because we bumped the item to the end of the
// belt but couldn't move it any farther. We need this to tell the item acceptor // belt but couldn't move it any farther. We need this to tell the item acceptor
// animation to start a tad later, so everything matches up. Yes I'm a perfectionist. // animation to start a tad later, so everything matches up. Yes I'm a perfectionist.
const excessVelocity: any = beltSpeed - clampedProgress; const excessVelocity = beltSpeed - clampedProgress;
// Try to directly get rid of the item // Try to directly get rid of the item
if (this.boundAcceptor && if (this.boundAcceptor &&
this.boundAcceptor(nextDistanceAndItem[1 /* item */], excessVelocity)) { this.boundAcceptor(nextDistanceAndItem[1 /* item */], excessVelocity)) {
this.items.pop(); this.items.pop();
const itemBehind: any = this.items[lastItemProcessed - 1]; const itemBehind = this.items[lastItemProcessed - 1];
if (itemBehind && this.numCompressedItemsAfterFirstItem > 0) { if (itemBehind && this.numCompressedItemsAfterFirstItem > 0) {
// So, with the next tick we will skip this item, but it actually has the potential // So, with the next tick we will skip this item, but it actually has the potential
// to process farther -> If we don't advance here, we loose a tiny bit of progress // to process farther -> If we don't advance here, we loose a tiny bit of progress
// every tick which causes the belt to be slower than it actually is. // every tick which causes the belt to be slower than it actually is.
// Also see #999 // Also see #999
const fixupProgress: any = Math.max(0, Math.min(remainingVelocity, itemBehind[0 /* nextDistance */])); const fixupProgress = Math.max(0, Math.min(remainingVelocity, itemBehind[0 /* nextDistance */]));
// See above // See above
itemBehind[0 /* nextDistance */] -= fixupProgress; itemBehind[0 /* nextDistance */] -= fixupProgress;
remainingVelocity -= fixupProgress; remainingVelocity -= fixupProgress;
@ -833,7 +833,7 @@ export class BeltPath extends BasicSerializableObject {
// Compute compressed item count // Compute compressed item count
this.numCompressedItemsAfterFirstItem = Math.max(0, this.numCompressedItemsAfterFirstItem, this.items.length - 2 - lastItemProcessed); this.numCompressedItemsAfterFirstItem = Math.max(0, this.numCompressedItemsAfterFirstItem, this.items.length - 2 - lastItemProcessed);
// Check if we have an item which is ready to be emitted // Check if we have an item which is ready to be emitted
const lastItem: any = this.items[this.items.length - 1]; const lastItem = this.items[this.items.length - 1];
if (lastItem && lastItem[0 /* nextDistance */] === 0) { if (lastItem && lastItem[0 /* nextDistance */] === 0) {
if (this.boundAcceptor && this.boundAcceptor(lastItem[1 /* item */])) { if (this.boundAcceptor && this.boundAcceptor(lastItem[1 /* item */])) {
this.items.pop(); this.items.pop();
@ -849,34 +849,34 @@ export class BeltPath extends BasicSerializableObject {
* {} * {}
*/ */
computePositionFromProgress(progress: number): Vector { computePositionFromProgress(progress: number): Vector {
let currentLength: any = 0; let currentLength = 0;
// floating point issues .. // floating point issues ..
assert(progress <= this.totalLength + 0.02, "Progress too big: " + progress); assert(progress <= this.totalLength + 0.02, "Progress too big: " + progress);
for (let i: any = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
const beltComp: any = this.entityPath[i].components.Belt; const beltComp = this.entityPath[i].components.Belt;
const localLength: any = beltComp.getEffectiveLengthTiles(); const localLength = beltComp.getEffectiveLengthTiles();
if (currentLength + localLength >= progress || i === this.entityPath.length - 1) { if (currentLength + localLength >= progress || i === this.entityPath.length - 1) {
// Min required here due to floating point issues // Min required here due to floating point issues
const localProgress: any = Math.min(1.0, progress - currentLength); const localProgress = Math.min(1.0, progress - currentLength);
assert(localProgress >= 0.0, "Invalid local progress: " + localProgress); assert(localProgress >= 0.0, "Invalid local progress: " + localProgress);
const localSpace: any = beltComp.transformBeltToLocalSpace(localProgress); const localSpace = beltComp.transformBeltToLocalSpace(localProgress);
return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace); return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace);
} }
currentLength += localLength; currentLength += localLength;
} }
assert(false, "invalid progress: " + progress + " (max: " + this.totalLength + ")"); assert(false, "invalid progress: " + progress + " (max: " + this.totalLength + ")");
} }
drawDebug(parameters: DrawParameters): any { drawDebug(parameters: DrawParameters) {
if (!parameters.visibleRect.containsRect(this.worldBounds)) { if (!parameters.visibleRect.containsRect(this.worldBounds)) {
return; return;
} }
parameters.context.fillStyle = "#d79a25"; parameters.context.fillStyle = "#d79a25";
parameters.context.strokeStyle = "#d79a25"; parameters.context.strokeStyle = "#d79a25";
parameters.context.beginPath(); parameters.context.beginPath();
for (let i: any = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
const entity: any = this.entityPath[i]; const entity = this.entityPath[i];
const pos: any = entity.components.StaticMapEntity; const pos = entity.components.StaticMapEntity;
const worldPos: any = pos.origin.toWorldSpaceCenterOfTile(); const worldPos = pos.origin.toWorldSpaceCenterOfTile();
if (i === 0) { if (i === 0) {
parameters.context.moveTo(worldPos.x, worldPos.y); parameters.context.moveTo(worldPos.x, worldPos.y);
} }
@ -886,10 +886,10 @@ export class BeltPath extends BasicSerializableObject {
} }
parameters.context.stroke(); parameters.context.stroke();
// Items // Items
let progress: any = this.spacingToFirstItem; let progress = this.spacingToFirstItem;
for (let i: any = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const nextDistanceAndItem: any = this.items[i]; const nextDistanceAndItem = this.items[i];
const worldPos: any = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile();
parameters.context.fillStyle = "#268e4d"; parameters.context.fillStyle = "#268e4d";
parameters.context.beginRoundedRect(worldPos.x - 5, worldPos.y - 5, 10, 10, 3); parameters.context.beginRoundedRect(worldPos.x - 5, worldPos.y - 5, 10, 10, 3);
parameters.context.fill(); parameters.context.fill();
@ -902,28 +902,28 @@ export class BeltPath extends BasicSerializableObject {
parameters.context.fillRect(worldPos.x + 5, worldPos.y, 20, 3); parameters.context.fillRect(worldPos.x + 5, worldPos.y, 20, 3);
} }
} }
for (let i: any = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
const entity: any = this.entityPath[i]; const entity = this.entityPath[i];
parameters.context.fillStyle = "#d79a25"; parameters.context.fillStyle = "#d79a25";
const pos: any = entity.components.StaticMapEntity; const pos = entity.components.StaticMapEntity;
const worldPos: any = pos.origin.toWorldSpaceCenterOfTile(); const worldPos = pos.origin.toWorldSpaceCenterOfTile();
parameters.context.beginCircle(worldPos.x, worldPos.y, i === 0 ? 5 : 3); parameters.context.beginCircle(worldPos.x, worldPos.y, i === 0 ? 5 : 3);
parameters.context.fill(); parameters.context.fill();
} }
for (let progress: any = 0; progress <= this.totalLength + 0.01; progress += 0.2) { for (let progress = 0; progress <= this.totalLength + 0.01; progress += 0.2) {
const worldPos: any = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile();
parameters.context.fillStyle = "red"; parameters.context.fillStyle = "red";
parameters.context.beginCircle(worldPos.x, worldPos.y, 1); parameters.context.beginCircle(worldPos.x, worldPos.y, 1);
parameters.context.fill(); parameters.context.fill();
} }
const firstItemIndicator: any = this.computePositionFromProgress(this.spacingToFirstItem).toWorldSpaceCenterOfTile(); const firstItemIndicator = this.computePositionFromProgress(this.spacingToFirstItem).toWorldSpaceCenterOfTile();
parameters.context.fillStyle = "purple"; parameters.context.fillStyle = "purple";
parameters.context.fillRect(firstItemIndicator.x - 3, firstItemIndicator.y - 1, 6, 2); parameters.context.fillRect(firstItemIndicator.x - 3, firstItemIndicator.y - 1, 6, 2);
} }
/** /**
* Checks if this belt path should render simplified * Checks if this belt path should render simplified
*/ */
checkIsPotatoMode(): any { checkIsPotatoMode() {
// POTATO Mode: Only show items when belt is hovered // POTATO Mode: Only show items when belt is hovered
if (!this.root.app.settings.getAllSettings().simplifiedBelts) { if (!this.root.app.settings.getAllSettings().simplifiedBelts) {
return false; return false;
@ -932,13 +932,13 @@ export class BeltPath extends BasicSerializableObject {
// Not in regular layer // Not in regular layer
return true; return true;
} }
const mousePos: any = this.root.app.mousePosition; const mousePos = this.root.app.mousePosition;
if (!mousePos) { if (!mousePos) {
// Mouse not registered // Mouse not registered
return true; return true;
} }
const tile: any = this.root.camera.screenToWorld(mousePos).toTileSpace(); const tile = this.root.camera.screenToWorld(mousePos).toTileSpace();
const contents: any = this.root.map.getLayerContentXY(tile.x, tile.y, "regular"); const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular");
if (!contents || !contents.components.Belt) { if (!contents || !contents.components.Belt) {
// Nothing below // Nothing below
return true; return true;
@ -952,7 +952,7 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Draws the path * Draws the path
*/ */
draw(parameters: DrawParameters): any { draw(parameters: DrawParameters) {
if (!parameters.visibleRect.containsRect(this.worldBounds)) { if (!parameters.visibleRect.containsRect(this.worldBounds)) {
return; return;
} }
@ -961,43 +961,43 @@ export class BeltPath extends BasicSerializableObject {
return; return;
} }
if (this.checkIsPotatoMode()) { if (this.checkIsPotatoMode()) {
const firstItem: any = this.items[0]; const firstItem = this.items[0];
if (this.entityPath.length > 1 && firstItem) { if (this.entityPath.length > 1 && firstItem) {
const medianBeltIndex: any = clamp(Math.round(this.entityPath.length / 2 - 1), 0, this.entityPath.length - 1); const medianBeltIndex = clamp(Math.round(this.entityPath.length / 2 - 1), 0, this.entityPath.length - 1);
const medianBelt: any = this.entityPath[medianBeltIndex]; const medianBelt = this.entityPath[medianBeltIndex];
const beltComp: any = medianBelt.components.Belt; const beltComp = medianBelt.components.Belt;
const staticComp: any = medianBelt.components.StaticMapEntity; const staticComp = medianBelt.components.StaticMapEntity;
const centerPosLocal: any = beltComp.transformBeltToLocalSpace(this.entityPath.length % 2 === 0 ? beltComp.getEffectiveLengthTiles() : 0.5); const centerPosLocal = beltComp.transformBeltToLocalSpace(this.entityPath.length % 2 === 0 ? beltComp.getEffectiveLengthTiles() : 0.5);
const centerPos: any = staticComp.localTileToWorld(centerPosLocal).toWorldSpaceCenterOfTile(); const centerPos = staticComp.localTileToWorld(centerPosLocal).toWorldSpaceCenterOfTile();
parameters.context.globalAlpha = 0.5; parameters.context.globalAlpha = 0.5;
firstItem[1 /* item */].drawItemCenteredClipped(centerPos.x, centerPos.y, parameters); firstItem[1 /* item */].drawItemCenteredClipped(centerPos.x, centerPos.y, parameters);
parameters.context.globalAlpha = 1; parameters.context.globalAlpha = 1;
} }
return; return;
} }
let currentItemPos: any = this.spacingToFirstItem; let currentItemPos = this.spacingToFirstItem;
let currentItemIndex: any = 0; let currentItemIndex = 0;
let trackPos: any = 0.0; let trackPos = 0.0;
let drawStack: Array<[ let drawStack: Array<[
Vector, Vector,
BaseItem BaseItem
]> = []; ]> = [];
let drawStackProp: any = ""; let drawStackProp = "";
// Iterate whole track and check items // Iterate whole track and check items
for (let i: any = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
const entity: any = this.entityPath[i]; const entity = this.entityPath[i];
const beltComp: any = entity.components.Belt; const beltComp = entity.components.Belt;
const beltLength: any = beltComp.getEffectiveLengthTiles(); const beltLength = beltComp.getEffectiveLengthTiles();
// Check if the current items are on the belt // Check if the current items are on the belt
while (trackPos + beltLength >= currentItemPos - 1e-5) { while (trackPos + beltLength >= currentItemPos - 1e-5) {
// It's on the belt, render it now // It's on the belt, render it now
const staticComp: any = entity.components.StaticMapEntity; const staticComp = entity.components.StaticMapEntity;
assert(currentItemPos - trackPos >= 0, "invalid track pos: " + currentItemPos + " vs " + trackPos + " (l =" + beltLength + ")"); assert(currentItemPos - trackPos >= 0, "invalid track pos: " + currentItemPos + " vs " + trackPos + " (l =" + beltLength + ")");
const localPos: any = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos); const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos);
const worldPos: any = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile(); const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile();
const distanceAndItem: any = this.items[currentItemIndex]; const distanceAndItem = this.items[currentItemIndex];
const item: any = distanceAndItem[1 /* item */]; const item = distanceAndItem[1 /* item */];
const nextItemDistance: any = distanceAndItem[0 /* nextDistance */]; const nextItemDistance = distanceAndItem[0 /* nextDistance */];
if (!parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, globalConfig.defaultItemDiameter)) { if (!parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, globalConfig.defaultItemDiameter)) {
// this one isn't visible, do not append it // this one isn't visible, do not append it
// Start a new stack // Start a new stack
@ -1008,7 +1008,7 @@ export class BeltPath extends BasicSerializableObject {
else { else {
if (drawStack.length > 1) { if (drawStack.length > 1) {
// Check if we can append to the stack, since its already a stack of two same items // Check if we can append to the stack, since its already a stack of two same items
const referenceItem: any = drawStack[0]; const referenceItem = drawStack[0];
if (referenceItem[1].equals(item) && if (referenceItem[1].equals(item) &&
Math.abs(referenceItem[0][drawStackProp] - worldPos[drawStackProp]) < 0.001) { Math.abs(referenceItem[0][drawStackProp] - worldPos[drawStackProp]) < 0.001) {
// Will continue stack // Will continue stack
@ -1021,11 +1021,11 @@ export class BeltPath extends BasicSerializableObject {
} }
} }
else if (drawStack.length === 1) { else if (drawStack.length === 1) {
const firstItem: any = drawStack[0]; const firstItem = drawStack[0];
// Check if we can make it a stack // Check if we can make it a stack
if (firstItem[1 /* item */].equals(item)) { if (firstItem[1 /* item */].equals(item)) {
// Same item, check if it is either horizontal or vertical // Same item, check if it is either horizontal or vertical
const startPos: any = firstItem[0 /* pos */]; const startPos = firstItem[0 /* pos */];
if (Math.abs(startPos.x - worldPos.x) < 0.001) { if (Math.abs(startPos.x - worldPos.x) < 0.001) {
drawStackProp = "x"; drawStackProp = "x";
} }
@ -1079,23 +1079,23 @@ export class BeltPath extends BasicSerializableObject {
]>; ]>;
root: GameRoot; root: GameRoot;
zoomLevel: number; zoomLevel: number;
}): any { }) {
context.scale(dpi, dpi); context.scale(dpi, dpi);
if (G_IS_DEV && globalConfig.debug.showShapeGrouping) { if (G_IS_DEV && globalConfig.debug.showShapeGrouping) {
context.fillStyle = "rgba(0, 0, 255, 0.5)"; context.fillStyle = "rgba(0, 0, 255, 0.5)";
context.fillRect(0, 0, w, h); context.fillRect(0, 0, w, h);
} }
const parameters: any = new DrawParameters({ const parameters = new DrawParameters({
context, context,
desiredAtlasScale: ORIGINAL_SPRITE_SCALE, desiredAtlasScale: ORIGINAL_SPRITE_SCALE,
root, root,
visibleRect: new Rectangle(-1000, -1000, 2000, 2000), visibleRect: new Rectangle(-1000, -1000, 2000, 2000),
zoomLevel, zoomLevel,
}); });
const itemSize: any = globalConfig.itemSpacingOnBelts * globalConfig.tileSize; const itemSize = globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
const item: any = stack[0]; const item = stack[0];
const pos: any = new Vector(itemSize / 2, itemSize / 2); const pos = new Vector(itemSize / 2, itemSize / 2);
for (let i: any = 0; i < stack.length; i++) { for (let i = 0; i < stack.length; i++) {
item[1].drawItemCenteredClipped(pos.x, pos.y, parameters, globalConfig.defaultItemDiameter); item[1].drawItemCenteredClipped(pos.x, pos.y, parameters, globalConfig.defaultItemDiameter);
pos[direction] += globalConfig.itemSpacingOnBelts * globalConfig.tileSize; pos[direction] += globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
} }
@ -1103,23 +1103,23 @@ export class BeltPath extends BasicSerializableObject {
drawDrawStack(stack: Array<[ drawDrawStack(stack: Array<[
Vector, Vector,
BaseItem BaseItem
]>, parameters: DrawParameters, directionProp: any): any { ]>, parameters: DrawParameters, directionProp) {
if (stack.length === 0) { if (stack.length === 0) {
return; return;
} }
const firstItem: any = stack[0]; const firstItem = stack[0];
const firstItemPos: any = firstItem[0]; const firstItemPos = firstItem[0];
if (stack.length === 1) { if (stack.length === 1) {
firstItem[1].drawItemCenteredClipped(firstItemPos.x, firstItemPos.y, parameters, globalConfig.defaultItemDiameter); firstItem[1].drawItemCenteredClipped(firstItemPos.x, firstItemPos.y, parameters, globalConfig.defaultItemDiameter);
return; return;
} }
const itemSize: any = globalConfig.itemSpacingOnBelts * globalConfig.tileSize; const itemSize = globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
const inverseDirection: any = directionProp === "x" ? "y" : "x"; const inverseDirection = directionProp === "x" ? "y" : "x";
const dimensions: any = new Vector(itemSize, itemSize); const dimensions = new Vector(itemSize, itemSize);
dimensions[inverseDirection] *= stack.length; dimensions[inverseDirection] *= stack.length;
const directionVector: any = firstItemPos.copy().sub(stack[1][0]); const directionVector = firstItemPos.copy().sub(stack[1][0]);
const dpi: any = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel);
const sprite: any = this.root.buffers.getForKey({ const sprite = this.root.buffers.getForKey({
key: "beltpaths", key: "beltpaths",
subKey: "stack-" + subKey: "stack-" +
directionProp + directionProp +
@ -1142,7 +1142,7 @@ export class BeltPath extends BasicSerializableObject {
zoomLevel: parameters.zoomLevel, zoomLevel: parameters.zoomLevel,
}, },
}); });
const anchor: any = directionVector[inverseDirection] < 0 ? firstItem : stack[stack.length - 1]; const anchor = directionVector[inverseDirection] < 0 ? firstItem : stack[stack.length - 1];
parameters.context.drawImage(sprite, anchor[0].x - itemSize / 2, anchor[0].y - itemSize / 2, dimensions.x, dimensions.y); parameters.context.drawImage(sprite, anchor[0].x - itemSize / 2, anchor[0].y - itemSize / 2, dimensions.x, dimensions.y);
} }
} }

View File

@ -23,21 +23,21 @@ export class Blueprint {
/** /**
* Creates a new blueprint from the given entity uids * Creates a new blueprint from the given entity uids
*/ */
static fromUids(root: GameRoot, uids: Array<number>): any { static fromUids(root: GameRoot, uids: Array<number>) {
const newEntities: any = []; const newEntities = [];
let averagePosition: any = new Vector(); let averagePosition = new Vector();
// First, create a copy // First, create a copy
for (let i: any = 0; i < uids.length; ++i) { for (let i = 0; i < uids.length; ++i) {
const entity: any = root.entityMgr.findByUid(uids[i]); const entity = root.entityMgr.findByUid(uids[i]);
assert(entity, "Entity for blueprint not found:" + uids[i]); assert(entity, "Entity for blueprint not found:" + uids[i]);
const clone: any = entity.clone(); const clone = entity.clone();
newEntities.push(clone); newEntities.push(clone);
const pos: any = entity.components.StaticMapEntity.getTileSpaceBounds().getCenter(); const pos = entity.components.StaticMapEntity.getTileSpaceBounds().getCenter();
averagePosition.addInplace(pos); averagePosition.addInplace(pos);
} }
averagePosition.divideScalarInplace(uids.length); averagePosition.divideScalarInplace(uids.length);
const blueprintOrigin: any = averagePosition.subScalars(0.5, 0.5).floor(); const blueprintOrigin = averagePosition.subScalars(0.5, 0.5).floor();
for (let i: any = 0; i < uids.length; ++i) { for (let i = 0; i < uids.length; ++i) {
newEntities[i].components.StaticMapEntity.origin.subInplace(blueprintOrigin); newEntities[i].components.StaticMapEntity.origin.subInplace(blueprintOrigin);
} }
// Now, make sure the origin is 0,0 // Now, make sure the origin is 0,0
@ -46,7 +46,7 @@ export class Blueprint {
/** /**
* Returns the cost of this blueprint in shapes * Returns the cost of this blueprint in shapes
*/ */
getCost(): any { getCost() {
if (G_IS_DEV && globalConfig.debug.blueprintsNoCost) { if (G_IS_DEV && globalConfig.debug.blueprintsNoCost) {
return 0; return 0;
} }
@ -55,13 +55,13 @@ export class Blueprint {
/** /**
* Draws the blueprint at the given origin * Draws the blueprint at the given origin
*/ */
draw(parameters: DrawParameters, tile: any): any { draw(parameters: DrawParameters, tile) {
parameters.context.globalAlpha = 0.8; parameters.context.globalAlpha = 0.8;
for (let i: any = 0; i < this.entities.length; ++i) { for (let i = 0; i < this.entities.length; ++i) {
const entity: any = this.entities[i]; const entity = this.entities[i];
const staticComp: any = entity.components.StaticMapEntity; const staticComp = entity.components.StaticMapEntity;
const newPos: any = staticComp.origin.add(tile); const newPos = staticComp.origin.add(tile);
const rect: any = staticComp.getTileSpaceBounds(); const rect = staticComp.getTileSpaceBounds();
rect.moveBy(tile.x, tile.y); rect.moveBy(tile.x, tile.y);
if (!parameters.root.logic.checkCanPlaceEntity(entity, { offset: tile })) { if (!parameters.root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
parameters.context.globalAlpha = 0.3; parameters.context.globalAlpha = 0.3;
@ -76,10 +76,10 @@ export class Blueprint {
/** /**
* Rotates the blueprint clockwise * Rotates the blueprint clockwise
*/ */
rotateCw(): any { rotateCw() {
for (let i: any = 0; i < this.entities.length; ++i) { for (let i = 0; i < this.entities.length; ++i) {
const entity: any = this.entities[i]; const entity = this.entities[i];
const staticComp: any = entity.components.StaticMapEntity; const staticComp = entity.components.StaticMapEntity;
// Actually keeping this in as an easter egg to rotate the trash can // Actually keeping this in as an easter egg to rotate the trash can
// if (staticComp.getMetaBuilding().getIsRotateable()) { // if (staticComp.getMetaBuilding().getIsRotateable()) {
staticComp.rotation = (staticComp.rotation + 90) % 360; staticComp.rotation = (staticComp.rotation + 90) % 360;
@ -91,26 +91,26 @@ export class Blueprint {
/** /**
* Rotates the blueprint counter clock wise * Rotates the blueprint counter clock wise
*/ */
rotateCcw(): any { rotateCcw() {
// Well ... // Well ...
for (let i: any = 0; i < 3; ++i) { for (let i = 0; i < 3; ++i) {
this.rotateCw(); this.rotateCw();
} }
} }
/** /**
* Checks if the blueprint can be placed at the given tile * Checks if the blueprint can be placed at the given tile
*/ */
canPlace(root: GameRoot, tile: Vector): any { canPlace(root: GameRoot, tile: Vector) {
let anyPlaceable: any = false; let anyPlaceable = false;
for (let i: any = 0; i < this.entities.length; ++i) { for (let i = 0; i < this.entities.length; ++i) {
const entity: any = this.entities[i]; const entity = this.entities[i];
if (root.logic.checkCanPlaceEntity(entity, { offset: tile })) { if (root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
anyPlaceable = true; anyPlaceable = true;
} }
} }
return anyPlaceable; return anyPlaceable;
} }
canAfford(root: GameRoot): any { canAfford(root: GameRoot) {
if (root.gameMode.getHasFreeCopyPaste()) { if (root.gameMode.getHasFreeCopyPaste()) {
return true; return true;
} }
@ -119,16 +119,16 @@ export class Blueprint {
/** /**
* Attempts to place the blueprint at the given tile * Attempts to place the blueprint at the given tile
*/ */
tryPlace(root: GameRoot, tile: Vector): any { tryPlace(root: GameRoot, tile: Vector) {
return root.logic.performBulkOperation((): any => { return root.logic.performBulkOperation(() => {
return root.logic.performImmutableOperation((): any => { return root.logic.performImmutableOperation(() => {
let count: any = 0; let count = 0;
for (let i: any = 0; i < this.entities.length; ++i) { for (let i = 0; i < this.entities.length; ++i) {
const entity: any = this.entities[i]; const entity = this.entities[i];
if (!root.logic.checkCanPlaceEntity(entity, { offset: tile })) { if (!root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
continue; continue;
} }
const clone: any = entity.clone(); const clone = entity.clone();
clone.components.StaticMapEntity.origin.addInplace(tile); clone.components.StaticMapEntity.origin.addInplace(tile);
root.logic.freeEntityAreaBeforeBuild(clone); root.logic.freeEntityAreaBeforeBuild(clone);
root.map.placeStaticEntity(clone); root.map.placeStaticEntity(clone);

View File

@ -30,7 +30,7 @@ const variantsCache: Map<string, number | string> = new Map();
/** /**
* Registers a new variant * Registers a new variant
*/ */
export function registerBuildingVariant(code: number | string, meta: typeof MetaBuilding, variant: string = "default" /* @TODO: Circular dependency, actually its defaultBuildingVariant */, rotationVariant: number = 0): any { export function registerBuildingVariant(code: number | string, meta: typeof MetaBuilding, variant: string = "default" /* @TODO: Circular dependency, actually its defaultBuildingVariant */, rotationVariant: number = 0) {
assert(!gBuildingVariants[code], "Duplicate id: " + code); assert(!gBuildingVariants[code], "Duplicate id: " + code);
gBuildingVariants[code] = { gBuildingVariants[code] = {
metaClass: meta, metaClass: meta,
@ -166,7 +166,7 @@ functiorateBuildingHash(build string, variant: strin
* @param {number} rotationVariant * @param {number} rotationVariant
* @returns * @returns
*/ */
function generateBuildingHash(buildingId: string, variant: string, rotationVariant: number): any { function generateBuildingHash(buildingId: string, variant: string, rotationVariant: number) {
return buildingId + "/" + variant + "/" + rotationVariant; return buildingId + "/" + variant + "/" + rotationVariant;
} }
/** /**
@ -180,10 +180,10 @@ export function getBuildingDataFromCode(code: string | number): BuildingVariantI
/** /**
* Builds the cache for the codes * Builds the cache for the codes
*/ */
export function buildBuildingCodeCache(): any { export function buildBuildingCodeCache() {
for (const code: any in gBuildingVariants) { for (const code in gBuildingVariants) {
const data: any = gBuildingVariants[code]; const data = gBuildingVariants[code];
const hash: any = generateBuildingHash(data.metaInstance.getId(), data.variant, data.rotationVariant); const hash = generateBuildingHash(data.metaInstance.getId(), data.variant, data.rotationVariant);
variantsCache.set(hash, isNaN(+code) ? code : +code); variantsCache.set(hash, isNaN(+code) ? code : +code);
} }
} }
@ -192,8 +192,8 @@ export function buildBuildingCodeCache(): any {
* {} * {}
*/ */
export function getCodeFromBuildingData(metaBuilding: MetaBuilding, variant: string, rotationVariant: number): number | string { export function getCodeFromBuildingData(metaBuilding: MetaBuilding, variant: string, rotationVariant: number): number | string {
const hash: any = generateBuildingHash(metaBuilding.getId(), variant, rotationVariant); const hash = generateBuildingHash(metaBuilding.getId(), variant, rotationVariant);
const result: any = variantsCache.get(hash); const result = variantsCache.get(hash);
if (G_IS_DEV) { if (G_IS_DEV) {
if (!result) { if (!result) {
console.warn("Known hashes:", Array.from(variantsCache.keys())); console.warn("Known hashes:", Array.from(variantsCache.keys()));

View File

@ -6,13 +6,13 @@ import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
const overlayMatrix: any = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 0]); const overlayMatrix = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 0]);
export class MetaAnalyzerBuilding extends MetaBuilding { export class MetaAnalyzerBuilding extends MetaBuilding {
constructor() { constructor() {
super("analyzer"); super("analyzer");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 43, internalId: 43,
@ -20,30 +20,30 @@ export class MetaAnalyzerBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#3a52bc"; return "#3a52bc";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing);
} }
/** {} **/ /** {} **/
getLayer(): "wires" { getLayer(): "wires" {
return "wires"; return "wires";
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getRenderPins(): any { getRenderPins() {
// We already have it included // We already have it included
return false; return false;
} }
getSpecialOverlayRenderMatrix(rotation: any, rotationVariant: any, variant: any): any { getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrix[rotation]; return overlayMatrix[rotation];
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -10,13 +10,13 @@ import { T } from "../../translations";
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
import { BeltUnderlaysComponent } from "../components/belt_underlays"; import { BeltUnderlaysComponent } from "../components/belt_underlays";
/** @enum {string} */ /** @enum {string} */
export const enumBalancerVariants: any = { export const enumBalancerVariants = {
merger: "merger", merger: "merger",
mergerInverse: "merger-inverse", mergerInverse: "merger-inverse",
splitter: "splitter", splitter: "splitter",
splitterInverse: "splitter-inverse", splitterInverse: "splitter-inverse",
}; };
const overlayMatrices: any = { const overlayMatrices = {
[defaultBuildingVariant]: null, [defaultBuildingVariant]: null,
[enumBalancerVariants.merger]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]), [enumBalancerVariants.merger]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
[enumBalancerVariants.mergerInverse]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]), [enumBalancerVariants.mergerInverse]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]),
@ -28,7 +28,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
constructor() { constructor() {
super("balancer"); super("balancer");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 4, internalId: 4,
@ -52,7 +52,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
}, },
]; ];
} }
getDimensions(variant: any): any { getDimensions(variant) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: case defaultBuildingVariant:
return new Vector(2, 1); return new Vector(2, 1);
@ -69,7 +69,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
* {} * {}
*/ */
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): Array<number> | null { getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): Array<number> | null {
const matrix: any = overlayMatrices[variant]; const matrix = overlayMatrices[variant];
if (matrix) { if (matrix) {
return matrix[rotation]; return matrix[rotation];
} }
@ -85,7 +85,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
if (root.gameMode.throughputDoesNotMatter()) { if (root.gameMode.throughputDoesNotMatter()) {
return []; return [];
} }
let speedMultiplier: any = 2; let speedMultiplier = 2;
switch (variant) { switch (variant) {
case enumBalancerVariants.merger: case enumBalancerVariants.merger:
case enumBalancerVariants.mergerInverse: case enumBalancerVariants.mergerInverse:
@ -93,15 +93,15 @@ export class MetaBalancerBuilding extends MetaBuilding {
case enumBalancerVariants.splitterInverse: case enumBalancerVariants.splitterInverse:
speedMultiplier = 1; speedMultiplier = 1;
} }
const speed: any = (root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.balancer) / 2) * speedMultiplier; const speed = (root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.balancer) / 2) * speedMultiplier;
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#555759"; return "#555759";
} }
getAvailableVariants(root: GameRoot): any { getAvailableVariants(root: GameRoot) {
const deterministic: any = root.gameMode.getIsDeterministic(); const deterministic = root.gameMode.getIsDeterministic();
let available: any = deterministic ? [] : [defaultBuildingVariant]; let available = deterministic ? [] : [defaultBuildingVariant];
if (!deterministic && root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_merger)) { if (!deterministic && root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_merger)) {
available.push(enumBalancerVariants.merger, enumBalancerVariants.mergerInverse); available.push(enumBalancerVariants.merger, enumBalancerVariants.mergerInverse);
} }
@ -110,13 +110,13 @@ export class MetaBalancerBuilding extends MetaBuilding {
} }
return available; return available;
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_balancer); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_balancer);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemAcceptorComponent({ entity.addComponent(new ItemAcceptorComponent({
slots: [], // set later slots: [], // set later
})); }));
@ -130,7 +130,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
})); }));
entity.addComponent(new BeltUnderlaysComponent({ underlays: [] })); entity.addComponent(new BeltUnderlaysComponent({ underlays: [] }));
} }
updateVariants(entity: Entity, rotationVariant: number, variant: string): any { updateVariants(entity: Entity, rotationVariant: number, variant: string) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: { case defaultBuildingVariant: {
entity.components.ItemAcceptor.setSlots([ entity.components.ItemAcceptor.setSlots([

View File

@ -8,8 +8,8 @@ import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { THEME } from "../theme"; import { THEME } from "../theme";
export const arrayBeltVariantToRotation: any = [enumDirection.top, enumDirection.left, enumDirection.right]; export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right];
export const beltOverlayMatrices: any = { export const beltOverlayMatrices = {
[enumDirection.top]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), [enumDirection.top]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
[enumDirection.left]: generateMatrixRotations([0, 0, 0, 1, 1, 0, 0, 1, 0]), [enumDirection.left]: generateMatrixRotations([0, 0, 0, 1, 1, 0, 0, 1, 0]),
[enumDirection.right]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]), [enumDirection.right]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
@ -19,7 +19,7 @@ export class MetaBeltBuilding extends MetaBuilding {
constructor() { constructor() {
super("belt"); super("belt");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 1, internalId: 1,
@ -38,25 +38,25 @@ export class MetaBeltBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return THEME.map.chunkOverview.beltColor; return THEME.map.chunkOverview.beltColor;
} }
getPlacementSound(): any { getPlacementSound() {
return SOUNDS.placeBelt; return SOUNDS.placeBelt;
} }
getHasDirectionLockAvailable(): any { getHasDirectionLockAvailable() {
return true; return true;
} }
getStayInPlacementMode(): any { getStayInPlacementMode() {
return true; return true;
} }
getRotateAutomaticallyWhilePlacing(): any { getRotateAutomaticallyWhilePlacing() {
return true; return true;
} }
getSprite(): any { getSprite() {
return null; return null;
} }
getIsReplaceable(): any { getIsReplaceable() {
return true; return true;
} }
/** /**
@ -69,10 +69,10 @@ export class MetaBeltBuilding extends MetaBuilding {
if (root.gameMode.throughputDoesNotMatter()) { if (root.gameMode.throughputDoesNotMatter()) {
return []; return [];
} }
const beltSpeed: any = root.hubGoals.getBeltBaseSpeed(); const beltSpeed = root.hubGoals.getBeltBaseSpeed();
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
} }
getPreviewSprite(rotationVariant: any): any { getPreviewSprite(rotationVariant) {
switch (arrayBeltVariantToRotation[rotationVariant]) { switch (arrayBeltVariantToRotation[rotationVariant]) {
case enumDirection.top: { case enumDirection.top: {
return Loader.getSprite("sprites/buildings/belt_top.png"); return Loader.getSprite("sprites/buildings/belt_top.png");
@ -88,7 +88,7 @@ export class MetaBeltBuilding extends MetaBuilding {
} }
} }
} }
getBlueprintSprite(rotationVariant: any): any { getBlueprintSprite(rotationVariant) {
switch (arrayBeltVariantToRotation[rotationVariant]) { switch (arrayBeltVariantToRotation[rotationVariant]) {
case enumDirection.top: { case enumDirection.top: {
return Loader.getSprite("sprites/blueprints/belt_top.png"); return Loader.getSprite("sprites/blueprints/belt_top.png");
@ -104,18 +104,18 @@ export class MetaBeltBuilding extends MetaBuilding {
} }
} }
} }
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): any { getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity) {
return beltOverlayMatrices[entity.components.Belt.direction][rotation]; return beltOverlayMatrices[entity.components.Belt.direction][rotation];
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new BeltComponent({ entity.addComponent(new BeltComponent({
direction: enumDirection.top, // updated later direction: enumDirection.top, // updated later
})); }));
} }
updateVariants(entity: Entity, rotationVariant: number): any { updateVariants(entity: Entity, rotationVariant: number) {
entity.components.Belt.direction = arrayBeltVariantToRotation[rotationVariant]; entity.components.Belt.direction = arrayBeltVariantToRotation[rotationVariant];
} }
/** /**
@ -133,20 +133,20 @@ export class MetaBeltBuilding extends MetaBuilding {
rotationVariant: number; rotationVariant: number;
connectedEntities?: Array<Entity>; connectedEntities?: Array<Entity>;
} { } {
const topDirection: any = enumAngleToDirection[rotation]; const topDirection = enumAngleToDirection[rotation];
const rightDirection: any = enumAngleToDirection[(rotation + 90) % 360]; const rightDirection = enumAngleToDirection[(rotation + 90) % 360];
const bottomDirection: any = enumAngleToDirection[(rotation + 180) % 360]; const bottomDirection = enumAngleToDirection[(rotation + 180) % 360];
const leftDirection: any = enumAngleToDirection[(rotation + 270) % 360]; const leftDirection = enumAngleToDirection[(rotation + 270) % 360];
const { ejectors, acceptors }: any = root.logic.getEjectorsAndAcceptorsAtTile(tile); const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile);
let hasBottomEjector: any = false; let hasBottomEjector = false;
let hasRightEjector: any = false; let hasRightEjector = false;
let hasLeftEjector: any = false; let hasLeftEjector = false;
let hasTopAcceptor: any = false; let hasTopAcceptor = false;
let hasLeftAcceptor: any = false; let hasLeftAcceptor = false;
let hasRightAcceptor: any = false; let hasRightAcceptor = false;
// Check all ejectors // Check all ejectors
for (let i: any = 0; i < ejectors.length; ++i) { for (let i = 0; i < ejectors.length; ++i) {
const ejector: any = ejectors[i]; const ejector = ejectors[i];
if (ejector.toDirection === topDirection) { if (ejector.toDirection === topDirection) {
hasBottomEjector = true; hasBottomEjector = true;
} }
@ -158,8 +158,8 @@ export class MetaBeltBuilding extends MetaBuilding {
} }
} }
// Check all acceptors // Check all acceptors
for (let i: any = 0; i < acceptors.length; ++i) { for (let i = 0; i < acceptors.length; ++i) {
const acceptor: any = acceptors[i]; const acceptor = acceptors[i];
if (acceptor.fromDirection === bottomDirection) { if (acceptor.fromDirection === bottomDirection) {
hasTopAcceptor = true; hasTopAcceptor = true;
} }

View File

@ -7,7 +7,7 @@ export class MetaBlockBuilding extends MetaBuilding {
constructor() { constructor() {
super("block"); super("block");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 64, internalId: 64,
@ -15,7 +15,7 @@ export class MetaBlockBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#333"; return "#333";
} }
/** /**
@ -138,11 +138,11 @@ export class MetaBlockBuilding extends MetaBuilding {
* @param {import("../../savegame/savegame_serializer").GameRoot} root * @param {import("../../savegame/savegame_serializer").GameRoot} root
* @returns * @returns
*/ */
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot): any { getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot) {
return root.gameMode.getIsEditor(); return root.gameMode.getIsEditor();
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { } setupEntityComponents(entity: Entity) { }
} }

View File

@ -10,7 +10,7 @@ export class MetaComparatorBuilding extends MetaBuilding {
constructor() { constructor() {
super("comparator"); super("comparator");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 46, internalId: 46,
@ -18,27 +18,27 @@ export class MetaComparatorBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#823cab"; return "#823cab";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing);
} }
/** {} **/ /** {} **/
getLayer(): "wires" { getLayer(): "wires" {
return "wires"; return "wires";
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getRenderPins(): any { getRenderPins() {
// We already have it included // We already have it included
return false; return false;
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -11,7 +11,7 @@ export class MetaConstantProducerBuilding extends MetaBuilding {
constructor() { constructor() {
super("constant_producer"); super("constant_producer");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 62, internalId: 62,
@ -19,7 +19,7 @@ export class MetaConstantProducerBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#bfd630"; return "#bfd630";
} }
/** /**
@ -142,13 +142,13 @@ export class MetaConstantProducerBuilding extends MetaBuilding {
* @param {import("../../savegame/savegame_serializer").GameRoot} root * @param {import("../../savegame/savegame_serializer").GameRoot} root
* @returns * @returns
*/ */
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot): any { getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot) {
return root.gameMode.getIsEditor(); return root.gameMode.getIsEditor();
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemEjectorComponent({ entity.addComponent(new ItemEjectorComponent({
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
})); }));

View File

@ -6,13 +6,13 @@ import { GameRoot } from "../root";
import { ConstantSignalComponent } from "../components/constant_signal"; import { ConstantSignalComponent } from "../components/constant_signal";
import { generateMatrixRotations } from "../../core/utils"; import { generateMatrixRotations } from "../../core/utils";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
const overlayMatrix: any = generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]); const overlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]);
export class MetaConstantSignalBuilding extends MetaBuilding { export class MetaConstantSignalBuilding extends MetaBuilding {
constructor() { constructor() {
super("constant_signal"); super("constant_signal");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 31, internalId: 31,
@ -20,29 +20,29 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#2b84fd"; return "#2b84fd";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_constant_signal); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_constant_signal);
} }
/** {} **/ /** {} **/
getLayer(): "wires" { getLayer(): "wires" {
return "wires"; return "wires";
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getRenderPins(): any { getRenderPins() {
return false; return false;
} }
getSpecialOverlayRenderMatrix(rotation: any): any { getSpecialOverlayRenderMatrix(rotation) {
return overlayMatrix[rotation]; return overlayMatrix[rotation];
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -9,13 +9,13 @@ import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
/** @enum {string} */ /** @enum {string} */
export const enumCutterVariants: any = { quad: "quad" }; export const enumCutterVariants = { quad: "quad" };
export class MetaCutterBuilding extends MetaBuilding { export class MetaCutterBuilding extends MetaBuilding {
constructor() { constructor() {
super("cutter"); super("cutter");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 9, internalId: 9,
@ -27,10 +27,10 @@ export class MetaCutterBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#7dcda2"; return "#7dcda2";
} }
getDimensions(variant: any): any { getDimensions(variant) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: case defaultBuildingVariant:
return new Vector(2, 1); return new Vector(2, 1);
@ -50,24 +50,24 @@ export class MetaCutterBuilding extends MetaBuilding {
if (root.gameMode.throughputDoesNotMatter()) { if (root.gameMode.throughputDoesNotMatter()) {
return []; return [];
} }
const speed: any = root.hubGoals.getProcessorBaseSpeed(variant === enumCutterVariants.quad const speed = root.hubGoals.getProcessorBaseSpeed(variant === enumCutterVariants.quad
? enumItemProcessorTypes.cutterQuad ? enumItemProcessorTypes.cutterQuad
: enumItemProcessorTypes.cutter); : enumItemProcessorTypes.cutter);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
getAvailableVariants(root: GameRoot): any { getAvailableVariants(root: GameRoot) {
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_quad)) { if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_quad)) {
return [defaultBuildingVariant, enumCutterVariants.quad]; return [defaultBuildingVariant, enumCutterVariants.quad];
} }
return super.getAvailableVariants(root); return super.getAvailableVariants(root);
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemProcessorComponent({ entity.addComponent(new ItemProcessorComponent({
inputsPerCharge: 1, inputsPerCharge: 1,
processorType: enumItemProcessorTypes.cutter, processorType: enumItemProcessorTypes.cutter,
@ -83,7 +83,7 @@ export class MetaCutterBuilding extends MetaBuilding {
], ],
})); }));
} }
updateVariants(entity: Entity, rotationVariant: number, variant: string): any { updateVariants(entity: Entity, rotationVariant: number, variant: string) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: { case defaultBuildingVariant: {
entity.components.ItemEjector.setSlots([ entity.components.ItemEjector.setSlots([

View File

@ -10,7 +10,7 @@ export class MetaDisplayBuilding extends MetaBuilding {
constructor() { constructor() {
super("display"); super("display");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 40, internalId: 40,
@ -18,22 +18,22 @@ export class MetaDisplayBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#aaaaaa"; return "#aaaaaa";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_display); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_display);
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getShowWiresLayerPreview(): any { getShowWiresLayerPreview() {
return true; return true;
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -14,7 +14,7 @@ export class MetaFilterBuilding extends MetaBuilding {
constructor() { constructor() {
super("filter"); super("filter");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 37, internalId: 37,
@ -22,16 +22,16 @@ export class MetaFilterBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#c45c2e"; return "#c45c2e";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_filter); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_filter);
} }
getDimensions(): any { getDimensions() {
return new Vector(2, 1); return new Vector(2, 1);
} }
getShowWiresLayerPreview(): any { getShowWiresLayerPreview() {
return true; return true;
} }
/** /**
@ -44,13 +44,13 @@ export class MetaFilterBuilding extends MetaBuilding {
if (root.gameMode.throughputDoesNotMatter()) { if (root.gameMode.throughputDoesNotMatter()) {
return []; return [];
} }
const beltSpeed: any = root.hubGoals.getBeltBaseSpeed(); const beltSpeed = root.hubGoals.getBeltBaseSpeed();
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -11,7 +11,7 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding {
constructor() { constructor() {
super("goal_acceptor"); super("goal_acceptor");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 63, internalId: 63,
@ -19,7 +19,7 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#ce418a"; return "#ce418a";
} }
/** /**
@ -142,13 +142,13 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding {
* @param {import("../../savegame/savegame_serializer").GameRoot} root * @param {import("../../savegame/savegame_serializer").GameRoot} root
* @returns * @returns
*/ */
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot): any { getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot) {
return root.gameMode.getIsEditor(); return root.gameMode.getIsEditor();
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemAcceptorComponent({ entity.addComponent(new ItemAcceptorComponent({
slots: [ slots: [
{ {

View File

@ -10,7 +10,7 @@ export class MetaHubBuilding extends MetaBuilding {
constructor() { constructor() {
super("hub"); super("hub");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 26, internalId: 26,
@ -18,29 +18,29 @@ export class MetaHubBuilding extends MetaBuilding {
}, },
]; ];
} }
getDimensions(): any { getDimensions() {
return new Vector(4, 4); return new Vector(4, 4);
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#eb5555"; return "#eb5555";
} }
getIsRotateable(): any { getIsRotateable() {
return false; return false;
} }
getBlueprintSprite(): any { getBlueprintSprite() {
return null; return null;
} }
getSprite(): any { getSprite() {
// We render it ourself // We render it ourself
return null; return null;
} }
getIsRemovable(): any { getIsRemovable() {
return false; return false;
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new HubComponent()); entity.addComponent(new HubComponent());
entity.addComponent(new ItemProcessorComponent({ entity.addComponent(new ItemProcessorComponent({
inputsPerCharge: 1, inputsPerCharge: 1,
@ -56,7 +56,7 @@ export class MetaHubBuilding extends MetaBuilding {
], ],
})); }));
const slots: Array<import("../components/item_acceptor").ItemAcceptorSlotConfig> = []; const slots: Array<import("../components/item_acceptor").ItemAcceptorSlotConfig> = [];
for (let i: any = 0; i < 4; ++i) { for (let i = 0; i < 4; ++i) {
slots.push({ pos: new Vector(i, 0), direction: enumDirection.top, filter: "shape" }, { pos: new Vector(i, 3), direction: enumDirection.bottom, filter: "shape" }, { pos: new Vector(0, i), direction: enumDirection.left, filter: "shape" }, { pos: new Vector(3, i), direction: enumDirection.right, filter: "shape" }); slots.push({ pos: new Vector(i, 0), direction: enumDirection.top, filter: "shape" }, { pos: new Vector(i, 3), direction: enumDirection.bottom, filter: "shape" }, { pos: new Vector(0, i), direction: enumDirection.left, filter: "shape" }, { pos: new Vector(3, i), direction: enumDirection.right, filter: "shape" });
} }
entity.addComponent(new ItemAcceptorComponent({ entity.addComponent(new ItemAcceptorComponent({

View File

@ -9,7 +9,7 @@ export class MetaItemProducerBuilding extends MetaBuilding {
constructor() { constructor() {
super("item_producer"); super("item_producer");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 61, internalId: 61,
@ -17,16 +17,16 @@ export class MetaItemProducerBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#b37dcd"; return "#b37dcd";
} }
getShowWiresLayerPreview(): any { getShowWiresLayerPreview() {
return true; return true;
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemEjectorComponent({ entity.addComponent(new ItemEjectorComponent({
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
})); }));

View File

@ -10,7 +10,7 @@ export class MetaLeverBuilding extends MetaBuilding {
constructor() { constructor() {
super("lever"); super("lever");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 33, internalId: 33,
@ -18,26 +18,26 @@ export class MetaLeverBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
// @todo: Render differently based on if its activated or not // @todo: Render differently based on if its activated or not
return "#1a678b"; return "#1a678b";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers);
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getSprite(): any { getSprite() {
return null; return null;
} }
getShowWiresLayerPreview(): any { getShowWiresLayerPreview() {
return true; return true;
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -7,25 +7,25 @@ import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"
import { generateMatrixRotations } from "../../core/utils"; import { generateMatrixRotations } from "../../core/utils";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
/** @enum {string} */ /** @enum {string} */
export const enumLogicGateVariants: any = { export const enumLogicGateVariants = {
not: "not", not: "not",
xor: "xor", xor: "xor",
or: "or", or: "or",
}; };
/** @enum {string} */ /** @enum {string} */
const enumVariantToGate: any = { const enumVariantToGate = {
[defaultBuildingVariant]: enumLogicGateType.and, [defaultBuildingVariant]: enumLogicGateType.and,
[enumLogicGateVariants.not]: enumLogicGateType.not, [enumLogicGateVariants.not]: enumLogicGateType.not,
[enumLogicGateVariants.xor]: enumLogicGateType.xor, [enumLogicGateVariants.xor]: enumLogicGateType.xor,
[enumLogicGateVariants.or]: enumLogicGateType.or, [enumLogicGateVariants.or]: enumLogicGateType.or,
}; };
const overlayMatrices: any = { const overlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]), [defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
[enumLogicGateVariants.xor]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]), [enumLogicGateVariants.xor]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
[enumLogicGateVariants.or]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]), [enumLogicGateVariants.or]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
[enumLogicGateVariants.not]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), [enumLogicGateVariants.not]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
}; };
const colors: any = { const colors = {
[defaultBuildingVariant]: "#f48d41", [defaultBuildingVariant]: "#f48d41",
[enumLogicGateVariants.xor]: "#f4a241", [enumLogicGateVariants.xor]: "#f4a241",
[enumLogicGateVariants.or]: "#f4d041", [enumLogicGateVariants.or]: "#f4d041",
@ -36,7 +36,7 @@ export class MetaLogicGateBuilding extends MetaBuilding {
constructor() { constructor() {
super("logic_gate"); super("logic_gate");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 32, internalId: 32,
@ -56,23 +56,23 @@ export class MetaLogicGateBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(variant: any): any { getSilhouetteColor(variant) {
return colors[variant]; return colors[variant];
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates);
} }
/** {} **/ /** {} **/
getLayer(): "wires" { getLayer(): "wires" {
return "wires"; return "wires";
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getSpecialOverlayRenderMatrix(rotation: any, rotationVariant: any, variant: any): any { getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrices[variant][rotation]; return overlayMatrices[variant][rotation];
} }
getAvailableVariants(): any { getAvailableVariants() {
return [ return [
defaultBuildingVariant, defaultBuildingVariant,
enumLogicGateVariants.or, enumLogicGateVariants.or,
@ -80,14 +80,14 @@ export class MetaLogicGateBuilding extends MetaBuilding {
enumLogicGateVariants.xor, enumLogicGateVariants.xor,
]; ];
} }
getRenderPins(): any { getRenderPins() {
// We already have it included // We already have it included
return false; return false;
} }
updateVariants(entity: Entity, rotationVariant: number, variant: any): any { updateVariants(entity: Entity, rotationVariant: number, variant) {
const gateType: any = enumVariantToGate[variant]; const gateType = enumVariantToGate[variant];
entity.components.LogicGate.type = gateType; entity.components.LogicGate.type = gateType;
const pinComp: any = entity.components.WiredPins; const pinComp = entity.components.WiredPins;
switch (gateType) { switch (gateType) {
case enumLogicGateType.and: case enumLogicGateType.and:
case enumLogicGateType.xor: case enumLogicGateType.xor:
@ -133,7 +133,7 @@ export class MetaLogicGateBuilding extends MetaBuilding {
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [], slots: [],
})); }));

View File

@ -8,8 +8,8 @@ import { enumHubGoalRewards } from "../tutorial_goals";
import { T } from "../../translations"; import { T } from "../../translations";
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
/** @enum {string} */ /** @enum {string} */
export const enumMinerVariants: any = { chainable: "chainable" }; export const enumMinerVariants = { chainable: "chainable" };
const overlayMatrix: any = { const overlayMatrix = {
[defaultBuildingVariant]: generateMatrixRotations([1, 1, 1, 1, 0, 1, 1, 1, 1]), [defaultBuildingVariant]: generateMatrixRotations([1, 1, 1, 1, 0, 1, 1, 1, 1]),
[enumMinerVariants.chainable]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]), [enumMinerVariants.chainable]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]),
}; };
@ -18,7 +18,7 @@ export class MetaMinerBuilding extends MetaBuilding {
constructor() { constructor() {
super("miner"); super("miner");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 7, internalId: 7,
@ -30,7 +30,7 @@ export class MetaMinerBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#b37dcd"; return "#b37dcd";
} }
/** /**
@ -43,28 +43,28 @@ export class MetaMinerBuilding extends MetaBuilding {
if (root.gameMode.throughputDoesNotMatter()) { if (root.gameMode.throughputDoesNotMatter()) {
return []; return [];
} }
const speed: any = root.hubGoals.getMinerBaseSpeed(); const speed = root.hubGoals.getMinerBaseSpeed();
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
getAvailableVariants(root: GameRoot): any { getAvailableVariants(root: GameRoot) {
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) {
return [enumMinerVariants.chainable]; return [enumMinerVariants.chainable];
} }
return super.getAvailableVariants(root); return super.getAvailableVariants(root);
} }
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): any { getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity) {
return overlayMatrix[variant][rotation]; return overlayMatrix[variant][rotation];
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new MinerComponent({})); entity.addComponent(new MinerComponent({}));
entity.addComponent(new ItemEjectorComponent({ entity.addComponent(new ItemEjectorComponent({
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
})); }));
} }
updateVariants(entity: Entity, rotationVariant: number, variant: string): any { updateVariants(entity: Entity, rotationVariant: number, variant: string) {
entity.components.Miner.chainable = variant === enumMinerVariants.chainable; entity.components.Miner.chainable = variant === enumMinerVariants.chainable;
} }
} }

View File

@ -13,7 +13,7 @@ export class MetaMixerBuilding extends MetaBuilding {
constructor() { constructor() {
super("mixer"); super("mixer");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 15, internalId: 15,
@ -21,13 +21,13 @@ export class MetaMixerBuilding extends MetaBuilding {
}, },
]; ];
} }
getDimensions(): any { getDimensions() {
return new Vector(2, 1); return new Vector(2, 1);
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#cdbb7d"; return "#cdbb7d";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_mixer); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_mixer);
} }
/** /**
@ -40,13 +40,13 @@ export class MetaMixerBuilding extends MetaBuilding {
if (root.gameMode.throughputDoesNotMatter()) { if (root.gameMode.throughputDoesNotMatter()) {
return []; return [];
} }
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.mixer); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.mixer);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemProcessorComponent({ entity.addComponent(new ItemProcessorComponent({
inputsPerCharge: 2, inputsPerCharge: 2,
processorType: enumItemProcessorTypes.mixer, processorType: enumItemProcessorTypes.mixer,

View File

@ -10,13 +10,13 @@ import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
/** @enum {string} */ /** @enum {string} */
export const enumPainterVariants: any = { mirrored: "mirrored", double: "double", quad: "quad" }; export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" };
export class MetaPainterBuilding extends MetaBuilding { export class MetaPainterBuilding extends MetaBuilding {
constructor() { constructor() {
super("painter"); super("painter");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 16, internalId: 16,
@ -36,7 +36,7 @@ export class MetaPainterBuilding extends MetaBuilding {
}, },
]; ];
} }
getDimensions(variant: any): any { getDimensions(variant) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: case defaultBuildingVariant:
case enumPainterVariants.mirrored: case enumPainterVariants.mirrored:
@ -49,7 +49,7 @@ export class MetaPainterBuilding extends MetaBuilding {
assertAlways(false, "Unknown painter variant: " + variant); assertAlways(false, "Unknown painter variant: " + variant);
} }
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#cd9b7d"; return "#cd9b7d";
} }
/** /**
@ -65,21 +65,21 @@ export class MetaPainterBuilding extends MetaBuilding {
switch (variant) { switch (variant) {
case defaultBuildingVariant: case defaultBuildingVariant:
case enumPainterVariants.mirrored: { case enumPainterVariants.mirrored: {
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painter); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painter);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
case enumPainterVariants.double: { case enumPainterVariants.double: {
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painterDouble); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painterDouble);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed, true)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed, true)]];
} }
case enumPainterVariants.quad: { case enumPainterVariants.quad: {
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painterQuad); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painterQuad);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
} }
} }
getAvailableVariants(root: GameRoot): any { getAvailableVariants(root: GameRoot) {
let variants: any = [defaultBuildingVariant, enumPainterVariants.mirrored]; let variants = [defaultBuildingVariant, enumPainterVariants.mirrored];
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_double)) { if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_double)) {
variants.push(enumPainterVariants.double); variants.push(enumPainterVariants.double);
} }
@ -89,13 +89,13 @@ export class MetaPainterBuilding extends MetaBuilding {
} }
return variants; return variants;
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemProcessorComponent({})); entity.addComponent(new ItemProcessorComponent({}));
entity.addComponent(new ItemEjectorComponent({ entity.addComponent(new ItemEjectorComponent({
slots: [{ pos: new Vector(1, 0), direction: enumDirection.right }], slots: [{ pos: new Vector(1, 0), direction: enumDirection.right }],
@ -115,7 +115,7 @@ export class MetaPainterBuilding extends MetaBuilding {
], ],
})); }));
} }
updateVariants(entity: Entity, rotationVariant: number, variant: string): any { updateVariants(entity: Entity, rotationVariant: number, variant: string) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: case defaultBuildingVariant:
case enumPainterVariants.mirrored: { case enumPainterVariants.mirrored: {

View File

@ -10,13 +10,13 @@ import { BeltUnderlaysComponent } from "../components/belt_underlays";
import { BeltReaderComponent } from "../components/belt_reader"; import { BeltReaderComponent } from "../components/belt_reader";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { generateMatrixRotations } from "../../core/utils"; import { generateMatrixRotations } from "../../core/utils";
const overlayMatrix: any = generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]); const overlayMatrix = generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]);
export class MetaReaderBuilding extends MetaBuilding { export class MetaReaderBuilding extends MetaBuilding {
constructor() { constructor() {
super("reader"); super("reader");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 49, internalId: 49,
@ -24,16 +24,16 @@ export class MetaReaderBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#25fff2"; return "#25fff2";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_belt_reader); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_belt_reader);
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getShowWiresLayerPreview(): any { getShowWiresLayerPreview() {
return true; return true;
} }
/** /**
@ -45,7 +45,7 @@ export class MetaReaderBuilding extends MetaBuilding {
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -9,8 +9,8 @@ import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
/** @enum {string} */ /** @enum {string} */
export const enumRotaterVariants: any = { ccw: "ccw", rotate180: "rotate180" }; export const enumRotaterVariants = { ccw: "ccw", rotate180: "rotate180" };
const overlayMatrices: any = { const overlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 1, 1, 1, 0, 0, 1, 1]), [defaultBuildingVariant]: generateMatrixRotations([0, 1, 1, 1, 1, 0, 0, 1, 1]),
[enumRotaterVariants.ccw]: generateMatrixRotations([1, 1, 0, 0, 1, 1, 1, 1, 0]), [enumRotaterVariants.ccw]: generateMatrixRotations([1, 1, 0, 0, 1, 1, 1, 1, 0]),
[enumRotaterVariants.rotate180]: generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]), [enumRotaterVariants.rotate180]: generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]),
@ -20,7 +20,7 @@ export class MetaRotaterBuilding extends MetaBuilding {
constructor() { constructor() {
super("rotater"); super("rotater");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 11, internalId: 11,
@ -36,14 +36,14 @@ export class MetaRotaterBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#7dc6cd"; return "#7dc6cd";
} }
/** /**
* {} * {}
*/ */
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): Array<number> | null { getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): Array<number> | null {
const matrix: any = overlayMatrices[variant]; const matrix = overlayMatrices[variant];
if (matrix) { if (matrix) {
return matrix[rotation]; return matrix[rotation];
} }
@ -61,21 +61,21 @@ export class MetaRotaterBuilding extends MetaBuilding {
} }
switch (variant) { switch (variant) {
case defaultBuildingVariant: { case defaultBuildingVariant: {
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
case enumRotaterVariants.ccw: { case enumRotaterVariants.ccw: {
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotaterCCW); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotaterCCW);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
case enumRotaterVariants.rotate180: { case enumRotaterVariants.rotate180: {
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater180); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater180);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
} }
} }
getAvailableVariants(root: GameRoot): any { getAvailableVariants(root: GameRoot) {
let variants: any = [defaultBuildingVariant]; let variants = [defaultBuildingVariant];
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) { if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) {
variants.push(enumRotaterVariants.ccw); variants.push(enumRotaterVariants.ccw);
} }
@ -84,13 +84,13 @@ export class MetaRotaterBuilding extends MetaBuilding {
} }
return variants; return variants;
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemProcessorComponent({ entity.addComponent(new ItemProcessorComponent({
inputsPerCharge: 1, inputsPerCharge: 1,
processorType: enumItemProcessorTypes.rotater, processorType: enumItemProcessorTypes.rotater,
@ -108,7 +108,7 @@ export class MetaRotaterBuilding extends MetaBuilding {
], ],
})); }));
} }
updateVariants(entity: Entity, rotationVariant: number, variant: string): any { updateVariants(entity: Entity, rotationVariant: number, variant: string) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: { case defaultBuildingVariant: {
entity.components.ItemProcessor.type = enumItemProcessorTypes.rotater; entity.components.ItemProcessor.type = enumItemProcessorTypes.rotater;

View File

@ -13,7 +13,7 @@ export class MetaStackerBuilding extends MetaBuilding {
constructor() { constructor() {
super("stacker"); super("stacker");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 14, internalId: 14,
@ -21,10 +21,10 @@ export class MetaStackerBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#9fcd7d"; return "#9fcd7d";
} }
getDimensions(): any { getDimensions() {
return new Vector(2, 1); return new Vector(2, 1);
} }
/** /**
@ -37,16 +37,16 @@ export class MetaStackerBuilding extends MetaBuilding {
if (root.gameMode.throughputDoesNotMatter()) { if (root.gameMode.throughputDoesNotMatter()) {
return []; return [];
} }
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.stacker); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.stacker);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_stacker); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_stacker);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemProcessorComponent({ entity.addComponent(new ItemProcessorComponent({
inputsPerCharge: 2, inputsPerCharge: 2,
processorType: enumItemProcessorTypes.stacker, processorType: enumItemProcessorTypes.stacker,

View File

@ -9,13 +9,13 @@ import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
const storageSize: any = 5000; const storageSize = 5000;
export class MetaStorageBuilding extends MetaBuilding { export class MetaStorageBuilding extends MetaBuilding {
constructor() { constructor() {
super("storage"); super("storage");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 21, internalId: 21,
@ -23,28 +23,28 @@ export class MetaStorageBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#bbdf6d"; return "#bbdf6d";
} }
/** /**
* {} * {}
*/ */
getAdditionalStatistics(root: any, variant: any): Array<[ getAdditionalStatistics(root, variant): Array<[
string, string,
string string
]> { ]> {
return [[T.ingame.buildingPlacement.infoTexts.storage, formatBigNumber(storageSize)]]; return [[T.ingame.buildingPlacement.infoTexts.storage, formatBigNumber(storageSize)]];
} }
getDimensions(): any { getDimensions() {
return new Vector(2, 2); return new Vector(2, 2);
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_storage); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_storage);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
// Required, since the item processor needs this. // Required, since the item processor needs this.
entity.addComponent(new ItemEjectorComponent({ entity.addComponent(new ItemEjectorComponent({
slots: [ slots: [

View File

@ -7,10 +7,10 @@ import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
/** @enum {string} */ /** @enum {string} */
export const enumTransistorVariants: any = { export const enumTransistorVariants = {
mirrored: "mirrored", mirrored: "mirrored",
}; };
const overlayMatrices: any = { const overlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]), [defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]),
[enumTransistorVariants.mirrored]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]), [enumTransistorVariants.mirrored]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
}; };
@ -19,7 +19,7 @@ export class MetaTransistorBuilding extends MetaBuilding {
constructor() { constructor() {
super("transistor"); super("transistor");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 38, internalId: 38,
@ -31,37 +31,37 @@ export class MetaTransistorBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#bc3a61"; return "#bc3a61";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates);
} }
/** {} **/ /** {} **/
getLayer(): "wires" { getLayer(): "wires" {
return "wires"; return "wires";
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getAvailableVariants(): any { getAvailableVariants() {
return [defaultBuildingVariant, enumTransistorVariants.mirrored]; return [defaultBuildingVariant, enumTransistorVariants.mirrored];
} }
getSpecialOverlayRenderMatrix(rotation: any, rotationVariant: any, variant: any): any { getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrices[variant][rotation]; return overlayMatrices[variant][rotation];
} }
getRenderPins(): any { getRenderPins() {
// We already have it included // We already have it included
return false; return false;
} }
updateVariants(entity: Entity, rotationVariant: number, variant: any): any { updateVariants(entity: Entity, rotationVariant: number, variant) {
entity.components.WiredPins.slots[1].direction = entity.components.WiredPins.slots[1].direction =
variant === enumTransistorVariants.mirrored ? enumDirection.right : enumDirection.left; variant === enumTransistorVariants.mirrored ? enumDirection.right : enumDirection.left;
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [ slots: [
{ {

View File

@ -7,13 +7,13 @@ import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
const overlayMatrix: any = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]); const overlayMatrix = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]);
export class MetaTrashBuilding extends MetaBuilding { export class MetaTrashBuilding extends MetaBuilding {
constructor() { constructor() {
super("trash"); super("trash");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 20, internalId: 20,
@ -21,29 +21,29 @@ export class MetaTrashBuilding extends MetaBuilding {
}, },
]; ];
} }
getIsRotateable(): any { getIsRotateable() {
return false; return false;
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#ed1d5d"; return "#ed1d5d";
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getSpecialOverlayRenderMatrix(rotation: any): any { getSpecialOverlayRenderMatrix(rotation) {
return overlayMatrix[rotation]; return overlayMatrix[rotation];
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash);
} }
addAchievementReceiver(entity: any): any { addAchievementReceiver(entity) {
if (!entity.root) { if (!entity.root) {
return; return;
} }
const itemProcessor: any = entity.components.ItemProcessor; const itemProcessor = entity.components.ItemProcessor;
const tryTakeItem: any = itemProcessor.tryTakeItem.bind(itemProcessor); const tryTakeItem = itemProcessor.tryTakeItem.bind(itemProcessor);
itemProcessor.tryTakeItem = (): any => { itemProcessor.tryTakeItem = () => {
const taken: any = tryTakeItem(...arguments); const taken = tryTakeItem(...arguments);
if (taken) { if (taken) {
entity.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.trash1000, 1); entity.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.trash1000, 1);
} }
@ -53,7 +53,7 @@ export class MetaTrashBuilding extends MetaBuilding {
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new ItemAcceptorComponent({ entity.addComponent(new ItemAcceptorComponent({
slots: [ slots: [
{ {

View File

@ -11,18 +11,18 @@ import { enumHubGoalRewards } from "../tutorial_goals";
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
import { T } from "../../translations"; import { T } from "../../translations";
/** @enum {string} */ /** @enum {string} */
export const arrayUndergroundRotationVariantToMode: any = [ export const arrayUndergroundRotationVariantToMode = [
enumUndergroundBeltMode.sender, enumUndergroundBeltMode.sender,
enumUndergroundBeltMode.receiver, enumUndergroundBeltMode.receiver,
]; ];
/** @enum {string} */ /** @enum {string} */
export const enumUndergroundBeltVariants: any = { tier2: "tier2" }; export const enumUndergroundBeltVariants = { tier2: "tier2" };
export const enumUndergroundBeltVariantToTier: any = { export const enumUndergroundBeltVariantToTier = {
[defaultBuildingVariant]: 0, [defaultBuildingVariant]: 0,
[enumUndergroundBeltVariants.tier2]: 1, [enumUndergroundBeltVariants.tier2]: 1,
}; };
const colorsByRotationVariant: any = ["#6d9dff", "#71ff9c"]; const colorsByRotationVariant = ["#6d9dff", "#71ff9c"];
const overlayMatrices: any = [ const overlayMatrices = [
// Sender // Sender
generateMatrixRotations([1, 1, 1, 0, 1, 0, 0, 1, 0]), generateMatrixRotations([1, 1, 1, 0, 1, 0, 0, 1, 0]),
// Receiver // Receiver
@ -33,7 +33,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
constructor() { constructor() {
super("underground_belt"); super("underground_belt");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 22, internalId: 22,
@ -57,16 +57,16 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(variant: any, rotationVariant: any): any { getSilhouetteColor(variant, rotationVariant) {
return colorsByRotationVariant[rotationVariant]; return colorsByRotationVariant[rotationVariant];
} }
getFlipOrientationAfterPlacement(): any { getFlipOrientationAfterPlacement() {
return true; return true;
} }
getStayInPlacementMode(): any { getStayInPlacementMode() {
return true; return true;
} }
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): any { getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity) {
return overlayMatrices[rotationVariant][rotation]; return overlayMatrices[rotationVariant][rotation];
} }
/** /**
@ -76,8 +76,8 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
string, string,
string string
]> { ]> {
const rangeTiles: any = globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]]; const rangeTiles = globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]];
const beltSpeed: any = root.hubGoals.getUndergroundBeltBaseSpeed(); const beltSpeed = root.hubGoals.getUndergroundBeltBaseSpeed();
const stats: Array<[ const stats: Array<[
string, string,
string string
@ -93,14 +93,14 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
stats.push([T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]); stats.push([T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]);
return stats; return stats;
} }
getAvailableVariants(root: GameRoot): any { getAvailableVariants(root: GameRoot) {
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) { if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) {
return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2]; return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2];
} }
return super.getAvailableVariants(root); return super.getAvailableVariants(root);
} }
getPreviewSprite(rotationVariant: number, variant: string): any { getPreviewSprite(rotationVariant: number, variant: string) {
let suffix: any = ""; let suffix = "";
if (variant !== defaultBuildingVariant) { if (variant !== defaultBuildingVariant) {
suffix = "-" + variant; suffix = "-" + variant;
} }
@ -113,8 +113,8 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
assertAlways(false, "Invalid rotation variant"); assertAlways(false, "Invalid rotation variant");
} }
} }
getBlueprintSprite(rotationVariant: number, variant: string): any { getBlueprintSprite(rotationVariant: number, variant: string) {
let suffix: any = ""; let suffix = "";
if (variant !== defaultBuildingVariant) { if (variant !== defaultBuildingVariant) {
suffix = "-" + variant; suffix = "-" + variant;
} }
@ -127,16 +127,16 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
assertAlways(false, "Invalid rotation variant"); assertAlways(false, "Invalid rotation variant");
} }
} }
getSprite(rotationVariant: number, variant: string): any { getSprite(rotationVariant: number, variant: string) {
return this.getPreviewSprite(rotationVariant, variant); return this.getPreviewSprite(rotationVariant, variant);
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_tunnel); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_tunnel);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
// Required, since the item processor needs this. // Required, since the item processor needs this.
entity.addComponent(new ItemEjectorComponent({ entity.addComponent(new ItemEjectorComponent({
slots: [], slots: [],
@ -161,18 +161,18 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
rotationVariant: number; rotationVariant: number;
connectedEntities?: Array<Entity>; connectedEntities?: Array<Entity>;
} { } {
const searchDirection: any = enumAngleToDirection[rotation]; const searchDirection = enumAngleToDirection[rotation];
const searchVector: any = enumDirectionToVector[searchDirection]; const searchVector = enumDirectionToVector[searchDirection];
const tier: any = enumUndergroundBeltVariantToTier[variant]; const tier = enumUndergroundBeltVariantToTier[variant];
const targetRotation: any = (rotation + 180) % 360; const targetRotation = (rotation + 180) % 360;
const targetSenderRotation: any = rotation; const targetSenderRotation = rotation;
for (let searchOffset: any = 1; searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier]; ++searchOffset) { for (let searchOffset = 1; searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier]; ++searchOffset) {
tile = tile.addScalars(searchVector.x, searchVector.y); tile = tile.addScalars(searchVector.x, searchVector.y);
const contents: any = root.map.getTileContent(tile, "regular"); const contents = root.map.getTileContent(tile, "regular");
if (contents) { if (contents) {
const undergroundComp: any = contents.components.UndergroundBelt; const undergroundComp = contents.components.UndergroundBelt;
if (undergroundComp && undergroundComp.tier === tier) { if (undergroundComp && undergroundComp.tier === tier) {
const staticComp: any = contents.components.StaticMapEntity; const staticComp = contents.components.StaticMapEntity;
if (staticComp.rotation === targetRotation) { if (staticComp.rotation === targetRotation) {
if (undergroundComp.mode !== enumUndergroundBeltMode.sender) { if (undergroundComp.mode !== enumUndergroundBeltMode.sender) {
// If we encounter an underground receiver on our way which is also faced in our direction, we don't accept that // If we encounter an underground receiver on our way which is also faced in our direction, we don't accept that
@ -205,7 +205,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
rotationVariant: 0, rotationVariant: 0,
}; };
} }
updateVariants(entity: Entity, rotationVariant: number, variant: string): any { updateVariants(entity: Entity, rotationVariant: number, variant: string) {
entity.components.UndergroundBelt.tier = enumUndergroundBeltVariantToTier[variant]; entity.components.UndergroundBelt.tier = enumUndergroundBeltVariantToTier[variant];
switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { switch (arrayUndergroundRotationVariantToMode[rotationVariant]) {
case enumUndergroundBeltMode.sender: { case enumUndergroundBeltMode.sender: {

View File

@ -10,21 +10,21 @@ import { MetaPainterBuilding } from "./painter";
import { MetaRotaterBuilding } from "./rotater"; import { MetaRotaterBuilding } from "./rotater";
import { MetaStackerBuilding } from "./stacker"; import { MetaStackerBuilding } from "./stacker";
/** @enum {string} */ /** @enum {string} */
export const enumVirtualProcessorVariants: any = { export const enumVirtualProcessorVariants = {
rotater: "rotater", rotater: "rotater",
unstacker: "unstacker", unstacker: "unstacker",
stacker: "stacker", stacker: "stacker",
painter: "painter", painter: "painter",
}; };
/** @enum {string} */ /** @enum {string} */
const enumVariantToGate: any = { const enumVariantToGate = {
[defaultBuildingVariant]: enumLogicGateType.cutter, [defaultBuildingVariant]: enumLogicGateType.cutter,
[enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater, [enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater,
[enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker, [enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker,
[enumVirtualProcessorVariants.stacker]: enumLogicGateType.stacker, [enumVirtualProcessorVariants.stacker]: enumLogicGateType.stacker,
[enumVirtualProcessorVariants.painter]: enumLogicGateType.painter, [enumVirtualProcessorVariants.painter]: enumLogicGateType.painter,
}; };
const colors: any = { const colors = {
[defaultBuildingVariant]: new MetaCutterBuilding().getSilhouetteColor(), [defaultBuildingVariant]: new MetaCutterBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.rotater]: new MetaRotaterBuilding().getSilhouetteColor(), [enumVirtualProcessorVariants.rotater]: new MetaRotaterBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.unstacker]: new MetaStackerBuilding().getSilhouetteColor(), [enumVirtualProcessorVariants.unstacker]: new MetaStackerBuilding().getSilhouetteColor(),
@ -36,7 +36,7 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
constructor() { constructor() {
super("virtual_processor"); super("virtual_processor");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 42, internalId: 42,
@ -60,20 +60,20 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(variant: any): any { getSilhouetteColor(variant) {
return colors[variant]; return colors[variant];
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing);
} }
/** {} **/ /** {} **/
getLayer(): "wires" { getLayer(): "wires" {
return "wires"; return "wires";
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getAvailableVariants(): any { getAvailableVariants() {
return [ return [
defaultBuildingVariant, defaultBuildingVariant,
enumVirtualProcessorVariants.rotater, enumVirtualProcessorVariants.rotater,
@ -82,14 +82,14 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
enumVirtualProcessorVariants.unstacker, enumVirtualProcessorVariants.unstacker,
]; ];
} }
getRenderPins(): any { getRenderPins() {
// We already have it included // We already have it included
return false; return false;
} }
updateVariants(entity: Entity, rotationVariant: number, variant: any): any { updateVariants(entity: Entity, rotationVariant: number, variant) {
const gateType: any = enumVariantToGate[variant]; const gateType = enumVariantToGate[variant];
entity.components.LogicGate.type = gateType; entity.components.LogicGate.type = gateType;
const pinComp: any = entity.components.WiredPins; const pinComp = entity.components.WiredPins;
switch (gateType) { switch (gateType) {
case enumLogicGateType.cutter: case enumLogicGateType.cutter:
case enumLogicGateType.unstacker: { case enumLogicGateType.unstacker: {
@ -155,7 +155,7 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WiredPinsComponent({ entity.addComponent(new WiredPinsComponent({
slots: [], slots: [],
})); }));

View File

@ -7,23 +7,23 @@ import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
export const arrayWireRotationVariantToType: any = [ export const arrayWireRotationVariantToType = [
enumWireType.forward, enumWireType.forward,
enumWireType.turn, enumWireType.turn,
enumWireType.split, enumWireType.split,
enumWireType.cross, enumWireType.cross,
]; ];
export const wireOverlayMatrices: any = { export const wireOverlayMatrices = {
[enumWireType.forward]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), [enumWireType.forward]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
[enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]), [enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]),
[enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]), [enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]), [enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
}; };
/** @enum {string} */ /** @enum {string} */
export const wireVariants: any = { export const wireVariants = {
second: "second", second: "second",
}; };
const enumWireVariantToVariant: any = { const enumWireVariantToVariant = {
[defaultBuildingVariant]: enumWireVariant.first, [defaultBuildingVariant]: enumWireVariant.first,
[wireVariants.second]: enumWireVariant.second, [wireVariants.second]: enumWireVariant.second,
}; };
@ -32,7 +32,7 @@ export class MetaWireBuilding extends MetaBuilding {
constructor() { constructor() {
super("wire"); super("wire");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 27, internalId: 27,
@ -76,51 +76,51 @@ export class MetaWireBuilding extends MetaBuilding {
}, },
]; ];
} }
getHasDirectionLockAvailable(): any { getHasDirectionLockAvailable() {
return true; return true;
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#61ef6f"; return "#61ef6f";
} }
getAvailableVariants(): any { getAvailableVariants() {
return [defaultBuildingVariant, wireVariants.second]; return [defaultBuildingVariant, wireVariants.second];
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getStayInPlacementMode(): any { getStayInPlacementMode() {
return true; return true;
} }
getPlacementSound(): any { getPlacementSound() {
return SOUNDS.placeBelt; return SOUNDS.placeBelt;
} }
getRotateAutomaticallyWhilePlacing(): any { getRotateAutomaticallyWhilePlacing() {
return true; return true;
} }
/** {} **/ /** {} **/
getLayer(): "wires" { getLayer(): "wires" {
return "wires"; return "wires";
} }
getSprite(): any { getSprite() {
return null; return null;
} }
getIsReplaceable(): any { getIsReplaceable() {
return true; return true;
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers);
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WireComponent({})); entity.addComponent(new WireComponent({}));
} }
updateVariants(entity: Entity, rotationVariant: number, variant: string): any { updateVariants(entity: Entity, rotationVariant: number, variant: string) {
entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant]; entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant];
entity.components.Wire.variant = enumWireVariantToVariant[variant]; entity.components.Wire.variant = enumWireVariantToVariant[variant];
} }
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): any { getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity) {
return wireOverlayMatrices[entity.components.Wire.type][rotation]; return wireOverlayMatrices[entity.components.Wire.type][rotation];
} }
/** /**
@ -128,7 +128,7 @@ export class MetaWireBuilding extends MetaBuilding {
* {} * {}
*/ */
getPreviewSprite(rotationVariant: number, variant: string): import("../../core/draw_utils").AtlasSprite { getPreviewSprite(rotationVariant: number, variant: string): import("../../core/draw_utils").AtlasSprite {
const wireVariant: any = enumWireVariantToVariant[variant]; const wireVariant = enumWireVariantToVariant[variant];
switch (arrayWireRotationVariantToType[rotationVariant]) { switch (arrayWireRotationVariantToType[rotationVariant]) {
case enumWireType.forward: { case enumWireType.forward: {
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_forward.png"); return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_forward.png");
@ -147,7 +147,7 @@ export class MetaWireBuilding extends MetaBuilding {
} }
} }
} }
getBlueprintSprite(rotationVariant: any, variant: any): any { getBlueprintSprite(rotationVariant, variant) {
return this.getPreviewSprite(rotationVariant, variant); return this.getPreviewSprite(rotationVariant, variant);
} }
/** /**
@ -165,19 +165,19 @@ export class MetaWireBuilding extends MetaBuilding {
rotationVariant: number; rotationVariant: number;
connectedEntities?: Array<Entity>; connectedEntities?: Array<Entity>;
} { } {
const wireVariant: any = enumWireVariantToVariant[variant]; const wireVariant = enumWireVariantToVariant[variant];
const connections: any = { const connections = {
top: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.top }), top: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.top }),
right: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.right }), right: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.right }),
bottom: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.bottom }), bottom: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.bottom }),
left: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.left }), left: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.left }),
}; };
let flag: any = 0; let flag = 0;
flag |= connections.top ? 0x1000 : 0; flag |= connections.top ? 0x1000 : 0;
flag |= connections.right ? 0x100 : 0; flag |= connections.right ? 0x100 : 0;
flag |= connections.bottom ? 0x10 : 0; flag |= connections.bottom ? 0x10 : 0;
flag |= connections.left ? 0x1 : 0; flag |= connections.left ? 0x1 : 0;
let targetType: any = enumWireType.forward; let targetType = enumWireType.forward;
// First, reset rotation // First, reset rotation
rotation = 0; rotation = 0;
switch (flag) { switch (flag) {

View File

@ -5,13 +5,13 @@ import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
const wireTunnelOverlayMatrix: any = generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]); const wireTunnelOverlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]);
export class MetaWireTunnelBuilding extends MetaBuilding { export class MetaWireTunnelBuilding extends MetaBuilding {
constructor() { constructor() {
super("wire_tunnel"); super("wire_tunnel");
} }
static getAllVariantCombinations(): any { static getAllVariantCombinations() {
return [ return [
{ {
internalId: 39, internalId: 39,
@ -19,19 +19,19 @@ export class MetaWireTunnelBuilding extends MetaBuilding {
}, },
]; ];
} }
getSilhouetteColor(): any { getSilhouetteColor() {
return "#777a86"; return "#777a86";
} }
getIsUnlocked(root: GameRoot): any { getIsUnlocked(root: GameRoot) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers); return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers);
} }
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): any { getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity) {
return wireTunnelOverlayMatrix[rotation]; return wireTunnelOverlayMatrix[rotation];
} }
getIsRotateable(): any { getIsRotateable() {
return false; return false;
} }
getDimensions(): any { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
/** {} **/ /** {} **/
@ -41,7 +41,7 @@ export class MetaWireTunnelBuilding extends MetaBuilding {
/** /**
* Creates the entity at the given location * Creates the entity at the given location
*/ */
setupEntityComponents(entity: Entity): any { setupEntityComponents(entity: Entity) {
entity.addComponent(new WireTunnelComponent()); entity.addComponent(new WireTunnelComponent());
} }
} }

View File

@ -8,19 +8,19 @@ import { mixVector, Vector } from "../core/vector";
import { BasicSerializableObject, types } from "../savegame/serialization"; import { BasicSerializableObject, types } from "../savegame/serialization";
import { KEYMAPPINGS } from "./key_action_mapper"; import { KEYMAPPINGS } from "./key_action_mapper";
import { GameRoot } from "./root"; import { GameRoot } from "./root";
const logger: any = createLogger("camera"); const logger = createLogger("camera");
export const USER_INTERACT_MOVE: any = "move"; export const USER_INTERACT_MOVE = "move";
export const USER_INTERACT_ZOOM: any = "zoom"; export const USER_INTERACT_ZOOM = "zoom";
export const USER_INTERACT_TOUCHEND: any = "touchend"; export const USER_INTERACT_TOUCHEND = "touchend";
const velocitySmoothing: any = 0.5; const velocitySmoothing = 0.5;
const velocityFade: any = 0.98; const velocityFade = 0.98;
const velocityStrength: any = 0.4; const velocityStrength = 0.4;
const velocityMax: any = 20; const velocityMax = 20;
const ticksBeforeErasingVelocity: any = 10; const ticksBeforeErasingVelocity = 10;
/** /**
* @enum {string} * @enum {string}
*/ */
export const enumMouseButton: any = { export const enumMouseButton = {
left: "left", left: "left",
middle: "middle", middle: "middle",
right: "right", right: "right",
@ -63,7 +63,7 @@ export class Camera extends BasicSerializableObject {
this.clampZoomLevel(); this.clampZoomLevel();
this.bindKeys(); this.bindKeys();
if (G_IS_DEV) { if (G_IS_DEV) {
window.addEventListener("keydown", (ev: any): any => { window.addEventListener("keydown", ev => {
if (ev.key === "i") { if (ev.key === "i") {
this.zoomLevel = 3; this.zoomLevel = 3;
} }
@ -71,17 +71,17 @@ export class Camera extends BasicSerializableObject {
} }
} }
// Serialization // Serialization
static getId(): any { static getId() {
return "Camera"; return "Camera";
} }
static getSchema(): any { static getSchema() {
return { return {
zoomLevel: types.float, zoomLevel: types.float,
center: types.vector, center: types.vector,
}; };
} }
deserialize(data: any): any { deserialize(data) {
const errorCode: any = super.deserialize(data); const errorCode = super.deserialize(data);
if (errorCode) { if (errorCode) {
return errorCode; return errorCode;
} }
@ -89,55 +89,55 @@ export class Camera extends BasicSerializableObject {
this.clampZoomLevel(); this.clampZoomLevel();
} }
// Simple getters & setters // Simple getters & setters
addScreenShake(amount: any): any { addScreenShake(amount) {
const currentShakeAmount: any = this.currentShake.length(); const currentShakeAmount = this.currentShake.length();
const scale: any = 1 / (1 + 3 * currentShakeAmount); const scale = 1 / (1 + 3 * currentShakeAmount);
this.currentShake.x = this.currentShake.x + 2 * (Math.random() - 0.5) * scale * amount; this.currentShake.x = this.currentShake.x + 2 * (Math.random() - 0.5) * scale * amount;
this.currentShake.y = this.currentShake.y + 2 * (Math.random() - 0.5) * scale * amount; this.currentShake.y = this.currentShake.y + 2 * (Math.random() - 0.5) * scale * amount;
} }
/** /**
* Sets a point in world space to focus on * Sets a point in world space to focus on
*/ */
setDesiredCenter(center: Vector): any { setDesiredCenter(center: Vector) {
this.desiredCenter = center.copy(); this.desiredCenter = center.copy();
this.currentlyMoving = false; this.currentlyMoving = false;
} }
/** /**
* Sets a desired zoom level * Sets a desired zoom level
*/ */
setDesiredZoom(zoom: number): any { setDesiredZoom(zoom: number) {
this.desiredZoom = zoom; this.desiredZoom = zoom;
} }
/** /**
* Returns if this camera is currently moving by a non-user interaction * Returns if this camera is currently moving by a non-user interaction
*/ */
isCurrentlyMovingToDesiredCenter(): any { isCurrentlyMovingToDesiredCenter() {
return this.desiredCenter !== null; return this.desiredCenter !== null;
} }
/** /**
* Sets the camera pan, every frame the camera will move by this amount * Sets the camera pan, every frame the camera will move by this amount
*/ */
setPan(pan: Vector): any { setPan(pan: Vector) {
this.desiredPan = pan.copy(); this.desiredPan = pan.copy();
} }
/** /**
* Finds a good initial zoom level * Finds a good initial zoom level
*/ */
findInitialZoom(): any { findInitialZoom() {
let desiredWorldSpaceWidth: any = 18 * globalConfig.tileSize; let desiredWorldSpaceWidth = 18 * globalConfig.tileSize;
if (window.innerWidth < 1000) { if (window.innerWidth < 1000) {
desiredWorldSpaceWidth = 12 * globalConfig.tileSize; desiredWorldSpaceWidth = 12 * globalConfig.tileSize;
} }
const zoomLevelX: any = this.root.gameWidth / desiredWorldSpaceWidth; const zoomLevelX = this.root.gameWidth / desiredWorldSpaceWidth;
const zoomLevelY: any = this.root.gameHeight / desiredWorldSpaceWidth; const zoomLevelY = this.root.gameHeight / desiredWorldSpaceWidth;
const finalLevel: any = Math.min(zoomLevelX, zoomLevelY); const finalLevel = Math.min(zoomLevelX, zoomLevelY);
assert(Number.isFinite(finalLevel) && finalLevel > 0, "Invalid zoom level computed for initial zoom: " + finalLevel); assert(Number.isFinite(finalLevel) && finalLevel > 0, "Invalid zoom level computed for initial zoom: " + finalLevel);
return finalLevel; return finalLevel;
} }
/** /**
* Clears all animations * Clears all animations
*/ */
clearAnimations(): any { clearAnimations() {
this.touchPostMoveVelocity.x = 0; this.touchPostMoveVelocity.x = 0;
this.touchPostMoveVelocity.y = 0; this.touchPostMoveVelocity.y = 0;
this.desiredCenter = null; this.desiredCenter = null;
@ -178,7 +178,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Cancels all interactions, that is user interaction and non user interaction * Cancels all interactions, that is user interaction and non user interaction
*/ */
cancelAllInteractions(): any { cancelAllInteractions() {
this.touchPostMoveVelocity = new Vector(0, 0); this.touchPostMoveVelocity = new Vector(0, 0);
this.desiredCenter = null; this.desiredCenter = null;
this.currentlyMoving = false; this.currentlyMoving = false;
@ -188,37 +188,37 @@ export class Camera extends BasicSerializableObject {
/** /**
* Returns effective viewport width * Returns effective viewport width
*/ */
getViewportWidth(): any { getViewportWidth() {
return this.root.gameWidth / this.zoomLevel; return this.root.gameWidth / this.zoomLevel;
} }
/** /**
* Returns effective viewport height * Returns effective viewport height
*/ */
getViewportHeight(): any { getViewportHeight() {
return this.root.gameHeight / this.zoomLevel; return this.root.gameHeight / this.zoomLevel;
} }
/** /**
* Returns effective world space viewport left * Returns effective world space viewport left
*/ */
getViewportLeft(): any { getViewportLeft() {
return this.center.x - this.getViewportWidth() / 2 + (this.currentShake.x * 10) / this.zoomLevel; return this.center.x - this.getViewportWidth() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
} }
/** /**
* Returns effective world space viewport right * Returns effective world space viewport right
*/ */
getViewportRight(): any { getViewportRight() {
return this.center.x + this.getViewportWidth() / 2 + (this.currentShake.x * 10) / this.zoomLevel; return this.center.x + this.getViewportWidth() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
} }
/** /**
* Returns effective world space viewport top * Returns effective world space viewport top
*/ */
getViewportTop(): any { getViewportTop() {
return this.center.y - this.getViewportHeight() / 2 + (this.currentShake.x * 10) / this.zoomLevel; return this.center.y - this.getViewportHeight() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
} }
/** /**
* Returns effective world space viewport bottom * Returns effective world space viewport bottom
*/ */
getViewportBottom(): any { getViewportBottom() {
return this.center.y + this.getViewportHeight() / 2 + (this.currentShake.x * 10) / this.zoomLevel; return this.center.y + this.getViewportHeight() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
} }
/** /**
@ -228,13 +228,13 @@ export class Camera extends BasicSerializableObject {
getVisibleRect(): Rectangle { getVisibleRect(): Rectangle {
return Rectangle.fromTRBL(Math.floor(this.getViewportTop()), Math.ceil(this.getViewportRight()), Math.ceil(this.getViewportBottom()), Math.floor(this.getViewportLeft())); return Rectangle.fromTRBL(Math.floor(this.getViewportTop()), Math.ceil(this.getViewportRight()), Math.ceil(this.getViewportBottom()), Math.floor(this.getViewportLeft()));
} }
getIsMapOverlayActive(): any { getIsMapOverlayActive() {
return this.zoomLevel < globalConfig.mapChunkOverviewMinZoom; return this.zoomLevel < globalConfig.mapChunkOverviewMinZoom;
} }
/** /**
* Attaches all event listeners * Attaches all event listeners
*/ */
internalInitEvents(): any { internalInitEvents() {
this.eventListenerTouchStart = this.onTouchStart.bind(this); this.eventListenerTouchStart = this.onTouchStart.bind(this);
this.eventListenerTouchEnd = this.onTouchEnd.bind(this); this.eventListenerTouchEnd = this.onTouchEnd.bind(this);
this.eventListenerTouchMove = this.onTouchMove.bind(this); this.eventListenerTouchMove = this.onTouchMove.bind(this);
@ -257,7 +257,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Cleans up all event listeners * Cleans up all event listeners
*/ */
cleanup(): any { cleanup() {
if (SUPPORT_TOUCH) { if (SUPPORT_TOUCH) {
this.root.canvas.removeEventListener("touchstart", this.eventListenerTouchStart); this.root.canvas.removeEventListener("touchstart", this.eventListenerTouchStart);
this.root.canvas.removeEventListener("touchend", this.eventListenerTouchEnd); this.root.canvas.removeEventListener("touchend", this.eventListenerTouchEnd);
@ -273,21 +273,21 @@ export class Camera extends BasicSerializableObject {
/** /**
* Binds the arrow keys * Binds the arrow keys
*/ */
bindKeys(): any { bindKeys() {
const mapper: any = this.root.keyMapper; const mapper = this.root.keyMapper;
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).add((): any => (this.keyboardForce.y = -1)); mapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).add(() => (this.keyboardForce.y = -1));
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveDown).add((): any => (this.keyboardForce.y = 1)); mapper.getBinding(KEYMAPPINGS.navigation.mapMoveDown).add(() => (this.keyboardForce.y = 1));
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).add((): any => (this.keyboardForce.x = 1)); mapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).add(() => (this.keyboardForce.x = 1));
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveLeft).add((): any => (this.keyboardForce.x = -1)); mapper.getBinding(KEYMAPPINGS.navigation.mapMoveLeft).add(() => (this.keyboardForce.x = -1));
mapper mapper
.getBinding(KEYMAPPINGS.navigation.mapZoomIn) .getBinding(KEYMAPPINGS.navigation.mapZoomIn)
.add((): any => (this.desiredZoom = this.zoomLevel * 1.2)); .add(() => (this.desiredZoom = this.zoomLevel * 1.2));
mapper mapper
.getBinding(KEYMAPPINGS.navigation.mapZoomOut) .getBinding(KEYMAPPINGS.navigation.mapZoomOut)
.add((): any => (this.desiredZoom = this.zoomLevel / 1.2)); .add(() => (this.desiredZoom = this.zoomLevel / 1.2));
mapper.getBinding(KEYMAPPINGS.navigation.centerMap).add((): any => this.centerOnMap()); mapper.getBinding(KEYMAPPINGS.navigation.centerMap).add(() => this.centerOnMap());
} }
centerOnMap(): any { centerOnMap() {
this.desiredCenter = new Vector(0, 0); this.desiredCenter = new Vector(0, 0);
} }
/** /**
@ -295,7 +295,7 @@ export class Camera extends BasicSerializableObject {
* {} world space * {} world space
*/ */
screenToWorld(screen: Vector): Vector { screenToWorld(screen: Vector): Vector {
const centerSpace: any = screen.subScalars(this.root.gameWidth / 2, this.root.gameHeight / 2); const centerSpace = screen.subScalars(this.root.gameWidth / 2, this.root.gameHeight / 2);
return centerSpace.divideScalar(this.zoomLevel).add(this.center); return centerSpace.divideScalar(this.zoomLevel).add(this.center);
} }
/** /**
@ -303,7 +303,7 @@ export class Camera extends BasicSerializableObject {
* {} screen space * {} screen space
*/ */
worldToScreen(world: Vector): Vector { worldToScreen(world: Vector): Vector {
const screenSpace: any = world.sub(this.center).multiplyScalar(this.zoomLevel); const screenSpace = world.sub(this.center).multiplyScalar(this.zoomLevel);
return screenSpace.addScalars(this.root.gameWidth / 2, this.root.gameHeight / 2); return screenSpace.addScalars(this.root.gameWidth / 2, this.root.gameHeight / 2);
} }
/** /**
@ -311,13 +311,13 @@ export class Camera extends BasicSerializableObject {
* {} true if its on screen * {} true if its on screen
*/ */
isWorldPointOnScreen(point: Vector): boolean { isWorldPointOnScreen(point: Vector): boolean {
const rect: any = this.getVisibleRect(); const rect = this.getVisibleRect();
return rect.containsPoint(point.x, point.y); return rect.containsPoint(point.x, point.y);
} }
getMaximumZoom(): any { getMaximumZoom() {
return this.root.gameMode.getMaximumZoom(); return this.root.gameMode.getMaximumZoom();
} }
getMinimumZoom(): any { getMinimumZoom() {
return this.root.gameMode.getMinimumZoom(); return this.root.gameMode.getMinimumZoom();
} }
/** /**
@ -339,7 +339,7 @@ export class Camera extends BasicSerializableObject {
* Checks if the mouse event is too close after a touch event and thus * Checks if the mouse event is too close after a touch event and thus
* should get ignored * should get ignored
*/ */
checkPreventDoubleMouse(): any { checkPreventDoubleMouse() {
if (performance.now() - clickDetectorGlobals.lastTouchTime < 1000.0) { if (performance.now() - clickDetectorGlobals.lastTouchTime < 1000.0) {
return false; return false;
} }
@ -348,7 +348,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Mousedown handler * Mousedown handler
*/ */
onMouseDown(event: MouseEvent): any { onMouseDown(event: MouseEvent) {
if (event.cancelable) { if (event.cancelable) {
event.preventDefault(); event.preventDefault();
// event.stopPropagation(); // event.stopPropagation();
@ -371,7 +371,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Mousemove handler * Mousemove handler
*/ */
onMouseMove(event: MouseEvent): any { onMouseMove(event: MouseEvent) {
if (event.cancelable) { if (event.cancelable) {
event.preventDefault(); event.preventDefault();
// event.stopPropagation(); // event.stopPropagation();
@ -390,7 +390,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Mouseup handler * Mouseup handler
*/ */
onMouseUp(event: MouseEvent=): any { onMouseUp(event: MouseEvent=) {
if (event) { if (event) {
if (event.cancelable) { if (event.cancelable) {
event.preventDefault(); event.preventDefault();
@ -406,27 +406,27 @@ export class Camera extends BasicSerializableObject {
/** /**
* Mousewheel event * Mousewheel event
*/ */
onMouseWheel(event: WheelEvent): any { onMouseWheel(event: WheelEvent) {
if (event.cancelable) { if (event.cancelable) {
event.preventDefault(); event.preventDefault();
// event.stopPropagation(); // event.stopPropagation();
} }
const prevZoom: any = this.zoomLevel; const prevZoom = this.zoomLevel;
const scale: any = 1 + 0.15 * this.root.app.settings.getScrollWheelSensitivity(); const scale = 1 + 0.15 * this.root.app.settings.getScrollWheelSensitivity();
assert(Number.isFinite(scale), "Got invalid scale in mouse wheel event: " + event.deltaY); assert(Number.isFinite(scale), "Got invalid scale in mouse wheel event: " + event.deltaY);
assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *before* wheel: " + this.zoomLevel); assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *before* wheel: " + this.zoomLevel);
this.zoomLevel *= event.deltaY < 0 ? scale : 1 / scale; this.zoomLevel *= event.deltaY < 0 ? scale : 1 / scale;
assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *after* wheel: " + this.zoomLevel); assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *after* wheel: " + this.zoomLevel);
this.clampZoomLevel(); this.clampZoomLevel();
this.desiredZoom = null; this.desiredZoom = null;
let mousePosition: any = this.root.app.mousePosition; let mousePosition = this.root.app.mousePosition;
if (!this.root.app.settings.getAllSettings().zoomToCursor) { if (!this.root.app.settings.getAllSettings().zoomToCursor) {
mousePosition = new Vector(this.root.gameWidth / 2, this.root.gameHeight / 2); mousePosition = new Vector(this.root.gameWidth / 2, this.root.gameHeight / 2);
} }
if (mousePosition) { if (mousePosition) {
const worldPos: any = this.root.camera.screenToWorld(mousePosition); const worldPos = this.root.camera.screenToWorld(mousePosition);
const worldDelta: any = worldPos.sub(this.center); const worldDelta = worldPos.sub(this.center);
const actualDelta: any = this.zoomLevel / prevZoom - 1; const actualDelta = this.zoomLevel / prevZoom - 1;
this.center = this.center.add(worldDelta.multiplyScalar(actualDelta)); this.center = this.center.add(worldDelta.multiplyScalar(actualDelta));
this.desiredCenter = null; this.desiredCenter = null;
} }
@ -435,7 +435,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Touch start handler * Touch start handler
*/ */
onTouchStart(event: TouchEvent): any { onTouchStart(event: TouchEvent) {
if (event.cancelable) { if (event.cancelable) {
event.preventDefault(); event.preventDefault();
// event.stopPropagation(); // event.stopPropagation();
@ -443,7 +443,7 @@ export class Camera extends BasicSerializableObject {
clickDetectorGlobals.lastTouchTime = performance.now(); clickDetectorGlobals.lastTouchTime = performance.now();
this.touchPostMoveVelocity = new Vector(0, 0); this.touchPostMoveVelocity = new Vector(0, 0);
if (event.touches.length === 1) { if (event.touches.length === 1) {
const touch: any = event.touches[0]; const touch = event.touches[0];
this.combinedSingleTouchStartHandler(touch.clientX, touch.clientY); this.combinedSingleTouchStartHandler(touch.clientX, touch.clientY);
} }
else if (event.touches.length === 2) { else if (event.touches.length === 2) {
@ -451,8 +451,8 @@ export class Camera extends BasicSerializableObject {
// // Something prevented pinching // // Something prevented pinching
// return false; // return false;
// } // }
const touch1: any = event.touches[0]; const touch1 = event.touches[0];
const touch2: any = event.touches[1]; const touch2 = event.touches[1];
this.currentlyMoving = false; this.currentlyMoving = false;
this.currentlyPinching = true; this.currentlyPinching = true;
this.lastPinchPositions = [ this.lastPinchPositions = [
@ -465,35 +465,35 @@ export class Camera extends BasicSerializableObject {
/** /**
* Touch move handler * Touch move handler
*/ */
onTouchMove(event: TouchEvent): any { onTouchMove(event: TouchEvent) {
if (event.cancelable) { if (event.cancelable) {
event.preventDefault(); event.preventDefault();
// event.stopPropagation(); // event.stopPropagation();
} }
clickDetectorGlobals.lastTouchTime = performance.now(); clickDetectorGlobals.lastTouchTime = performance.now();
if (event.touches.length === 1) { if (event.touches.length === 1) {
const touch: any = event.touches[0]; const touch = event.touches[0];
this.combinedSingleTouchMoveHandler(touch.clientX, touch.clientY); this.combinedSingleTouchMoveHandler(touch.clientX, touch.clientY);
} }
else if (event.touches.length === 2) { else if (event.touches.length === 2) {
if (this.currentlyPinching) { if (this.currentlyPinching) {
const touch1: any = event.touches[0]; const touch1 = event.touches[0];
const touch2: any = event.touches[1]; const touch2 = event.touches[1];
const newPinchPositions: any = [ const newPinchPositions = [
new Vector(touch1.clientX, touch1.clientY), new Vector(touch1.clientX, touch1.clientY),
new Vector(touch2.clientX, touch2.clientY), new Vector(touch2.clientX, touch2.clientY),
]; ];
// Get distance of taps last time and now // Get distance of taps last time and now
const lastDistance: any = this.lastPinchPositions[0].distance(this.lastPinchPositions[1]); const lastDistance = this.lastPinchPositions[0].distance(this.lastPinchPositions[1]);
const thisDistance: any = newPinchPositions[0].distance(newPinchPositions[1]); const thisDistance = newPinchPositions[0].distance(newPinchPositions[1]);
// IMPORTANT to do math max here to avoid NaN and causing an invalid zoom level // IMPORTANT to do math max here to avoid NaN and causing an invalid zoom level
const difference: any = thisDistance / Math.max(0.001, lastDistance); const difference = thisDistance / Math.max(0.001, lastDistance);
// Find old center of zoom // Find old center of zoom
let oldCenter: any = this.lastPinchPositions[0].centerPoint(this.lastPinchPositions[1]); let oldCenter = this.lastPinchPositions[0].centerPoint(this.lastPinchPositions[1]);
// Find new center of zoom // Find new center of zoom
let center: any = newPinchPositions[0].centerPoint(newPinchPositions[1]); let center = newPinchPositions[0].centerPoint(newPinchPositions[1]);
// Compute movement // Compute movement
let movement: any = oldCenter.sub(center); let movement = oldCenter.sub(center);
this.center.x += movement.x / this.zoomLevel; this.center.x += movement.x / this.zoomLevel;
this.center.y += movement.y / this.zoomLevel; this.center.y += movement.y / this.zoomLevel;
// Compute zoom // Compute zoom
@ -508,7 +508,7 @@ export class Camera extends BasicSerializableObject {
")"); ")");
this.zoomLevel *= difference; this.zoomLevel *= difference;
// Stick to pivot point // Stick to pivot point
const correcture: any = center.multiplyScalar(difference - 1).divideScalar(this.zoomLevel); const correcture = center.multiplyScalar(difference - 1).divideScalar(this.zoomLevel);
this.center = this.center.add(correcture); this.center = this.center.add(correcture);
this.lastPinchPositions = newPinchPositions; this.lastPinchPositions = newPinchPositions;
this.userInteraction.dispatch(USER_INTERACT_MOVE); this.userInteraction.dispatch(USER_INTERACT_MOVE);
@ -525,7 +525,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Touch end and cancel handler * Touch end and cancel handler
*/ */
onTouchEnd(event: TouchEvent=): any { onTouchEnd(event: TouchEvent=) {
if (event) { if (event) {
if (event.cancelable) { if (event.cancelable) {
event.preventDefault(); event.preventDefault();
@ -536,15 +536,15 @@ export class Camera extends BasicSerializableObject {
if (event.changedTouches.length === 0) { if (event.changedTouches.length === 0) {
logger.warn("Touch end without changed touches"); logger.warn("Touch end without changed touches");
} }
const touch: any = event.changedTouches[0]; const touch = event.changedTouches[0];
this.combinedSingleTouchStopHandler(touch.clientX, touch.clientY); this.combinedSingleTouchStopHandler(touch.clientX, touch.clientY);
return false; return false;
} }
/** /**
* Internal touch start handler * Internal touch start handler
*/ */
combinedSingleTouchStartHandler(x: number, y: number): any { combinedSingleTouchStartHandler(x: number, y: number) {
const pos: any = new Vector(x, y); const pos = new Vector(x, y);
if (this.downPreHandler.dispatch(pos, enumMouseButton.left) === STOP_PROPAGATION) { if (this.downPreHandler.dispatch(pos, enumMouseButton.left) === STOP_PROPAGATION) {
// Somebody else captured it // Somebody else captured it
return; return;
@ -559,8 +559,8 @@ export class Camera extends BasicSerializableObject {
/** /**
* Internal touch move handler * Internal touch move handler
*/ */
combinedSingleTouchMoveHandler(x: number, y: number): any { combinedSingleTouchMoveHandler(x: number, y: number) {
const pos: any = new Vector(x, y); const pos = new Vector(x, y);
if (this.movePreHandler.dispatch(pos) === STOP_PROPAGATION) { if (this.movePreHandler.dispatch(pos) === STOP_PROPAGATION) {
// Somebody else captured it // Somebody else captured it
return; return;
@ -568,7 +568,7 @@ export class Camera extends BasicSerializableObject {
if (!this.currentlyMoving) { if (!this.currentlyMoving) {
return false; return false;
} }
let delta: any = this.lastMovingPosition.sub(pos).divideScalar(this.zoomLevel); let delta = this.lastMovingPosition.sub(pos).divideScalar(this.zoomLevel);
if (G_IS_DEV && globalConfig.debug.testCulling) { if (G_IS_DEV && globalConfig.debug.testCulling) {
// When testing culling, we see everything from the same distance // When testing culling, we see everything from the same distance
delta = delta.multiplyScalar(this.zoomLevel * -2); delta = delta.multiplyScalar(this.zoomLevel * -2);
@ -588,7 +588,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Internal touch stop handler * Internal touch stop handler
*/ */
combinedSingleTouchStopHandler(x: any, y: any): any { combinedSingleTouchStopHandler(x, y) {
if (this.currentlyMoving || this.currentlyPinching) { if (this.currentlyMoving || this.currentlyPinching) {
this.currentlyMoving = false; this.currentlyMoving = false;
this.currentlyPinching = false; this.currentlyPinching = false;
@ -604,7 +604,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Clamps the camera zoom level within the allowed range * Clamps the camera zoom level within the allowed range
*/ */
clampZoomLevel(): any { clampZoomLevel() {
if (G_IS_DEV && globalConfig.debug.disableZoomLimits) { if (G_IS_DEV && globalConfig.debug.disableZoomLimits) {
return; return;
} }
@ -618,25 +618,25 @@ export class Camera extends BasicSerializableObject {
/** /**
* Clamps the center within set boundaries * Clamps the center within set boundaries
*/ */
clampToBounds(): any { clampToBounds() {
const bounds: any = this.root.gameMode.getCameraBounds(); const bounds = this.root.gameMode.getCameraBounds();
if (!bounds) { if (!bounds) {
return; return;
} }
const tileScaleBounds: any = this.root.gameMode.getCameraBounds().allScaled(globalConfig.tileSize); const tileScaleBounds = this.root.gameMode.getCameraBounds().allScaled(globalConfig.tileSize);
this.center.x = clamp(this.center.x, tileScaleBounds.x, tileScaleBounds.x + tileScaleBounds.w); this.center.x = clamp(this.center.x, tileScaleBounds.x, tileScaleBounds.x + tileScaleBounds.w);
this.center.y = clamp(this.center.y, tileScaleBounds.y, tileScaleBounds.y + tileScaleBounds.h); this.center.y = clamp(this.center.y, tileScaleBounds.y, tileScaleBounds.y + tileScaleBounds.h);
} }
/** /**
* Updates the camera * Updates the camera
*/ */
update(dt: number): any { update(dt: number) {
dt = Math.min(dt, 33); dt = Math.min(dt, 33);
this.cameraUpdateTimeBucket += dt; this.cameraUpdateTimeBucket += dt;
// Simulate movement of N FPS // Simulate movement of N FPS
const updatesPerFrame: any = 4; const updatesPerFrame = 4;
const physicsStepSizeMs: any = 1000.0 / (60.0 * updatesPerFrame); const physicsStepSizeMs = 1000.0 / (60.0 * updatesPerFrame);
let now: any = this.root.time.systemNow() - 3 * physicsStepSizeMs; let now = this.root.time.systemNow() - 3 * physicsStepSizeMs;
while (this.cameraUpdateTimeBucket > physicsStepSizeMs) { while (this.cameraUpdateTimeBucket > physicsStepSizeMs) {
now += physicsStepSizeMs; now += physicsStepSizeMs;
this.cameraUpdateTimeBucket -= physicsStepSizeMs; this.cameraUpdateTimeBucket -= physicsStepSizeMs;
@ -652,13 +652,13 @@ export class Camera extends BasicSerializableObject {
/** /**
* Prepares a context to transform it * Prepares a context to transform it
*/ */
transform(context: CanvasRenderingContext2D): any { transform(context: CanvasRenderingContext2D) {
if (G_IS_DEV && globalConfig.debug.testCulling) { if (G_IS_DEV && globalConfig.debug.testCulling) {
context.transform(1, 0, 0, 1, 100, 100); context.transform(1, 0, 0, 1, 100, 100);
return; return;
} }
this.clampZoomLevel(); this.clampZoomLevel();
const zoom: any = this.zoomLevel; const zoom = this.zoomLevel;
context.transform( context.transform(
// Scale, skew, rotate // Scale, skew, rotate
zoom, 0, 0, zoom, zoom, 0, 0, zoom,
@ -668,14 +668,14 @@ export class Camera extends BasicSerializableObject {
/** /**
* Internal shake handler * Internal shake handler
*/ */
internalUpdateShake(now: number, dt: number): any { internalUpdateShake(now: number, dt: number) {
this.currentShake = this.currentShake.multiplyScalar(0.92); this.currentShake = this.currentShake.multiplyScalar(0.92);
} }
/** /**
* Internal pan handler * Internal pan handler
*/ */
internalUpdatePanning(now: number, dt: number): any { internalUpdatePanning(now: number, dt: number) {
const baseStrength: any = velocityStrength * this.root.app.platformWrapper.getTouchPanStrength(); const baseStrength = velocityStrength * this.root.app.platformWrapper.getTouchPanStrength();
this.touchPostMoveVelocity = this.touchPostMoveVelocity.multiplyScalar(velocityFade); this.touchPostMoveVelocity = this.touchPostMoveVelocity.multiplyScalar(velocityFade);
// Check if the camera is being dragged but standing still: if not, zero out `touchPostMoveVelocity`. // Check if the camera is being dragged but standing still: if not, zero out `touchPostMoveVelocity`.
if (this.currentlyMoving && this.desiredCenter === null) { if (this.currentlyMoving && this.desiredCenter === null) {
@ -694,7 +694,7 @@ export class Camera extends BasicSerializableObject {
} }
// Check influence of past points // Check influence of past points
if (!this.currentlyMoving && !this.currentlyPinching) { if (!this.currentlyMoving && !this.currentlyPinching) {
const len: any = this.touchPostMoveVelocity.length(); const len = this.touchPostMoveVelocity.length();
if (len >= velocityMax) { if (len >= velocityMax) {
this.touchPostMoveVelocity.x = (this.touchPostMoveVelocity.x * velocityMax) / len; this.touchPostMoveVelocity.x = (this.touchPostMoveVelocity.x * velocityMax) / len;
this.touchPostMoveVelocity.y = (this.touchPostMoveVelocity.y * velocityMax) / len; this.touchPostMoveVelocity.y = (this.touchPostMoveVelocity.y * velocityMax) / len;
@ -709,7 +709,7 @@ export class Camera extends BasicSerializableObject {
/** /**
* Internal screen panning handler * Internal screen panning handler
*/ */
internalUpdateMousePanning(now: number, dt: number): any { internalUpdateMousePanning(now: number, dt: number) {
if (!this.root.app.focused) { if (!this.root.app.focused) {
return; return;
} }
@ -717,7 +717,7 @@ export class Camera extends BasicSerializableObject {
// Not enabled // Not enabled
return; return;
} }
const mousePos: any = this.root.app.mousePosition; const mousePos = this.root.app.mousePosition;
if (!mousePos) { if (!mousePos) {
return; return;
} }
@ -735,8 +735,8 @@ export class Camera extends BasicSerializableObject {
// Out of screen // Out of screen
return; return;
} }
const panAreaPixels: any = 2; const panAreaPixels = 2;
const panVelocity: any = new Vector(); const panVelocity = new Vector();
if (mousePos.x < panAreaPixels) { if (mousePos.x < panAreaPixels) {
panVelocity.x -= 1; panVelocity.x -= 1;
} }
@ -755,11 +755,11 @@ export class Camera extends BasicSerializableObject {
/** /**
* Updates the non user interaction zooming * Updates the non user interaction zooming
*/ */
internalUpdateZooming(now: number, dt: number): any { internalUpdateZooming(now: number, dt: number) {
if (!this.currentlyPinching && this.desiredZoom !== null) { if (!this.currentlyPinching && this.desiredZoom !== null) {
const diff: any = this.zoomLevel - this.desiredZoom; const diff = this.zoomLevel - this.desiredZoom;
if (Math.abs(diff) > 0.0001) { if (Math.abs(diff) > 0.0001) {
let fade: any = 0.94; let fade = 0.94;
if (diff > 0) { if (diff > 0) {
// Zoom out faster than in // Zoom out faster than in
fade = 0.9; fade = 0.9;
@ -778,13 +778,13 @@ export class Camera extends BasicSerializableObject {
/** /**
* Updates the non user interaction centering * Updates the non user interaction centering
*/ */
internalUpdateCentering(now: number, dt: number): any { internalUpdateCentering(now: number, dt: number) {
if (!this.currentlyMoving && this.desiredCenter !== null) { if (!this.currentlyMoving && this.desiredCenter !== null) {
const diff: any = this.center.direction(this.desiredCenter); const diff = this.center.direction(this.desiredCenter);
const length: any = diff.length(); const length = diff.length();
const tolerance: any = 1 / this.zoomLevel; const tolerance = 1 / this.zoomLevel;
if (length > tolerance) { if (length > tolerance) {
const movement: any = diff.multiplyScalar(Math.min(1, dt * 0.008)); const movement = diff.multiplyScalar(Math.min(1, dt * 0.008));
this.center.x += movement.x; this.center.x += movement.x;
this.center.y += movement.y; this.center.y += movement.y;
} }
@ -796,13 +796,13 @@ export class Camera extends BasicSerializableObject {
/** /**
* Updates the keyboard forces * Updates the keyboard forces
*/ */
internalUpdateKeyboardForce(now: number, dt: number): any { internalUpdateKeyboardForce(now: number, dt: number) {
if (!this.currentlyMoving && this.desiredCenter == null) { if (!this.currentlyMoving && this.desiredCenter == null) {
const limitingDimension: any = Math.min(this.root.gameWidth, this.root.gameHeight); const limitingDimension = Math.min(this.root.gameWidth, this.root.gameHeight);
const moveAmount: any = ((limitingDimension / 2048) * dt) / this.zoomLevel; const moveAmount = ((limitingDimension / 2048) * dt) / this.zoomLevel;
let forceX: any = 0; let forceX = 0;
let forceY: any = 0; let forceY = 0;
const actionMapper: any = this.root.keyMapper; const actionMapper = this.root.keyMapper;
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).pressed) { if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).pressed) {
forceY -= 1; forceY -= 1;
} }
@ -815,7 +815,7 @@ export class Camera extends BasicSerializableObject {
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).pressed) { if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).pressed) {
forceX += 1; forceX += 1;
} }
let movementSpeed: any = this.root.app.settings.getMovementSpeed() * let movementSpeed = this.root.app.settings.getMovementSpeed() *
(actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveFaster).pressed ? 4 : 1); (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveFaster).pressed ? 4 : 1);
this.center.x += moveAmount * forceX * movementSpeed; this.center.x += moveAmount * forceX * movementSpeed;
this.center.y += moveAmount * forceY * movementSpeed; this.center.y += moveAmount * forceY * movementSpeed;

View File

@ -1,5 +1,5 @@
/** @enum {string} */ /** @enum {string} */
export const enumColors: any = { export const enumColors = {
red: "red", red: "red",
green: "green", green: "green",
blue: "blue", blue: "blue",
@ -9,9 +9,9 @@ export const enumColors: any = {
white: "white", white: "white",
uncolored: "uncolored", uncolored: "uncolored",
}; };
const c: any = enumColors; const c = enumColors;
/** @enum {string} */ /** @enum {string} */
export const enumColorToShortcode: any = { export const enumColorToShortcode = {
[c.red]: "r", [c.red]: "r",
[c.green]: "g", [c.green]: "g",
[c.blue]: "b", [c.blue]: "b",
@ -22,12 +22,12 @@ export const enumColorToShortcode: any = {
[c.uncolored]: "u", [c.uncolored]: "u",
}; };
/** @enum {enumColors} */ /** @enum {enumColors} */
export const enumShortcodeToColor: any = {}; export const enumShortcodeToColor = {};
for (const key: any in enumColorToShortcode) { for (const key in enumColorToShortcode) {
enumShortcodeToColor[enumColorToShortcode[key]] = key; enumShortcodeToColor[enumColorToShortcode[key]] = key;
} }
/** @enum {string} */ /** @enum {string} */
export const enumColorsToHexCode: any = { export const enumColorsToHexCode = {
[c.red]: "#ff666a", [c.red]: "#ff666a",
[c.green]: "#78ff66", [c.green]: "#78ff66",
[c.blue]: "#66a7ff", [c.blue]: "#66a7ff",
@ -42,8 +42,8 @@ export const enumColorsToHexCode: any = {
[c.uncolored]: "#aaaaaa", [c.uncolored]: "#aaaaaa",
}; };
/** @enum {Object.<string, string>} */ /** @enum {Object.<string, string>} */
export const enumColorMixingResults: any = {}; export const enumColorMixingResults = {};
const bitfieldToColor: any = [ const bitfieldToColor = [
/* 000 */ c.uncolored, /* 000 */ c.uncolored,
/* 001 */ c.red, /* 001 */ c.red,
/* 010 */ c.green, /* 010 */ c.green,
@ -53,9 +53,9 @@ const bitfieldToColor: any = [
/* 110 */ c.cyan, /* 110 */ c.cyan,
/* 111 */ c.white, /* 111 */ c.white,
]; ];
for (let i: any = 0; i < 1 << 3; ++i) { for (let i = 0; i < 1 << 3; ++i) {
enumColorMixingResults[bitfieldToColor[i]] = {}; enumColorMixingResults[bitfieldToColor[i]] = {};
for (let j: any = 0; j < 1 << 3; ++j) { for (let j = 0; j < 1 << 3; ++j) {
enumColorMixingResults[bitfieldToColor[i]][bitfieldToColor[j]] = bitfieldToColor[i | j]; enumColorMixingResults[bitfieldToColor[i]][bitfieldToColor[j]] = bitfieldToColor[i | j];
} }
} }

View File

@ -12,17 +12,17 @@ export class Component extends BasicSerializableObject {
/** /**
* Should return the schema used for serialization * Should return the schema used for serialization
*/ */
static getSchema(): any { static getSchema() {
return {}; return {};
} }
/** /**
* Copy the current state to another component * Copy the current state to another component
*/ */
copyAdditionalStateTo(otherComponent: Component): any { } copyAdditionalStateTo(otherComponent: Component) { }
/** /**
* Clears all items and state * Clears all items and state
*/ */
clear(): any { } clear() { }
/* dev:start */ /* dev:start */
/** /**
* Fixes typeof DerivedComponent is not assignable to typeof Component, compiled out * Fixes typeof DerivedComponent is not assignable to typeof Component, compiled out

View File

@ -20,8 +20,8 @@ import { BeltReaderComponent } from "./components/belt_reader";
import { FilterComponent } from "./components/filter"; import { FilterComponent } from "./components/filter";
import { ItemProducerComponent } from "./components/item_producer"; import { ItemProducerComponent } from "./components/item_producer";
import { GoalAcceptorComponent } from "./components/goal_acceptor"; import { GoalAcceptorComponent } from "./components/goal_acceptor";
export function initComponentRegistry(): any { export function initComponentRegistry() {
const components: any = [ const components = [
StaticMapEntityComponent, StaticMapEntityComponent,
BeltComponent, BeltComponent,
ItemEjectorComponent, ItemEjectorComponent,
@ -44,7 +44,7 @@ export function initComponentRegistry(): any {
ItemProducerComponent, ItemProducerComponent,
GoalAcceptorComponent, GoalAcceptorComponent,
]; ];
components.forEach((component: any): any => gComponentRegistry.register(component)); components.forEach(component => gComponentRegistry.register(component));
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS // IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS
// Sanity check - If this is thrown, you forgot to add a new component here // Sanity check - If this is thrown, you forgot to add a new component here
assert( assert(

View File

@ -2,7 +2,7 @@ import { enumDirection, Vector } from "../../core/vector";
import { types } from "../../savegame/serialization"; import { types } from "../../savegame/serialization";
import { BeltPath } from "../belt_path"; import { BeltPath } from "../belt_path";
import { Component } from "../component"; import { Component } from "../component";
export const curvedBeltLength: any = 0.78; export const curvedBeltLength = /* Math.PI / 4 */ 0.78;
export const FAKE_BELT_ACCEPTOR_SLOT: import("./item_acceptor").ItemAcceptorSlot = { export const FAKE_BELT_ACCEPTOR_SLOT: import("./item_acceptor").ItemAcceptorSlot = {
pos: new Vector(0, 0), pos: new Vector(0, 0),
direction: enumDirection.bottom, direction: enumDirection.bottom,
@ -30,7 +30,7 @@ export const FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION: {
}, },
}; };
export class BeltComponent extends Component { export class BeltComponent extends Component {
static getId(): any { static getId() {
return "Belt"; return "Belt";
} }
public direction = direction; public direction = direction;
@ -39,7 +39,7 @@ export class BeltComponent extends Component {
constructor({ direction = enumDirection.top }) { constructor({ direction = enumDirection.top }) {
super(); super();
} }
clear(): any { clear() {
if (this.assignedPath) { if (this.assignedPath) {
this.assignedPath.clearAllItems(); this.assignedPath.clearAllItems();
} }
@ -79,12 +79,12 @@ export class BeltComponent extends Component {
return new Vector(0, 0.5 - progress); return new Vector(0, 0.5 - progress);
case enumDirection.right: { case enumDirection.right: {
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress); assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress);
const arcProgress: any = (progress / curvedBeltLength) * 0.5 * Math.PI; const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
return new Vector(0.5 - 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress)); return new Vector(0.5 - 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress));
} }
case enumDirection.left: { case enumDirection.left: {
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress); assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress);
const arcProgress: any = (progress / curvedBeltLength) * 0.5 * Math.PI; const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
return new Vector(-0.5 + 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress)); return new Vector(-0.5 + 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress));
} }
default: default:

View File

@ -3,15 +3,15 @@ import { BaseItem } from "../base_item";
import { typeItemSingleton } from "../item_resolver"; import { typeItemSingleton } from "../item_resolver";
import { types } from "../../savegame/serialization"; import { types } from "../../savegame/serialization";
/** @enum {string} */ /** @enum {string} */
export const enumBeltReaderType: any = { export const enumBeltReaderType = {
wired: "wired", wired: "wired",
wireless: "wireless", wireless: "wireless",
}; };
export class BeltReaderComponent extends Component { export class BeltReaderComponent extends Component {
static getId(): any { static getId() {
return "BeltReader"; return "BeltReader";
} }
static getSchema(): any { static getSchema() {
return { return {
lastItem: types.nullable(typeItemSingleton), lastItem: types.nullable(typeItemSingleton),
}; };
@ -21,7 +21,7 @@ export class BeltReaderComponent extends Component {
super(); super();
this.clear(); this.clear();
} }
clear(): any { clear() {
/** /**
* Which items went through the reader, we only store the time * Which items went through the reader, we only store the time
*/ */

View File

@ -9,7 +9,7 @@ import { Component } from "../component";
* Top Only: * Top Only:
* @enum {string} * @enum {string}
*/ */
export const enumClippedBeltUnderlayType: any = { export const enumClippedBeltUnderlayType = {
full: "full", full: "full",
bottomOnly: "bottomOnly", bottomOnly: "bottomOnly",
topOnly: "topOnly", topOnly: "topOnly",
@ -22,7 +22,7 @@ export type BeltUnderlayTile = {
}; };
export class BeltUnderlaysComponent extends Component { export class BeltUnderlaysComponent extends Component {
static getId(): any { static getId() {
return "BeltUnderlays"; return "BeltUnderlays";
} }
public underlays = underlays; public underlays = underlays;

View File

@ -3,10 +3,10 @@ import { BaseItem } from "../base_item";
import { Component } from "../component"; import { Component } from "../component";
import { typeItemSingleton } from "../item_resolver"; import { typeItemSingleton } from "../item_resolver";
export class ConstantSignalComponent extends Component { export class ConstantSignalComponent extends Component {
static getId(): any { static getId() {
return "ConstantSignal"; return "ConstantSignal";
} }
static getSchema(): any { static getSchema() {
return { return {
signal: types.nullable(typeItemSingleton), signal: types.nullable(typeItemSingleton),
}; };
@ -14,7 +14,7 @@ export class ConstantSignalComponent extends Component {
/** /**
* Copy the current state to another component * Copy the current state to another component
*/ */
copyAdditionalStateTo(otherComponent: ConstantSignalComponent): any { copyAdditionalStateTo(otherComponent: ConstantSignalComponent) {
otherComponent.signal = this.signal; otherComponent.signal = this.signal;
} }
public signal = signal; public signal = signal;

View File

@ -1,6 +1,6 @@
import { Component } from "../component"; import { Component } from "../component";
export class DisplayComponent extends Component { export class DisplayComponent extends Component {
static getId(): any { static getId() {
return "Display"; return "Display";
} }
} }

View File

@ -8,13 +8,13 @@ export type PendingFilterItem = {
}; };
export class FilterComponent extends Component { export class FilterComponent extends Component {
static getId(): any { static getId() {
return "Filter"; return "Filter";
} }
duplicateWithoutContents(): any { duplicateWithoutContents() {
return new FilterComponent(); return new FilterComponent();
} }
static getSchema(): any { static getSchema() {
return { return {
pendingItemsToLeaveThrough: types.array(types.structured({ pendingItemsToLeaveThrough: types.array(types.structured({
item: typeItemSingleton, item: typeItemSingleton,
@ -31,7 +31,7 @@ export class FilterComponent extends Component {
super(); super();
this.clear(); this.clear();
} }
clear(): any { clear() {
/** /**
* Items in queue to leave through * Items in queue to leave through
*/ */

View File

@ -3,10 +3,10 @@ import { BaseItem } from "../base_item";
import { Component } from "../component"; import { Component } from "../component";
import { typeItemSingleton } from "../item_resolver"; import { typeItemSingleton } from "../item_resolver";
export class GoalAcceptorComponent extends Component { export class GoalAcceptorComponent extends Component {
static getId(): any { static getId() {
return "GoalAcceptor"; return "GoalAcceptor";
} }
static getSchema(): any { static getSchema() {
return { return {
item: typeItemSingleton, item: typeItemSingleton,
}; };
@ -17,7 +17,7 @@ export class GoalAcceptorComponent extends Component {
super(); super();
this.clear(); this.clear();
} }
clear(): any { clear() {
/** /**
* The last item we delivered * The last item we delivered
*/ */
@ -30,18 +30,18 @@ export class GoalAcceptorComponent extends Component {
/** /**
* Clears items but doesn't instantly reset the progress bar * Clears items but doesn't instantly reset the progress bar
*/ */
clearItems(): any { clearItems() {
this.lastDelivery = null; this.lastDelivery = null;
this.currentDeliveredItems = 0; this.currentDeliveredItems = 0;
} }
getRequiredSecondsPerItem(): any { getRequiredSecondsPerItem() {
return (globalConfig.goalAcceptorsPerProducer / return (globalConfig.goalAcceptorsPerProducer /
(globalConfig.puzzleModeSpeed * globalConfig.beltSpeedItemsPerSecond)); (globalConfig.puzzleModeSpeed * globalConfig.beltSpeedItemsPerSecond));
} }
/** /**
* Copy the current state to another component * Copy the current state to another component
*/ */
copyAdditionalStateTo(otherComponent: GoalAcceptorComponent): any { copyAdditionalStateTo(otherComponent: GoalAcceptorComponent) {
otherComponent.item = this.item; otherComponent.item = this.item;
} }
} }

View File

@ -1,6 +1,6 @@
import { Component } from "../component"; import { Component } from "../component";
export class HubComponent extends Component { export class HubComponent extends Component {
static getId(): any { static getId() {
return "Hub"; return "Hub";
} }
} }

View File

@ -20,7 +20,7 @@ export type ItemAcceptorSlotConfig = {
export class ItemAcceptorComponent extends Component { export class ItemAcceptorComponent extends Component {
static getId(): any { static getId() {
return "ItemAcceptor"; return "ItemAcceptor";
} }
@ -29,16 +29,16 @@ export class ItemAcceptorComponent extends Component {
this.setSlots(slots); this.setSlots(slots);
this.clear(); this.clear();
} }
clear(): any { clear() {
/** /**
* Fixes belt animations * Fixes belt animations
*/ */
this.itemConsumptionAnimations = []; this.itemConsumptionAnimations = [];
} }
setSlots(slots: Array<ItemAcceptorSlotConfig>): any { setSlots(slots: Array<ItemAcceptorSlotConfig>) {
this.slots = []; this.slots = [];
for (let i: any = 0; i < slots.length; ++i) { for (let i = 0; i < slots.length; ++i) {
const slot: any = slots[i]; const slot = slots[i];
this.slots.push({ this.slots.push({
pos: slot.pos, pos: slot.pos,
direction: slot.direction, direction: slot.direction,
@ -52,14 +52,14 @@ export class ItemAcceptorComponent extends Component {
* *
* NOTICE: The belt path ignores this for performance reasons and does his own check * NOTICE: The belt path ignores this for performance reasons and does his own check
*/ */
canAcceptItem(slotIndex: number, item: BaseItem=): any { canAcceptItem(slotIndex: number, item: BaseItem=) {
const slot: any = this.slots[slotIndex]; const slot = this.slots[slotIndex];
return !slot.filter || slot.filter === item.getItemType(); return !slot.filter || slot.filter === item.getItemType();
} }
/** /**
* Called when an item has been accepted so that * Called when an item has been accepted so that
*/ */
onItemAccepted(slotIndex: number, direction: enumDirection, item: BaseItem, remainingProgress: number = 0.0): any { onItemAccepted(slotIndex: number, direction: enumDirection, item: BaseItem, remainingProgress: number = 0.0) {
this.itemConsumptionAnimations.push({ this.itemConsumptionAnimations.push({
item, item,
slotIndex, slotIndex,
@ -75,10 +75,10 @@ export class ItemAcceptorComponent extends Component {
// We need to invert our direction since the acceptor specifies *from* which direction // We need to invert our direction since the acceptor specifies *from* which direction
// it accepts items, but the ejector specifies *into* which direction it ejects items. // it accepts items, but the ejector specifies *into* which direction it ejects items.
// E.g.: Ejector ejects into "right" direction but acceptor accepts from "left" direction. // E.g.: Ejector ejects into "right" direction but acceptor accepts from "left" direction.
const desiredDirection: any = enumInvertedDirections[fromLocalDirection]; const desiredDirection = enumInvertedDirections[fromLocalDirection];
// Go over all slots and try to find a target slot // Go over all slots and try to find a target slot
for (let slotIndex: any = 0; slotIndex < this.slots.length; ++slotIndex) { for (let slotIndex = 0; slotIndex < this.slots.length; ++slotIndex) {
const slot: any = this.slots[slotIndex]; const slot = this.slots[slotIndex];
// Make sure the acceptor slot is on the right position // Make sure the acceptor slot is on the right position
if (!slot.pos.equals(targetLocalTile)) { if (!slot.pos.equals(targetLocalTile)) {
continue; continue;

View File

@ -17,10 +17,10 @@ export type ItemEjectorSlot = {
}; };
export class ItemEjectorComponent extends Component { export class ItemEjectorComponent extends Component {
static getId(): any { static getId() {
return "ItemEjector"; return "ItemEjector";
} }
static getSchema(): any { static getSchema() {
// The cachedDestSlot, cachedTargetEntity fields are not serialized. // The cachedDestSlot, cachedTargetEntity fields are not serialized.
return { return {
slots: types.fixedSizeArray(types.structured({ slots: types.fixedSizeArray(types.structured({
@ -35,8 +35,8 @@ export class ItemEjectorComponent extends Component {
super(); super();
this.setSlots(slots); this.setSlots(slots);
} }
clear(): any { clear() {
for (const slot: any of this.slots) { for (const slot of this.slots) {
slot.item = null; slot.item = null;
slot.lastItem = null; slot.lastItem = null;
slot.progress = 0; slot.progress = 0;
@ -45,10 +45,10 @@ export class ItemEjectorComponent extends Component {
setSlots(slots: Array<{ setSlots(slots: Array<{
pos: Vector; pos: Vector;
direction: enumDirection; direction: enumDirection;
}>): any { }>) {
this.slots = []; this.slots = [];
for (let i: any = 0; i < slots.length; ++i) { for (let i = 0; i < slots.length; ++i) {
const slot: any = slots[i]; const slot = slots[i];
this.slots.push({ this.slots.push({
pos: slot.pos, pos: slot.pos,
direction: slot.direction, direction: slot.direction,
@ -65,14 +65,14 @@ export class ItemEjectorComponent extends Component {
* {} * {}
*/ */
getSlotTargetLocalTile(slot: ItemEjectorSlot): Vector { getSlotTargetLocalTile(slot: ItemEjectorSlot): Vector {
const directionVector: any = enumDirectionToVector[slot.direction]; const directionVector = enumDirectionToVector[slot.direction];
return slot.pos.add(directionVector); return slot.pos.add(directionVector);
} }
/** /**
* Returns whether any slot ejects to the given local tile * Returns whether any slot ejects to the given local tile
*/ */
anySlotEjectsToLocalTile(tile: Vector): any { anySlotEjectsToLocalTile(tile: Vector) {
for (let i: any = 0; i < this.slots.length; ++i) { for (let i = 0; i < this.slots.length; ++i) {
if (this.getSlotTargetLocalTile(this.slots[i]).equals(tile)) { if (this.getSlotTargetLocalTile(this.slots[i]).equals(tile)) {
return true; return true;
} }
@ -92,7 +92,7 @@ export class ItemEjectorComponent extends Component {
* {} * {}
*/ */
getFirstFreeSlot(): ?number { getFirstFreeSlot(): ?number {
for (let i: any = 0; i < this.slots.length; ++i) { for (let i = 0; i < this.slots.length; ++i) {
if (this.canEjectOnSlot(i)) { if (this.canEjectOnSlot(i)) {
return i; return i;
} }
@ -117,8 +117,8 @@ export class ItemEjectorComponent extends Component {
* {} * {}
*/ */
takeSlotItem(slotIndex: number): BaseItem | null { takeSlotItem(slotIndex: number): BaseItem | null {
const slot: any = this.slots[slotIndex]; const slot = this.slots[slotIndex];
const item: any = slot.item; const item = slot.item;
slot.item = null; slot.item = null;
slot.progress = 0.0; slot.progress = 0.0;
return item; return item;

View File

@ -2,7 +2,7 @@ import { types } from "../../savegame/serialization";
import { BaseItem } from "../base_item"; import { BaseItem } from "../base_item";
import { Component } from "../component"; import { Component } from "../component";
/** @enum {string} */ /** @enum {string} */
export const enumItemProcessorTypes: any = { export const enumItemProcessorTypes = {
balancer: "balancer", balancer: "balancer",
cutter: "cutter", cutter: "cutter",
cutterQuad: "cutterQuad", cutterQuad: "cutterQuad",
@ -21,7 +21,7 @@ export const enumItemProcessorTypes: any = {
goal: "goal", goal: "goal",
}; };
/** @enum {string} */ /** @enum {string} */
export const enumItemProcessorRequirements: any = { export const enumItemProcessorRequirements = {
painterQuad: "painterQuad", painterQuad: "painterQuad",
}; };
export type EjectorItemToEject = { export type EjectorItemToEject = {
@ -36,10 +36,10 @@ export type EjectorCharge = {
export class ItemProcessorComponent extends Component { export class ItemProcessorComponent extends Component {
static getId(): any { static getId() {
return "ItemProcessor"; return "ItemProcessor";
} }
static getSchema(): any { static getSchema() {
return { return {
nextOutputSlot: types.uint, nextOutputSlot: types.uint,
}; };
@ -53,7 +53,7 @@ export class ItemProcessorComponent extends Component {
super(); super();
this.clear(); this.clear();
} }
clear(): any { clear() {
// Which slot to emit next, this is only a preference and if it can't emit // Which slot to emit next, this is only a preference and if it can't emit
// it will take the other one. Some machines ignore this (e.g. the balancer) to make // it will take the other one. Some machines ignore this (e.g. the balancer) to make
// sure the outputs always match // sure the outputs always match
@ -78,7 +78,7 @@ export class ItemProcessorComponent extends Component {
/** /**
* Tries to take the item * Tries to take the item
*/ */
tryTakeItem(item: BaseItem, sourceSlot: number): any { tryTakeItem(item: BaseItem, sourceSlot: number) {
if (this.type === enumItemProcessorTypes.hub || if (this.type === enumItemProcessorTypes.hub ||
this.type === enumItemProcessorTypes.trash || this.type === enumItemProcessorTypes.trash ||
this.type === enumItemProcessorTypes.goal) { this.type === enumItemProcessorTypes.goal) {

View File

@ -1,6 +1,6 @@
import { Component } from "../component"; import { Component } from "../component";
export class ItemProducerComponent extends Component { export class ItemProducerComponent extends Component {
static getId(): any { static getId() {
return "ItemProducer"; return "ItemProducer";
} }
} }

View File

@ -1,10 +1,10 @@
import { Component } from "../component"; import { Component } from "../component";
import { types } from "../../savegame/serialization"; import { types } from "../../savegame/serialization";
export class LeverComponent extends Component { export class LeverComponent extends Component {
static getId(): any { static getId() {
return "Lever"; return "Lever";
} }
static getSchema(): any { static getSchema() {
return { return {
toggled: types.bool, toggled: types.bool,
}; };
@ -12,7 +12,7 @@ export class LeverComponent extends Component {
/** /**
* Copy the current state to another component * Copy the current state to another component
*/ */
copyAdditionalStateTo(otherComponent: LeverComponent): any { copyAdditionalStateTo(otherComponent: LeverComponent) {
otherComponent.toggled = this.toggled; otherComponent.toggled = this.toggled;
} }
public toggled = toggled; public toggled = toggled;

View File

@ -1,6 +1,6 @@
import { Component } from "../component"; import { Component } from "../component";
/** @enum {string} */ /** @enum {string} */
export const enumLogicGateType: any = { export const enumLogicGateType = {
and: "and", and: "and",
not: "not", not: "not",
xor: "xor", xor: "xor",
@ -15,7 +15,7 @@ export const enumLogicGateType: any = {
painter: "painter", painter: "painter",
}; };
export class LogicGateComponent extends Component { export class LogicGateComponent extends Component {
static getId(): any { static getId() {
return "LogicGate"; return "LogicGate";
} }
public type = type; public type = type;

View File

@ -3,12 +3,12 @@ import { BaseItem } from "../base_item";
import { Component } from "../component"; import { Component } from "../component";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { typeItemSingleton } from "../item_resolver"; import { typeItemSingleton } from "../item_resolver";
const chainBufferSize: any = 6; const chainBufferSize = 6;
export class MinerComponent extends Component { export class MinerComponent extends Component {
static getId(): any { static getId() {
return "Miner"; return "Miner";
} }
static getSchema(): any { static getSchema() {
// cachedMinedItem is not serialized. // cachedMinedItem is not serialized.
return { return {
lastMiningTime: types.ufloat, lastMiningTime: types.ufloat,
@ -24,14 +24,14 @@ export class MinerComponent extends Component {
super(); super();
this.clear(); this.clear();
} }
clear(): any { clear() {
/** /**
* Stores items from other miners which were chained to this * Stores items from other miners which were chained to this
* miner. * miner.
*/ */
this.itemChainBuffer = []; this.itemChainBuffer = [];
} }
tryAcceptChainedItem(item: BaseItem): any { tryAcceptChainedItem(item: BaseItem) {
if (this.itemChainBuffer.length > chainBufferSize) { if (this.itemChainBuffer.length > chainBufferSize) {
// Well, this one is full // Well, this one is full
return false; return false;

View File

@ -7,10 +7,10 @@ import { types } from "../../savegame/serialization";
import { getBuildingDataFromCode } from "../building_codes"; import { getBuildingDataFromCode } from "../building_codes";
import { Component } from "../component"; import { Component } from "../component";
export class StaticMapEntityComponent extends Component { export class StaticMapEntityComponent extends Component {
static getId(): any { static getId() {
return "StaticMapEntity"; return "StaticMapEntity";
} }
static getSchema(): any { static getSchema() {
return { return {
origin: types.tileVector, origin: types.tileVector,
rotation: types.float, rotation: types.float,
@ -71,7 +71,7 @@ export class StaticMapEntityComponent extends Component {
/** /**
* Copy the current state to another component * Copy the current state to another component
*/ */
copyAdditionalStateTo(otherComponent: Component): any { copyAdditionalStateTo(otherComponent: Component) {
return new StaticMapEntityComponent({ return new StaticMapEntityComponent({
origin: this.origin.copy(), origin: this.origin.copy(),
rotation: this.rotation, rotation: this.rotation,
@ -93,7 +93,7 @@ export class StaticMapEntityComponent extends Component {
* {} * {}
*/ */
getTileSpaceBounds(): Rectangle { getTileSpaceBounds(): Rectangle {
const size: any = this.getTileSize(); const size = this.getTileSize();
switch (this.rotation) { switch (this.rotation) {
case 0: case 0:
return new Rectangle(this.origin.x, this.origin.y, size.x, size.y); return new Rectangle(this.origin.x, this.origin.y, size.x, size.y);
@ -140,7 +140,7 @@ export class StaticMapEntityComponent extends Component {
* {} * {}
*/ */
localTileToWorld(localTile: Vector): Vector { localTileToWorld(localTile: Vector): Vector {
const result: any = localTile.rotateFastMultipleOf90(this.rotation); const result = localTile.rotateFastMultipleOf90(this.rotation);
result.x += this.origin.x; result.x += this.origin.x;
result.y += this.origin.y; result.y += this.origin.y;
return result; return result;
@ -148,19 +148,19 @@ export class StaticMapEntityComponent extends Component {
/** /**
* Transforms from world space to local space * Transforms from world space to local space
*/ */
worldToLocalTile(worldTile: Vector): any { worldToLocalTile(worldTile: Vector) {
const localUnrotated: any = worldTile.sub(this.origin); const localUnrotated = worldTile.sub(this.origin);
return this.unapplyRotationToVector(localUnrotated); return this.unapplyRotationToVector(localUnrotated);
} }
/** /**
* Returns whether the entity should be drawn for the given parameters * Returns whether the entity should be drawn for the given parameters
*/ */
shouldBeDrawn(parameters: DrawParameters): any { shouldBeDrawn(parameters: DrawParameters) {
let x: any = 0; let x = 0;
let y: any = 0; let y = 0;
let w: any = 0; let w = 0;
let h: any = 0; let h = 0;
const size: any = this.getTileSize(); const size = this.getTileSize();
switch (this.rotation) { switch (this.rotation) {
case 0: { case 0: {
x = this.origin.x; x = this.origin.x;
@ -198,13 +198,13 @@ export class StaticMapEntityComponent extends Component {
/** /**
* Draws a sprite over the whole space of the entity * Draws a sprite over the whole space of the entity
*/ */
drawSpriteOnBoundsClipped(parameters: DrawParameters, sprite: AtlasSprite, extrudePixels: number= = 0, overridePosition: Vector= = null): any { drawSpriteOnBoundsClipped(parameters: DrawParameters, sprite: AtlasSprite, extrudePixels: number= = 0, overridePosition: Vector= = null) {
if (!this.shouldBeDrawn(parameters) && !overridePosition) { if (!this.shouldBeDrawn(parameters) && !overridePosition) {
return; return;
} }
const size: any = this.getTileSize(); const size = this.getTileSize();
let worldX: any = this.origin.x * globalConfig.tileSize; let worldX = this.origin.x * globalConfig.tileSize;
let worldY: any = this.origin.y * globalConfig.tileSize; let worldY = this.origin.y * globalConfig.tileSize;
if (overridePosition) { if (overridePosition) {
worldX = overridePosition.x * globalConfig.tileSize; worldX = overridePosition.x * globalConfig.tileSize;
worldY = overridePosition.y * globalConfig.tileSize; worldY = overridePosition.y * globalConfig.tileSize;
@ -214,8 +214,8 @@ export class StaticMapEntityComponent extends Component {
sprite.drawCached(parameters, worldX - extrudePixels * size.x, worldY - extrudePixels * size.y, globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, globalConfig.tileSize * size.y + 2 * extrudePixels * size.y); sprite.drawCached(parameters, worldX - extrudePixels * size.x, worldY - extrudePixels * size.y, globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, globalConfig.tileSize * size.y + 2 * extrudePixels * size.y);
} }
else { else {
const rotationCenterX: any = worldX + globalConfig.halfTileSize; const rotationCenterX = worldX + globalConfig.halfTileSize;
const rotationCenterY: any = worldY + globalConfig.halfTileSize; const rotationCenterY = worldY + globalConfig.halfTileSize;
parameters.context.translate(rotationCenterX, rotationCenterY); parameters.context.translate(rotationCenterX, rotationCenterY);
parameters.context.rotate(Math.radians(this.rotation)); parameters.context.rotate(Math.radians(this.rotation));
sprite.drawCached(parameters, -globalConfig.halfTileSize - extrudePixels * size.x, -globalConfig.halfTileSize - extrudePixels * size.y, globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, globalConfig.tileSize * size.y + 2 * extrudePixels * size.y, false // no clipping possible here sprite.drawCached(parameters, -globalConfig.halfTileSize - extrudePixels * size.x, -globalConfig.halfTileSize - extrudePixels * size.y, globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, globalConfig.tileSize * size.y + 2 * extrudePixels * size.y, false // no clipping possible here

View File

@ -8,10 +8,10 @@ export const MODS_ADDITIONAL_STORAGE_ITEM_RESOLVER: {
[x: string]: (item: BaseItem) => Boolean; [x: string]: (item: BaseItem) => Boolean;
} = {}; } = {};
export class StorageComponent extends Component { export class StorageComponent extends Component {
static getId(): any { static getId() {
return "Storage"; return "Storage";
} }
static getSchema(): any { static getSchema() {
return { return {
storedCount: types.uint, storedCount: types.uint,
storedItem: types.nullable(typeItemSingleton), storedItem: types.nullable(typeItemSingleton),
@ -28,14 +28,14 @@ export class StorageComponent extends Component {
/** /**
* Returns whether this storage can accept the item * Returns whether this storage can accept the item
*/ */
canAcceptItem(item: BaseItem): any { canAcceptItem(item: BaseItem) {
if (this.storedCount >= this.maximumStorage) { if (this.storedCount >= this.maximumStorage) {
return false; return false;
} }
if (!this.storedItem || this.storedCount === 0) { if (!this.storedItem || this.storedCount === 0) {
return true; return true;
} }
const itemType: any = item.getItemType(); const itemType = item.getItemType();
if (itemType !== this.storedItem.getItemType()) { if (itemType !== this.storedItem.getItemType()) {
// Check type matches // Check type matches
return false; return false;
@ -60,7 +60,7 @@ export class StorageComponent extends Component {
getIsFull(): boolean { getIsFull(): boolean {
return this.storedCount >= this.maximumStorage; return this.storedCount >= this.maximumStorage;
} }
takeItem(item: BaseItem): any { takeItem(item: BaseItem) {
this.storedItem = item; this.storedItem = item;
this.storedCount++; this.storedCount++;
} }

View File

@ -5,7 +5,7 @@ import { Component } from "../component";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { typeItemSingleton } from "../item_resolver"; import { typeItemSingleton } from "../item_resolver";
/** @enum {string} */ /** @enum {string} */
export const enumUndergroundBeltMode: any = { export const enumUndergroundBeltMode = {
sender: "sender", sender: "sender",
receiver: "receiver", receiver: "receiver",
}; };
@ -15,10 +15,10 @@ export type LinkedUndergroundBelt = {
}; };
export class UndergroundBeltComponent extends Component { export class UndergroundBeltComponent extends Component {
static getId(): any { static getId() {
return "UndergroundBelt"; return "UndergroundBelt";
} }
static getSchema(): any { static getSchema() {
return { return {
pendingItems: types.array(types.pair(typeItemSingleton, types.float)), pendingItems: types.array(types.pair(typeItemSingleton, types.float)),
}; };
@ -31,7 +31,7 @@ export class UndergroundBeltComponent extends Component {
super(); super();
this.clear(); this.clear();
} }
clear(): any { clear() {
this.consumptionAnimations = []; this.consumptionAnimations = [];
/** /**
* Used on both receiver and sender. * Used on both receiver and sender.
@ -44,7 +44,7 @@ export class UndergroundBeltComponent extends Component {
/** /**
* Tries to accept an item from an external source like a regular belt or building * Tries to accept an item from an external source like a regular belt or building
*/ */
tryAcceptExternalItem(item: BaseItem, beltSpeed: number): any { tryAcceptExternalItem(item: BaseItem, beltSpeed: number) {
if (this.mode !== enumUndergroundBeltMode.sender) { if (this.mode !== enumUndergroundBeltMode.sender) {
// Only senders accept external items // Only senders accept external items
return false; return false;
@ -59,13 +59,13 @@ export class UndergroundBeltComponent extends Component {
/** /**
* Tries to accept a tunneled item * Tries to accept a tunneled item
*/ */
tryAcceptTunneledItem(item: BaseItem, travelDistance: number, beltSpeed: number, now: number): any { tryAcceptTunneledItem(item: BaseItem, travelDistance: number, beltSpeed: number, now: number) {
if (this.mode !== enumUndergroundBeltMode.receiver) { if (this.mode !== enumUndergroundBeltMode.receiver) {
// Only receivers can accept tunneled items // Only receivers can accept tunneled items
return false; return false;
} }
// Notice: We assume that for all items the travel distance is the same // Notice: We assume that for all items the travel distance is the same
const maxItemsInTunnel: any = (2 + travelDistance) / globalConfig.itemSpacingOnBelts; const maxItemsInTunnel = (2 + travelDistance) / globalConfig.itemSpacingOnBelts;
if (this.pendingItems.length >= maxItemsInTunnel) { if (this.pendingItems.length >= maxItemsInTunnel) {
// Simulate a real belt which gets full at some point // Simulate a real belt which gets full at some point
return false; return false;
@ -74,7 +74,7 @@ export class UndergroundBeltComponent extends Component {
// This corresponds to the item ejector - it needs 0.5 additional tiles to eject the item. // This corresponds to the item ejector - it needs 0.5 additional tiles to eject the item.
// So instead of adding 1 we add 0.5 only. // So instead of adding 1 we add 0.5 only.
// Additionally it takes 1 tile for the acceptor which we just add on top. // Additionally it takes 1 tile for the acceptor which we just add on top.
const travelDuration: any = (travelDistance + 1.5) / beltSpeed / globalConfig.itemSpacingOnBelts; const travelDuration = (travelDistance + 1.5) / beltSpeed / globalConfig.itemSpacingOnBelts;
this.pendingItems.push([item, now + travelDuration]); this.pendingItems.push([item, now + travelDuration]);
return true; return true;
} }

View File

@ -1,18 +1,18 @@
import { Component } from "../component"; import { Component } from "../component";
/** @enum {string} */ /** @enum {string} */
export const enumWireType: any = { export const enumWireType = {
forward: "forward", forward: "forward",
turn: "turn", turn: "turn",
split: "split", split: "split",
cross: "cross", cross: "cross",
}; };
/** @enum {string} */ /** @enum {string} */
export const enumWireVariant: any = { export const enumWireVariant = {
first: "first", first: "first",
second: "second", second: "second",
}; };
export class WireComponent extends Component { export class WireComponent extends Component {
static getId(): any { static getId() {
return "Wire"; return "Wire";
} }
public type = type; public type = type;

Some files were not shown because too many files have changed in this diff Show More