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:
parent
e768561dc6
commit
4dd57c1605
@ -40,13 +40,13 @@ import { MOD_SIGNALS } from "./mods/mod_signals";
|
||||
import { ModsState } from "./states/mods";
|
||||
|
||||
import type { AchievementProviderInterface } from "./platform/achievement_provider";
|
||||
import type { SoundInterface } from "./platform/sound";
|
||||
import type { SoundInterface } from "./platform/sound";
|
||||
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
|
||||
let pageHiddenPropName: any, pageVisibilityEventName: any;
|
||||
let pageHiddenPropName: string, pageVisibilityEventName: string;
|
||||
if (typeof document.hidden !== "undefined") {
|
||||
// Opera 12.10 and Firefox 18 and later support
|
||||
pageHiddenPropName = "hidden";
|
||||
@ -62,9 +62,7 @@ if (typeof document.hidden !== "undefined") {
|
||||
}
|
||||
|
||||
export class Application {
|
||||
public unloaded = true;
|
||||
|
||||
// Global stuff
|
||||
public unloaded = false;
|
||||
public settings = new ApplicationSettings(this);
|
||||
public ticker = new AnimationFrame();
|
||||
public stateMgr = new StateManager(this);
|
||||
@ -72,44 +70,28 @@ export class Application {
|
||||
public inputMgr = new InputDistributor(this);
|
||||
public backgroundResourceLoader = new BackgroundResourcesLoader(this);
|
||||
public clientApi = new ClientAPI(this);
|
||||
|
||||
// Restrictions (Like demo etc)
|
||||
public restrictionMgr = new RestrictionManager(this);
|
||||
|
||||
// Platform dependent stuff
|
||||
public storage: StorageInterface = null;
|
||||
public sound: SoundInterface = new SoundImplBrowser(this);
|
||||
public platformWrapper: PlatformWrapperInterface = G_IS_STANDALONE ? new PlatformWrapperImplElectron(this) : new PlatformWrapperImplBrowser(this);
|
||||
public achievementProvider: AchievementProviderInterface = new NoAchievementProvider(this);
|
||||
public adProvider: AdProviderInterface = new NoAdProvider(this);
|
||||
public analytics: AnalyticsInterface = new GoogleAnalyticsImpl(this);
|
||||
public gameAnalytics = new ShapezGameAnalytics(this);
|
||||
|
||||
// Track if the window is focused (only relevant for browser)
|
||||
public sound: SoundInterface = null;
|
||||
public platformWrapper: PlatformWrapperInterface = null;
|
||||
public achievementProvider: AchievementProviderInterface = null;
|
||||
public adProvider: AdProviderInterface = null;
|
||||
public analytics: AnalyticsInterface = null;
|
||||
public gameAnalytics: ShapezGameAnalytics = null;
|
||||
public focused = true;
|
||||
|
||||
// Track if the window is visible
|
||||
public pageVisible = true;
|
||||
|
||||
// Track if the app is paused (cordova)
|
||||
public applicationPaused = false;
|
||||
public trackedIsRenderable = new TrackedState(this.onAppRenderableStateChanged, this);
|
||||
public trackedIsPlaying = new TrackedState(this.onAppPlayingStateChanged, this);
|
||||
|
||||
// Dimensions
|
||||
public trackedIsRenderable: TypedTrackedState<boolean> = new TrackedState(this.onAppRenderableStateChanged, this);
|
||||
public trackedIsPlaying: TypedTrackedState<boolean> = new TrackedState(this.onAppPlayingStateChanged, this);
|
||||
public screenWidth = 0;
|
||||
public screenHeight = 0;
|
||||
// Store the timestamp where we last checked for a screen resize, since orientationchange is unreliable with cordova
|
||||
public lastResizeCheck: number = null;
|
||||
// Store the mouse position, or null if not available
|
||||
public mousePosition: Vector = null;
|
||||
|
||||
|
||||
public lastResizeCheck = null;
|
||||
public mousePosition: Vector | null = null;
|
||||
|
||||
/**
|
||||
* Boots the application
|
||||
*/
|
||||
async boot(): Promise<void> {
|
||||
async boot() {
|
||||
console.log("Booting ...");
|
||||
|
||||
assert(!GLOBAL_APP, "Tried to construct application twice");
|
||||
@ -122,12 +104,11 @@ export class Application {
|
||||
try {
|
||||
await MODS.initMods();
|
||||
}
|
||||
catch (ex: any) {
|
||||
catch (ex) {
|
||||
alert("Failed to load mods (launch with --dev for more info): \n\n" + ex);
|
||||
}
|
||||
|
||||
this.unloaded = false;
|
||||
|
||||
this.initPlatformDependentInstances();
|
||||
this.registerStates();
|
||||
this.registerEventListeners();
|
||||
|
||||
@ -151,11 +132,31 @@ export class Application {
|
||||
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
|
||||
*/
|
||||
registerStates(): void {
|
||||
const states: Array<typeof GameState> = [
|
||||
registerStates() {
|
||||
const states: Array<typeof GameState> = [
|
||||
WegameSplashState,
|
||||
PreloadState,
|
||||
MobileWarningState,
|
||||
@ -169,6 +170,7 @@ export class Application {
|
||||
LoginState,
|
||||
ModsState,
|
||||
];
|
||||
|
||||
for (let i = 0; i < states.length; ++i) {
|
||||
this.stateMgr.register(states[i]);
|
||||
}
|
||||
@ -177,7 +179,7 @@ export class Application {
|
||||
/**
|
||||
* Registers all event listeners
|
||||
*/
|
||||
registerEventListeners(): void {
|
||||
registerEventListeners() {
|
||||
window.addEventListener("focus", this.onFocus.bind(this));
|
||||
window.addEventListener("blur", this.onBlur.bind(this));
|
||||
|
||||
@ -191,19 +193,17 @@ export class Application {
|
||||
|
||||
// Unload events
|
||||
window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true);
|
||||
|
||||
document.addEventListener(pageVisibilityEventName, this.handleVisibilityChange.bind(this), false);
|
||||
|
||||
// Track touches so we can update the focus appropriately
|
||||
document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true);
|
||||
document.addEventListener("touchend", this.updateFocusAfterUserInteraction.bind(this), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the focus after a touch
|
||||
*/
|
||||
updateFocusAfterUserInteraction(event: TouchEvent): void {
|
||||
const target = (event.target as HTMLElement);
|
||||
updateFocusAfterUserInteraction(event: TouchEvent) {
|
||||
const target = event.target as HTMLElement;
|
||||
if (!target || !target.tagName) {
|
||||
// Safety check
|
||||
logger.warn("Invalid touchstart/touchend event:", event);
|
||||
@ -222,16 +222,16 @@ export class Application {
|
||||
// If we click an input field, focus it now
|
||||
if (target.tagName.toLowerCase() === "input") {
|
||||
// We *really* need the focus
|
||||
waitNextFrame().then((): any => target.focus());
|
||||
waitNextFrame().then(() => target.focus());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a page visibility change event
|
||||
*/
|
||||
handleVisibilityChange(event: Event): void {
|
||||
handleVisibilityChange(event: Event) {
|
||||
window.focus();
|
||||
const pageVisible: any = !document[pageHiddenPropName];
|
||||
const pageVisible = !document[pageHiddenPropName];
|
||||
if (pageVisible !== this.pageVisible) {
|
||||
this.pageVisible = pageVisible;
|
||||
logger.log("Visibility changed:", this.pageVisible);
|
||||
@ -242,35 +242,35 @@ export class Application {
|
||||
/**
|
||||
* Handles a mouse move event
|
||||
*/
|
||||
handleMousemove(event: MouseEvent): void {
|
||||
handleMousemove(event: MouseEvent) {
|
||||
this.mousePosition = new Vector(event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal on focus handler
|
||||
*/
|
||||
onFocus(): void {
|
||||
onFocus() {
|
||||
this.focused = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal blur handler
|
||||
*/
|
||||
onBlur(): void {
|
||||
onBlur() {
|
||||
this.focused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the app is currently visible
|
||||
*/
|
||||
isRenderable(): boolean {
|
||||
isRenderable() {
|
||||
return !this.applicationPaused && this.pageVisible;
|
||||
}
|
||||
|
||||
onAppRenderableStateChanged(renderable: boolean): void {
|
||||
onAppRenderableStateChanged(renderable: boolean) {
|
||||
logger.log("Application renderable:", renderable);
|
||||
window.focus();
|
||||
const currentState: any = this.stateMgr.getCurrentState();
|
||||
const currentState = this.stateMgr.getCurrentState();
|
||||
if (!renderable) {
|
||||
if (currentState) {
|
||||
currentState.onAppPause();
|
||||
@ -286,11 +286,11 @@ export class Application {
|
||||
this.sound.onPageRenderableStateChanged(renderable);
|
||||
}
|
||||
|
||||
onAppPlayingStateChanged(playing: boolean): void {
|
||||
onAppPlayingStateChanged(playing: boolean) {
|
||||
try {
|
||||
this.adProvider.setPlayStatus(playing);
|
||||
}
|
||||
catch (ex: any) {
|
||||
catch (ex) {
|
||||
console.warn("Play status changed");
|
||||
}
|
||||
}
|
||||
@ -298,10 +298,9 @@ export class Application {
|
||||
/**
|
||||
* Internal before-unload handler
|
||||
*/
|
||||
onBeforeUnload(event: BeforeUnloadEvent): void {
|
||||
onBeforeUnload(event) {
|
||||
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_STANDALONE) {
|
||||
// Need to show a "Are you sure you want to exit"
|
||||
@ -310,7 +309,6 @@ export class Application {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitializes the application
|
||||
*/
|
||||
@ -321,12 +319,12 @@ export class Application {
|
||||
/**
|
||||
* Background frame update callback
|
||||
*/
|
||||
onBackgroundFrame(dt: number): void {
|
||||
onBackgroundFrame(dt: number) {
|
||||
if (this.isRenderable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentState: any = this.stateMgr.getCurrentState();
|
||||
const currentState = this.stateMgr.getCurrentState();
|
||||
if (currentState) {
|
||||
currentState.onBackgroundTick(dt);
|
||||
}
|
||||
@ -335,12 +333,12 @@ export class Application {
|
||||
/**
|
||||
* Frame update callback
|
||||
*/
|
||||
onFrameEmitted(dt: number): void {
|
||||
onFrameEmitted(dt: number) {
|
||||
if (!this.isRenderable()) {
|
||||
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!)
|
||||
if (!this.lastResizeCheck || time - this.lastResizeCheck > 1000) {
|
||||
@ -348,7 +346,7 @@ export class Application {
|
||||
this.lastResizeCheck = time;
|
||||
}
|
||||
|
||||
const currentState: any = this.stateMgr.getCurrentState();
|
||||
const currentState = this.stateMgr.getCurrentState();
|
||||
this.trackedIsPlaying.set(currentState && currentState.getIsIngame());
|
||||
if (currentState) {
|
||||
currentState.onRender(dt);
|
||||
@ -358,19 +356,19 @@ export class Application {
|
||||
/**
|
||||
* 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 h = window.innerHeight;
|
||||
if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) {
|
||||
this.screenWidth = w;
|
||||
this.screenHeight = h;
|
||||
const currentState: GameState = this.stateMgr.getCurrentState();
|
||||
const currentState = this.stateMgr.getCurrentState();
|
||||
if (currentState) {
|
||||
currentState.onResized(this.screenWidth, this.screenHeight);
|
||||
}
|
||||
|
||||
const scale: number = this.getEffectiveUiScale();
|
||||
waitNextFrame().then((): any => document.documentElement.style.setProperty("--ui-scale", `${scale}`));
|
||||
const scale = this.getEffectiveUiScale();
|
||||
waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", `${scale}`));
|
||||
window.focus();
|
||||
}
|
||||
}
|
||||
@ -385,7 +383,7 @@ export class Application {
|
||||
/**
|
||||
* Callback after ui scale has changed
|
||||
*/
|
||||
updateAfterUiScaleChanged(): void {
|
||||
updateAfterUiScaleChanged() {
|
||||
this.checkResize(true);
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ import { Signal } from "./signal";
|
||||
// @ts-ignore
|
||||
import BackgroundAnimationFrameEmitterWorker from "../webworkers/background_animation_frame_emittter.worker";
|
||||
import { createLogger } from "./logging";
|
||||
const logger: any = createLogger("animation_frame");
|
||||
const maxDtMs: any = 1000;
|
||||
const resetDtMs: any = 16;
|
||||
const logger = createLogger("animation_frame");
|
||||
const maxDtMs = 1000;
|
||||
const resetDtMs = 16;
|
||||
export class AnimationFrame {
|
||||
public frameEmitted = new Signal();
|
||||
public bgFrameEmitted = new Signal();
|
||||
@ -14,33 +14,33 @@ export class AnimationFrame {
|
||||
public backgroundWorker = new BackgroundAnimationFrameEmitterWorker();
|
||||
|
||||
constructor() {
|
||||
this.backgroundWorker.addEventListener("error", (err: any): any => {
|
||||
this.backgroundWorker.addEventListener("error", err => {
|
||||
logger.error("Error in background fps worker:", err);
|
||||
});
|
||||
this.backgroundWorker.addEventListener("message", this.handleBackgroundTick.bind(this));
|
||||
}
|
||||
handleBackgroundTick(): any {
|
||||
const time: any = performance.now();
|
||||
let dt: any = time - this.bgLastTime;
|
||||
handleBackgroundTick() {
|
||||
const time = performance.now();
|
||||
let dt = time - this.bgLastTime;
|
||||
if (dt > maxDtMs) {
|
||||
dt = resetDtMs;
|
||||
}
|
||||
this.bgFrameEmitted.dispatch(dt);
|
||||
this.bgLastTime = time;
|
||||
}
|
||||
start(): any {
|
||||
start() {
|
||||
assertAlways(window.requestAnimationFrame, "requestAnimationFrame is not supported!");
|
||||
this.handleAnimationFrame();
|
||||
}
|
||||
handleAnimationFrame(time: any): any {
|
||||
let dt: any = time - this.lastTime;
|
||||
handleAnimationFrame(time) {
|
||||
let dt = time - this.lastTime;
|
||||
if (dt > maxDtMs) {
|
||||
dt = resetDtMs;
|
||||
}
|
||||
try {
|
||||
this.frameEmitted.dispatch(dt);
|
||||
}
|
||||
catch (ex: any) {
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
this.lastTime = time;
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { createLogger } from "./logging";
|
||||
const logger: any = createLogger("assert");
|
||||
let assertionErrorShown: any = false;
|
||||
function initAssert(): any {
|
||||
const logger = createLogger("assert");
|
||||
let assertionErrorShown = false;
|
||||
function initAssert() {
|
||||
/**
|
||||
* Expects a given condition to be true
|
||||
* @param {} failureMessage
|
||||
*/
|
||||
// @ts-ignore
|
||||
window.assert = function (condition: Boolean, ...failureMessage: ...String): any {
|
||||
window.assert = function (condition: Boolean, ...failureMessage: ...String) {
|
||||
if (!condition) {
|
||||
logger.error("assertion failed:", ...failureMessage);
|
||||
if (!assertionErrorShown) {
|
||||
|
@ -2,15 +2,15 @@
|
||||
import CompressionWorker from "../webworkers/compression.worker";
|
||||
import { createLogger } from "./logging";
|
||||
import { round2Digits } from "./utils";
|
||||
const logger: any = createLogger("async_compression");
|
||||
export let compressionPrefix: any = String.fromCodePoint(1);
|
||||
function checkCryptPrefix(prefix: any): any {
|
||||
const logger = createLogger("async_compression");
|
||||
export let compressionPrefix = String.fromCodePoint(1);
|
||||
function checkCryptPrefix(prefix) {
|
||||
try {
|
||||
window.localStorage.setItem("prefix_test", prefix);
|
||||
window.localStorage.removeItem("prefix_test");
|
||||
return true;
|
||||
}
|
||||
catch (ex: any) {
|
||||
catch (ex) {
|
||||
logger.warn("Prefix '" + prefix + "' not available");
|
||||
return false;
|
||||
}
|
||||
@ -36,27 +36,27 @@ class AsynCompression {
|
||||
} = {};
|
||||
|
||||
constructor() {
|
||||
this.worker.addEventListener("message", (event: any): any => {
|
||||
const { jobId, result }: any = event.data;
|
||||
const jobData: any = this.currentJobs[jobId];
|
||||
this.worker.addEventListener("message", event => {
|
||||
const { jobId, result } = event.data;
|
||||
const jobData = this.currentJobs[jobId];
|
||||
if (!jobData) {
|
||||
logger.error("Failed to resolve job result, job id", jobId, "is not known");
|
||||
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");
|
||||
const resolver: any = jobData.resolver;
|
||||
const resolver = jobData.resolver;
|
||||
delete this.currentJobs[jobId];
|
||||
resolver(result);
|
||||
});
|
||||
this.worker.addEventListener("error", (err: any): any => {
|
||||
this.worker.addEventListener("error", err => {
|
||||
logger.error("Got error from webworker:", err, "aborting all jobs");
|
||||
const failureCalls: any = [];
|
||||
for (const jobId: any in this.currentJobs) {
|
||||
const failureCalls = [];
|
||||
for (const jobId in this.currentJobs) {
|
||||
failureCalls.push(this.currentJobs[jobId].errorHandler);
|
||||
}
|
||||
this.currentJobs = {};
|
||||
for (let i: any = 0; i < failureCalls.length; ++i) {
|
||||
for (let i = 0; i < failureCalls.length; ++i) {
|
||||
failureCalls[i](err);
|
||||
}
|
||||
});
|
||||
@ -64,7 +64,7 @@ class AsynCompression {
|
||||
/**
|
||||
* Compresses any object
|
||||
*/
|
||||
compressObjectAsync(obj: any): any {
|
||||
compressObjectAsync(obj: any) {
|
||||
logger.log("Compressing object async (optimized)");
|
||||
return this.internalQueueJob("compressObject", {
|
||||
obj,
|
||||
@ -76,9 +76,9 @@ class AsynCompression {
|
||||
* {}
|
||||
*/
|
||||
internalQueueJob(job: string, data: any): Promise<any> {
|
||||
const jobId: any = ++this.currentJobId;
|
||||
return new Promise((resolve: any, reject: any): any => {
|
||||
const errorHandler: any = (err: any): any => {
|
||||
const jobId = ++this.currentJobId;
|
||||
return new Promise((resolve, reject) => {
|
||||
const errorHandler = err => {
|
||||
logger.error("Failed to compress job", jobId, ":", err);
|
||||
reject(err);
|
||||
};
|
||||
@ -92,4 +92,4 @@ class AsynCompression {
|
||||
});
|
||||
}
|
||||
}
|
||||
export const asyncCompressor: any = new AsynCompression();
|
||||
export const asyncCompressor = new AsynCompression();
|
||||
|
@ -34,7 +34,7 @@ export class AtlasDefinition {
|
||||
|
||||
constructor({ frames, meta }) {
|
||||
}
|
||||
getFullSourcePath(): any {
|
||||
getFullSourcePath() {
|
||||
return this.sourceFileName;
|
||||
}
|
||||
}
|
||||
@ -42,6 +42,6 @@ export const atlasFiles: AtlasDefinition[] = require
|
||||
// @ts-ignore
|
||||
.context("../../../res_built/atlas/", false, /.*\.json/i)
|
||||
.keys()
|
||||
.map((f: any): any => f.replace(/^\.\//gi, ""))
|
||||
.map((f: any): any => require("../../../res_built/atlas/" + f))
|
||||
.map((data: any): any => new AtlasDefinition(data));
|
||||
.map(f => f.replace(/^\.\//gi, ""))
|
||||
.map(f => require("../../../res_built/atlas/" + f))
|
||||
.map(data => new AtlasDefinition(data));
|
||||
|
@ -10,18 +10,18 @@ import { Loader } from "./loader";
|
||||
import { createLogger } from "./logging";
|
||||
import { Signal } from "./signal";
|
||||
import { clamp, getLogoSprite, timeoutPromise } from "./utils";
|
||||
const logger: any = createLogger("background_loader");
|
||||
const MAIN_MENU_ASSETS: any = {
|
||||
const logger = createLogger("background_loader");
|
||||
const MAIN_MENU_ASSETS = {
|
||||
sprites: [getLogoSprite()],
|
||||
sounds: [SOUNDS.uiClick, SOUNDS.uiError, SOUNDS.dialogError, SOUNDS.dialogOk],
|
||||
atlas: [],
|
||||
css: [],
|
||||
};
|
||||
const INGAME_ASSETS: any = {
|
||||
const INGAME_ASSETS = {
|
||||
sprites: [],
|
||||
sounds: [
|
||||
...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,
|
||||
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))];
|
||||
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,
|
||||
// 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,
|
||||
};
|
||||
export class BackgroundResourcesLoader {
|
||||
@ -44,19 +44,19 @@ export class BackgroundResourcesLoader {
|
||||
|
||||
constructor(app) {
|
||||
}
|
||||
getMainMenuPromise(): any {
|
||||
getMainMenuPromise() {
|
||||
if (this.mainMenuPromise) {
|
||||
return this.mainMenuPromise;
|
||||
}
|
||||
logger.log("⏰ Loading main menu assets");
|
||||
return (this.mainMenuPromise = this.loadAssets(MAIN_MENU_ASSETS));
|
||||
}
|
||||
getIngamePromise(): any {
|
||||
getIngamePromise() {
|
||||
if (this.ingamePromise) {
|
||||
return this.ingamePromise;
|
||||
}
|
||||
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);
|
||||
}
|
||||
async loadAssets({ sprites, sounds, atlas, css }: {
|
||||
@ -64,50 +64,50 @@ export class BackgroundResourcesLoader {
|
||||
sounds: string[];
|
||||
atlas: AtlasDefinition[];
|
||||
css: string[];
|
||||
}): any {
|
||||
}) {
|
||||
let promiseFunctions: ((progressHandler: (progress: number) => void) => Promise<void>)[] = [];
|
||||
// CSS
|
||||
for (let i: any = 0; i < css.length; ++i) {
|
||||
promiseFunctions.push((progress: any): any => timeoutPromise(this.internalPreloadCss(css[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch((err: any): any => {
|
||||
for (let i = 0; i < css.length; ++i) {
|
||||
promiseFunctions.push(progress => timeoutPromise(this.internalPreloadCss(css[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch(err => {
|
||||
logger.error("Failed to load css:", css[i], err);
|
||||
throw new Error("HUD Stylesheet " + css[i] + " failed to load: " + err);
|
||||
}));
|
||||
}
|
||||
// ATLAS FILES
|
||||
for (let i: any = 0; i < atlas.length; ++i) {
|
||||
promiseFunctions.push((progress: any): any => timeoutPromise(Loader.preloadAtlas(atlas[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch((err: any): any => {
|
||||
for (let i = 0; i < atlas.length; ++i) {
|
||||
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);
|
||||
throw new Error("Atlas " + atlas[i].sourceFileName + " failed to load: " + err);
|
||||
}));
|
||||
}
|
||||
// HUD Sprites
|
||||
for (let i: any = 0; i < sprites.length; ++i) {
|
||||
promiseFunctions.push((progress: any): any => timeoutPromise(Loader.preloadCSSSprite(sprites[i], progress), LOADER_TIMEOUT_PER_RESOURCE).catch((err: any): any => {
|
||||
for (let i = 0; i < sprites.length; ++i) {
|
||||
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);
|
||||
throw new Error("HUD Sprite " + sprites[i] + " failed to load: " + err);
|
||||
}));
|
||||
}
|
||||
// SFX & Music
|
||||
for (let i: any = 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 => {
|
||||
for (let i = 0; i < sounds.length; ++i) {
|
||||
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);
|
||||
}));
|
||||
}
|
||||
const originalAmount: any = promiseFunctions.length;
|
||||
const start: any = performance.now();
|
||||
const originalAmount = promiseFunctions.length;
|
||||
const start = performance.now();
|
||||
logger.log("⏰ Preloading", originalAmount, "assets");
|
||||
let progress: any = 0;
|
||||
let progress = 0;
|
||||
this.resourceStateChangedSignal.dispatch({ progress });
|
||||
let promises: any = [];
|
||||
for (let i: any = 0; i < promiseFunctions.length; i++) {
|
||||
let lastIndividualProgress: any = 0;
|
||||
const progressHandler: any = (individualProgress: any): any => {
|
||||
const delta: any = clamp(individualProgress) - lastIndividualProgress;
|
||||
let promises = [];
|
||||
for (let i = 0; i < promiseFunctions.length; i++) {
|
||||
let lastIndividualProgress = 0;
|
||||
const progressHandler = individualProgress => {
|
||||
const delta = clamp(individualProgress) - lastIndividualProgress;
|
||||
lastIndividualProgress = clamp(individualProgress);
|
||||
progress += delta / originalAmount;
|
||||
this.resourceStateChangedSignal.dispatch({ progress });
|
||||
};
|
||||
promises.push(promiseFunctions[i](progressHandler).then((): any => {
|
||||
promises.push(promiseFunctions[i](progressHandler).then(() => {
|
||||
progressHandler(1);
|
||||
}));
|
||||
}
|
||||
@ -117,28 +117,28 @@ export class BackgroundResourcesLoader {
|
||||
/**
|
||||
* 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) {
|
||||
dialogs
|
||||
.showWarning(T.dialogs.resourceLoadFailed.title, T.dialogs.resourceLoadFailed.descSteamDemo + "<br>" + err, ["retry"])
|
||||
.retry.add((): any => window.location.reload());
|
||||
.retry.add(() => window.location.reload());
|
||||
}
|
||||
else {
|
||||
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>`) +
|
||||
"<br>" +
|
||||
err, ["retry"])
|
||||
.retry.add((): any => window.location.reload());
|
||||
.retry.add(() => window.location.reload());
|
||||
}
|
||||
}
|
||||
preloadWithProgress(src: any, progressHandler: any): any {
|
||||
return new Promise((resolve: any, reject: any): any => {
|
||||
const xhr: any = new XMLHttpRequest();
|
||||
let notifiedNotComputable: any = false;
|
||||
const fullUrl: any = cachebust(src);
|
||||
preloadWithProgress(src, progressHandler) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
let notifiedNotComputable = false;
|
||||
const fullUrl = cachebust(src);
|
||||
xhr.open("GET", fullUrl, true);
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.onprogress = function (ev: any): any {
|
||||
xhr.onprogress = function (ev) {
|
||||
if (ev.lengthComputable) {
|
||||
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/)) {
|
||||
reject(fullUrl + ": " + xhr.status + " " + xhr.statusText);
|
||||
}
|
||||
@ -166,22 +166,22 @@ export class BackgroundResourcesLoader {
|
||||
if (!notifiedNotComputable) {
|
||||
progressHandler(1);
|
||||
}
|
||||
const options: any = {};
|
||||
const headers: any = xhr.getAllResponseHeaders();
|
||||
const contentType: any = headers.match(/^Content-Type:\s*(.*?)$/im);
|
||||
const options = {};
|
||||
const headers = xhr.getAllResponseHeaders();
|
||||
const contentType = headers.match(/^Content-Type:\s*(.*?)$/im);
|
||||
if (contentType && contentType[1]) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
internalPreloadCss(src: any, progressHandler: any): any {
|
||||
return this.preloadWithProgress(src, progressHandler).then((blobSrc: any): any => {
|
||||
var styleElement: any = document.createElement("link");
|
||||
internalPreloadCss(src, progressHandler) {
|
||||
return this.preloadWithProgress(src, progressHandler).then(blobSrc => {
|
||||
var styleElement = document.createElement("link");
|
||||
styleElement.href = blobSrc;
|
||||
styleElement.rel = "stylesheet";
|
||||
styleElement.setAttribute("media", "all");
|
||||
|
@ -8,8 +8,8 @@ export type CacheEntry = {
|
||||
lastUse: number;
|
||||
};
|
||||
|
||||
const logger: any = createLogger("buffers");
|
||||
const bufferGcDurationSeconds: any = 0.5;
|
||||
const logger = createLogger("buffers");
|
||||
const bufferGcDurationSeconds = 0.5;
|
||||
export class BufferMaintainer {
|
||||
public root = root;
|
||||
public cache: Map<string, Map<string, CacheEntry>> = new Map();
|
||||
@ -22,17 +22,17 @@ export class BufferMaintainer {
|
||||
/**
|
||||
* Returns the buffer stats
|
||||
*/
|
||||
getStats(): any {
|
||||
let stats: any = {
|
||||
getStats() {
|
||||
let stats = {
|
||||
rootKeys: 0,
|
||||
subKeys: 0,
|
||||
vramBytes: 0,
|
||||
};
|
||||
this.cache.forEach((subCache: any, key: any): any => {
|
||||
this.cache.forEach((subCache, key) => {
|
||||
++stats.rootKeys;
|
||||
subCache.forEach((cacheEntry: any, subKey: any): any => {
|
||||
subCache.forEach((cacheEntry, subKey) => {
|
||||
++stats.subKeys;
|
||||
const canvas: any = cacheEntry.canvas;
|
||||
const canvas = cacheEntry.canvas;
|
||||
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
|
||||
* for a few iterations
|
||||
*/
|
||||
garbargeCollect(): any {
|
||||
let totalKeys: any = 0;
|
||||
let deletedKeys: any = 0;
|
||||
const minIteration: any = this.iterationIndex;
|
||||
this.cache.forEach((subCache: any, key: any): any => {
|
||||
let unusedSubKeys: any = [];
|
||||
garbargeCollect() {
|
||||
let totalKeys = 0;
|
||||
let deletedKeys = 0;
|
||||
const minIteration = this.iterationIndex;
|
||||
this.cache.forEach((subCache, key) => {
|
||||
let unusedSubKeys = [];
|
||||
// Filter sub cache
|
||||
subCache.forEach((cacheEntry: any, subKey: any): any => {
|
||||
subCache.forEach((cacheEntry, subKey) => {
|
||||
if (cacheEntry.lastUse < minIteration ||
|
||||
// @ts-ignore
|
||||
cacheEntry.canvas._contextLost) {
|
||||
@ -62,7 +62,7 @@ export class BufferMaintainer {
|
||||
}
|
||||
});
|
||||
// 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]);
|
||||
}
|
||||
});
|
||||
@ -91,8 +91,8 @@ export class BufferMaintainer {
|
||||
// }
|
||||
++this.iterationIndex;
|
||||
}
|
||||
update(): any {
|
||||
const now: any = this.root.time.realtimeNow();
|
||||
update() {
|
||||
const now = this.root.time.realtimeNow();
|
||||
if (now - this.lastIteration > bufferGcDurationSeconds) {
|
||||
this.lastIteration = now;
|
||||
this.garbargeCollect();
|
||||
@ -112,21 +112,21 @@ export class BufferMaintainer {
|
||||
additionalParams: object=;
|
||||
}): HTMLCanvasElement {
|
||||
// First, create parent key
|
||||
let parent: any = this.cache.get(key);
|
||||
let parent = this.cache.get(key);
|
||||
if (!parent) {
|
||||
parent = new Map();
|
||||
this.cache.set(key, parent);
|
||||
}
|
||||
// Now search for sub key
|
||||
const cacheHit: any = parent.get(subKey);
|
||||
const cacheHit = parent.get(subKey);
|
||||
if (cacheHit) {
|
||||
cacheHit.lastUse = this.iterationIndex;
|
||||
return cacheHit.canvas;
|
||||
}
|
||||
// Need to generate new buffer
|
||||
const effectiveWidth: any = w * dpi;
|
||||
const effectiveHeight: any = h * dpi;
|
||||
const [canvas, context]: any = makeOffscreenBuffer(effectiveWidth, effectiveHeight, {
|
||||
const effectiveWidth = w * dpi;
|
||||
const effectiveHeight = h * dpi;
|
||||
const [canvas, context] = makeOffscreenBuffer(effectiveWidth, effectiveHeight, {
|
||||
reusable: true,
|
||||
label: "buffer-" + key + "/" + subKey,
|
||||
smooth: true,
|
||||
@ -147,12 +147,12 @@ export class BufferMaintainer {
|
||||
key: string;
|
||||
subKey: string;
|
||||
}): ?HTMLCanvasElement {
|
||||
let parent: any = this.cache.get(key);
|
||||
let parent = this.cache.get(key);
|
||||
if (!parent) {
|
||||
return null;
|
||||
}
|
||||
// Now search for sub key
|
||||
const cacheHit: any = parent.get(subKey);
|
||||
const cacheHit = parent.get(subKey);
|
||||
if (cacheHit) {
|
||||
return cacheHit.canvas;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { globalConfig } from "./config";
|
||||
import { fastArrayDelete } from "./utils";
|
||||
import { createLogger } from "./logging";
|
||||
const logger: any = createLogger("buffer_utils");
|
||||
const logger = createLogger("buffer_utils");
|
||||
/**
|
||||
* Enables images smoothing on a context
|
||||
*/
|
||||
export function enableImageSmoothing(context: CanvasRenderingContext2D): any {
|
||||
export function enableImageSmoothing(context: CanvasRenderingContext2D) {
|
||||
context.imageSmoothingEnabled = true;
|
||||
context.webkitImageSmoothingEnabled = true;
|
||||
// @ts-ignore
|
||||
@ -14,7 +14,7 @@ export function enableImageSmoothing(context: CanvasRenderingContext2D): any {
|
||||
/**
|
||||
* Disables image smoothing on a context
|
||||
*/
|
||||
export function disableImageSmoothing(context: CanvasRenderingContext2D): any {
|
||||
export function disableImageSmoothing(context: CanvasRenderingContext2D) {
|
||||
context.imageSmoothingEnabled = false;
|
||||
context.webkitImageSmoothingEnabled = false;
|
||||
}
|
||||
@ -31,14 +31,14 @@ const freeCanvasBuckets: Map<number, Array<CanvasCacheEntry>> = new Map();
|
||||
/**
|
||||
* Track statistics
|
||||
*/
|
||||
const stats: any = {
|
||||
const stats = {
|
||||
vramUsage: 0,
|
||||
backlogVramUsage: 0,
|
||||
bufferCount: 0,
|
||||
numReused: 0,
|
||||
numCreated: 0,
|
||||
};
|
||||
export function getBufferVramUsageBytes(canvas: HTMLCanvasElement): any {
|
||||
export function getBufferVramUsageBytes(canvas: HTMLCanvasElement) {
|
||||
assert(canvas, "no canvas given");
|
||||
assert(Number.isFinite(canvas.width), "bad canvas width: " + canvas.width);
|
||||
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
|
||||
*/
|
||||
export function getBufferStats(): any {
|
||||
let numBuffersFree: any = 0;
|
||||
freeCanvasBuckets.forEach((bucket: any): any => {
|
||||
export function getBufferStats() {
|
||||
let numBuffersFree = 0;
|
||||
freeCanvasBuckets.forEach(bucket => {
|
||||
numBuffersFree += bucket.length;
|
||||
});
|
||||
return {
|
||||
@ -61,10 +61,10 @@ export function getBufferStats(): any {
|
||||
/**
|
||||
* Clears the backlog buffers if they grew too much
|
||||
*/
|
||||
export function clearBufferBacklog(): any {
|
||||
freeCanvasBuckets.forEach((bucket: any): any => {
|
||||
export function clearBufferBacklog() {
|
||||
freeCanvasBuckets.forEach(bucket => {
|
||||
while (bucket.length > 500) {
|
||||
const entry: any = bucket[bucket.length - 1];
|
||||
const entry = bucket[bucket.length - 1];
|
||||
stats.backlogVramUsage -= getBufferVramUsageBytes(entry.canvas);
|
||||
delete entry.canvas;
|
||||
delete entry.context;
|
||||
@ -76,7 +76,7 @@ export function clearBufferBacklog(): any {
|
||||
* 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,
|
||||
CanvasRenderingContext2D
|
||||
] {
|
||||
@ -89,18 +89,18 @@ export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusa
|
||||
w = Math.max(1, w);
|
||||
h = Math.max(1, h);
|
||||
}
|
||||
const recommendedSize: any = 1024 * 1024;
|
||||
const recommendedSize = 1024 * 1024;
|
||||
if (w * h > recommendedSize) {
|
||||
logger.warn("Creating huge buffer:", w, "x", h, "with label", label);
|
||||
}
|
||||
w = Math.floor(w);
|
||||
h = Math.floor(h);
|
||||
let canvas: any = null;
|
||||
let context: any = null;
|
||||
let canvas = null;
|
||||
let context = null;
|
||||
// Ok, search in cache first
|
||||
const bucket: any = freeCanvasBuckets.get(w * h) || [];
|
||||
for (let i: any = 0; i < bucket.length; ++i) {
|
||||
const { canvas: useableCanvas, context: useableContext }: any = bucket[i];
|
||||
const bucket = freeCanvasBuckets.get(w * h) || [];
|
||||
for (let i = 0; i < bucket.length; ++i) {
|
||||
const { canvas: useableCanvas, context: useableContext } = bucket[i];
|
||||
if (useableCanvas.width === w && useableCanvas.height === h) {
|
||||
// Ok we found one
|
||||
canvas = useableCanvas;
|
||||
@ -126,12 +126,12 @@ export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusa
|
||||
canvas.height = h;
|
||||
// Initial state
|
||||
context.save();
|
||||
canvas.addEventListener("webglcontextlost", (): any => {
|
||||
canvas.addEventListener("webglcontextlost", () => {
|
||||
console.warn("canvas::webglcontextlost", canvas);
|
||||
// @ts-ignore
|
||||
canvas._contextLost = true;
|
||||
});
|
||||
canvas.addEventListener("contextlost", (): any => {
|
||||
canvas.addEventListener("contextlost", () => {
|
||||
console.warn("canvas::contextlost", canvas);
|
||||
// @ts-ignore
|
||||
canvas._contextLost = true;
|
||||
@ -155,20 +155,20 @@ export function makeOffscreenBuffer(w: Number, h: Number, { smooth = true, reusa
|
||||
/**
|
||||
* Frees a canvas
|
||||
*/
|
||||
export function registerCanvas(canvas: HTMLCanvasElement, context: any): any {
|
||||
export function registerCanvas(canvas: HTMLCanvasElement, context) {
|
||||
registeredCanvas.push({ canvas, context });
|
||||
stats.bufferCount += 1;
|
||||
const bytesUsed: any = getBufferVramUsageBytes(canvas);
|
||||
const bytesUsed = getBufferVramUsageBytes(canvas);
|
||||
stats.vramUsage += bytesUsed;
|
||||
}
|
||||
/**
|
||||
* Frees a canvas
|
||||
*/
|
||||
export function freeCanvas(canvas: HTMLCanvasElement): any {
|
||||
export function freeCanvas(canvas: HTMLCanvasElement) {
|
||||
assert(canvas, "Canvas is empty");
|
||||
let index: any = -1;
|
||||
let data: any = null;
|
||||
for (let i: any = 0; i < registeredCanvas.length; ++i) {
|
||||
let index = -1;
|
||||
let data = null;
|
||||
for (let i = 0; i < registeredCanvas.length; ++i) {
|
||||
if (registeredCanvas[i].canvas === canvas) {
|
||||
index = i;
|
||||
data = registeredCanvas[i];
|
||||
@ -180,8 +180,8 @@ export function freeCanvas(canvas: HTMLCanvasElement): any {
|
||||
return;
|
||||
}
|
||||
fastArrayDelete(registeredCanvas, index);
|
||||
const key: any = canvas.width * canvas.height;
|
||||
const bucket: any = freeCanvasBuckets.get(key);
|
||||
const key = canvas.width * canvas.height;
|
||||
const bucket = freeCanvasBuckets.get(key);
|
||||
if (bucket) {
|
||||
bucket.push(data);
|
||||
}
|
||||
@ -189,7 +189,7 @@ export function freeCanvas(canvas: HTMLCanvasElement): any {
|
||||
freeCanvasBuckets.set(key, [data]);
|
||||
}
|
||||
stats.bufferCount -= 1;
|
||||
const bytesUsed: any = getBufferVramUsageBytes(canvas);
|
||||
const bytesUsed = getBufferVramUsageBytes(canvas);
|
||||
stats.vramUsage -= bytesUsed;
|
||||
stats.backlogVramUsage += bytesUsed;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 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) {
|
||||
return "/v/" + G_BUILD_COMMIT_HASH + "/" + path;
|
||||
}
|
||||
|
@ -5,17 +5,17 @@ import { Vector } from "./vector";
|
||||
import { IS_MOBILE, SUPPORT_TOUCH } from "./config";
|
||||
import { SOUNDS } from "../platform/sound";
|
||||
import { GLOBAL_APP } from "./globals";
|
||||
const logger: any = createLogger("click_detector");
|
||||
export const MAX_MOVE_DISTANCE_PX: any = IS_MOBILE ? 20 : 80;
|
||||
const logger = createLogger("click_detector");
|
||||
export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 80;
|
||||
// For debugging
|
||||
const registerClickDetectors: any = G_IS_DEV && true;
|
||||
const registerClickDetectors = G_IS_DEV && true;
|
||||
if (registerClickDetectors) {
|
||||
window.activeClickDetectors = [];
|
||||
}
|
||||
// Store active click detectors so we can cancel them
|
||||
const ongoingClickDetectors: Array<ClickDetector> = [];
|
||||
// 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,
|
||||
};
|
||||
export type ClickDetectorConstructorArgs = {
|
||||
@ -59,10 +59,10 @@ export class ClickDetector {
|
||||
/**
|
||||
* Cleans up all event listeners of this detector
|
||||
*/
|
||||
cleanup(): any {
|
||||
cleanup() {
|
||||
if (this.element) {
|
||||
if (registerClickDetectors) {
|
||||
const index: any = window.activeClickDetectors.indexOf(this);
|
||||
const index = window.activeClickDetectors.indexOf(this);
|
||||
if (index < 0) {
|
||||
logger.error("Click detector cleanup but is not active");
|
||||
}
|
||||
@ -70,7 +70,7 @@ export class ClickDetector {
|
||||
window.activeClickDetectors.splice(index, 1);
|
||||
}
|
||||
}
|
||||
const options: any = this.internalGetEventListenerOptions();
|
||||
const options = this.internalGetEventListenerOptions();
|
||||
if (SUPPORT_TOUCH) {
|
||||
this.element.removeEventListener("touchstart", this.handlerTouchStart, options);
|
||||
this.element.removeEventListener("touchend", this.handlerTouchEnd, options);
|
||||
@ -97,14 +97,14 @@ export class ClickDetector {
|
||||
}
|
||||
}
|
||||
// INTERNAL METHODS
|
||||
internalPreventClick(event: Event): any {
|
||||
internalPreventClick(event: Event) {
|
||||
window.focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
/**
|
||||
* Internal method to get the options to pass to an event listener
|
||||
*/
|
||||
internalGetEventListenerOptions(): any {
|
||||
internalGetEventListenerOptions() {
|
||||
return {
|
||||
capture: this.consumeEvents,
|
||||
passive: !this.preventDefault,
|
||||
@ -113,8 +113,8 @@ export class ClickDetector {
|
||||
/**
|
||||
* Binds the click detector to an element
|
||||
*/
|
||||
internalBindTo(element: HTMLElement): any {
|
||||
const options: any = this.internalGetEventListenerOptions();
|
||||
internalBindTo(element: HTMLElement) {
|
||||
const options = this.internalGetEventListenerOptions();
|
||||
this.handlerTouchStart = this.internalOnPointerDown.bind(this);
|
||||
this.handlerTouchEnd = this.internalOnPointerEnd.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.
|
||||
*/
|
||||
internalIsDomElementAttached(): any {
|
||||
internalIsDomElementAttached() {
|
||||
return this.element && document.documentElement.contains(this.element);
|
||||
}
|
||||
/**
|
||||
* 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) {
|
||||
// Already cleaned up
|
||||
return false;
|
||||
@ -191,7 +191,7 @@ export class ClickDetector {
|
||||
logger.warn("Got unexpected target touches:", event.targetTouches.length, "->", event.targetTouches);
|
||||
return new Vector(0, 0);
|
||||
}
|
||||
const touch: any = event.changedTouches[0];
|
||||
const touch = event.changedTouches[0];
|
||||
return new Vector(touch.clientX, touch.clientY);
|
||||
}
|
||||
if (event instanceof MouseEvent) {
|
||||
@ -203,7 +203,7 @@ export class ClickDetector {
|
||||
/**
|
||||
* Cacnels all ongoing events on this detector
|
||||
*/
|
||||
cancelOngoingEvents(): any {
|
||||
cancelOngoingEvents() {
|
||||
if (this.applyCssClass && this.element) {
|
||||
this.element.classList.remove(this.applyCssClass);
|
||||
}
|
||||
@ -215,15 +215,15 @@ export class ClickDetector {
|
||||
/**
|
||||
* Internal pointer down handler
|
||||
*/
|
||||
internalOnPointerDown(event: TouchEvent | MouseEvent): any {
|
||||
internalOnPointerDown(event: TouchEvent | MouseEvent) {
|
||||
window.focus();
|
||||
if (!this.internalEventPreHandler(event, 1)) {
|
||||
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) {
|
||||
const isRightClick: any = event.button === 2;
|
||||
const isRightClick = event.button === 2;
|
||||
if (isRightClick) {
|
||||
// Ignore right clicks
|
||||
this.rightClick.dispatch(position, event);
|
||||
@ -262,20 +262,20 @@ export class ClickDetector {
|
||||
/**
|
||||
* Internal pointer move handler
|
||||
*/
|
||||
internalOnPointerMove(event: TouchEvent | MouseEvent): any {
|
||||
internalOnPointerMove(event: TouchEvent | MouseEvent) {
|
||||
if (!this.internalEventPreHandler(event, 1)) {
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Internal pointer end handler
|
||||
*/
|
||||
internalOnPointerEnd(event: TouchEvent | MouseEvent): any {
|
||||
internalOnPointerEnd(event: TouchEvent | MouseEvent) {
|
||||
window.focus();
|
||||
if (!this.internalEventPreHandler(event, 0)) {
|
||||
return false;
|
||||
@ -285,25 +285,25 @@ export class ClickDetector {
|
||||
return false;
|
||||
}
|
||||
if (event instanceof MouseEvent) {
|
||||
const isRightClick: any = event.button === 2;
|
||||
const isRightClick = event.button === 2;
|
||||
if (isRightClick) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const index: any = ongoingClickDetectors.indexOf(this);
|
||||
const index = ongoingClickDetectors.indexOf(this);
|
||||
if (index < 0) {
|
||||
logger.warn("Got pointer end but click detector is not in pressed state");
|
||||
}
|
||||
else {
|
||||
fastArrayDelete(ongoingClickDetectors, index);
|
||||
}
|
||||
let dispatchClick: any = false;
|
||||
let dispatchClickPos: any = null;
|
||||
let dispatchClick = false;
|
||||
let dispatchClickPos = null;
|
||||
// Check for correct down position, otherwise must have pinched or so
|
||||
if (this.clickDownPosition) {
|
||||
|
||||
const pos: any = (this.constructor as typeof ClickDetector).extractPointerPosition(event);
|
||||
const distance: any = pos.distance(this.clickDownPosition);
|
||||
const pos = this.constructor as typeof ClickDetector).extractPointerPosition(event);
|
||||
const distance = pos.distance(this.clickDownPosition);
|
||||
if (!IS_MOBILE || distance <= this.maxDistance) {
|
||||
dispatchClick = true;
|
||||
dispatchClickPos = pos;
|
||||
@ -323,8 +323,8 @@ export class ClickDetector {
|
||||
this.touchend.dispatch(event);
|
||||
this.touchendSimple.dispatch();
|
||||
if (dispatchClick) {
|
||||
const detectors: any = ongoingClickDetectors.slice();
|
||||
for (let i: any = 0; i < detectors.length; ++i) {
|
||||
const detectors = ongoingClickDetectors.slice();
|
||||
for (let i = 0; i < detectors.length; ++i) {
|
||||
detectors[i].cancelOngoingEvents();
|
||||
}
|
||||
this.click.dispatch(dispatchClickPos, event);
|
||||
@ -335,7 +335,7 @@ export class ClickDetector {
|
||||
/**
|
||||
* Internal touch cancel handler
|
||||
*/
|
||||
internalOnTouchCancel(event: TouchEvent | MouseEvent): any {
|
||||
internalOnTouchCancel(event: TouchEvent | MouseEvent) {
|
||||
if (!this.internalEventPreHandler(event, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
/* typehints:start */
|
||||
import type { Application } from "../application";
|
||||
/* typehints:end */
|
||||
export const IS_DEBUG: any = G_IS_DEV &&
|
||||
export const IS_DEBUG = G_IS_DEV &&
|
||||
typeof window !== "undefined" &&
|
||||
window.location.port === "3005" &&
|
||||
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
|
||||
window.location.search.indexOf("nodebug") < 0;
|
||||
export const SUPPORT_TOUCH: any = false;
|
||||
const smoothCanvas: any = true;
|
||||
export const THIRDPARTY_URLS: any = {
|
||||
export const SUPPORT_TOUCH = false;
|
||||
const smoothCanvas = true;
|
||||
export const THIRDPARTY_URLS = {
|
||||
discord: "https://discord.gg/HN7EVzV",
|
||||
github: "https://github.com/tobspr-games/shapez.io",
|
||||
reddit: "https://www.reddit.com/r/shapezio",
|
||||
@ -25,13 +25,13 @@ export const THIRDPARTY_URLS: any = {
|
||||
},
|
||||
modBrowser: "https://shapez.mod.io/",
|
||||
};
|
||||
export function openStandaloneLink(app: Application, campaign: string): any {
|
||||
const discount: any = globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : "";
|
||||
const event: any = campaign + discount;
|
||||
export function openStandaloneLink(app: Application, campaign: string) {
|
||||
const discount = globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : "";
|
||||
const event = campaign + discount;
|
||||
app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneCampaignLink.replace("$campaign", event));
|
||||
app.gameAnalytics.noteMinor("g.stdlink." + event);
|
||||
}
|
||||
export const globalConfig: any = {
|
||||
export const globalConfig = {
|
||||
// Size of a single tile in Pixels.
|
||||
// NOTICE: Update webpack.production.config too!
|
||||
tileSize: 32,
|
||||
@ -106,7 +106,7 @@ export const globalConfig: any = {
|
||||
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
|
||||
globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5;
|
||||
globalConfig.mapChunkWorldSize = globalConfig.mapChunkSize * globalConfig.tileSize;
|
||||
|
@ -33,8 +33,8 @@ export function smoothenDpi(dpi: number): number {
|
||||
/**
|
||||
* Prepares a context for hihg dpi rendering
|
||||
*/
|
||||
export function prepareHighDPIContext(context: CanvasRenderingContext2D, smooth: any = true): any {
|
||||
const dpi: any = getDeviceDPI();
|
||||
export function prepareHighDPIContext(context: CanvasRenderingContext2D, smooth = true) {
|
||||
const dpi = getDeviceDPI();
|
||||
context.scale(dpi, dpi);
|
||||
if (smooth) {
|
||||
context.imageSmoothingEnabled = true;
|
||||
@ -50,12 +50,12 @@ export function prepareHighDPIContext(context: CanvasRenderingContext2D, smooth:
|
||||
/**
|
||||
* Resizes a high dpi canvas
|
||||
*/
|
||||
export function resizeHighDPICanvas(canvas: HTMLCanvasElement, w: number, h: number, smooth: any = true): any {
|
||||
const dpi: any = getDeviceDPI();
|
||||
const wNumber: any = Math.floor(w);
|
||||
const hNumber: any = Math.floor(h);
|
||||
const targetW: any = Math.floor(wNumber * dpi);
|
||||
const targetH: any = Math.floor(hNumber * dpi);
|
||||
export function resizeHighDPICanvas(canvas: HTMLCanvasElement, w: number, h: number, smooth = true) {
|
||||
const dpi = getDeviceDPI();
|
||||
const wNumber = Math.floor(w);
|
||||
const hNumber = Math.floor(h);
|
||||
const targetW = Math.floor(wNumber * dpi);
|
||||
const targetH = Math.floor(hNumber * dpi);
|
||||
if (targetW !== canvas.width || targetH !== canvas.height) {
|
||||
// console.log("Resize Canvas from", canvas.width, canvas.height, "to", targetW, targetH)
|
||||
canvas.width = targetW;
|
||||
@ -68,9 +68,9 @@ export function resizeHighDPICanvas(canvas: HTMLCanvasElement, w: number, h: num
|
||||
/**
|
||||
* Resizes a canvas
|
||||
*/
|
||||
export function resizeCanvas(canvas: HTMLCanvasElement, w: number, h: number, setStyle: any = true): any {
|
||||
const actualW: any = Math.ceil(w);
|
||||
const actualH: any = Math.ceil(h);
|
||||
export function resizeCanvas(canvas: HTMLCanvasElement, w: number, h: number, setStyle = true) {
|
||||
const actualW = Math.ceil(w);
|
||||
const actualH = Math.ceil(h);
|
||||
if (actualW !== canvas.width || actualH !== canvas.height) {
|
||||
canvas.width = actualW;
|
||||
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
|
||||
*/
|
||||
export function resizeCanvasAndClear(canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, w: number, h: number): any {
|
||||
const actualW: any = Math.ceil(w);
|
||||
const actualH: any = Math.ceil(h);
|
||||
export function resizeCanvasAndClear(canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, w: number, h: number) {
|
||||
const actualW = Math.ceil(w);
|
||||
const actualH = Math.ceil(h);
|
||||
if (actualW !== canvas.width || actualH !== canvas.height) {
|
||||
canvas.width = actualW;
|
||||
canvas.height = actualH;
|
||||
|
@ -4,9 +4,9 @@ export type DrawParameters = import("./draw_parameters").DrawParameters;
|
||||
import { globalConfig } from "./config";
|
||||
import { createLogger } from "./logging";
|
||||
import { Rectangle } from "./rectangle";
|
||||
const logger: any = createLogger("draw_utils");
|
||||
export function initDrawUtils(): any {
|
||||
CanvasRenderingContext2D.prototype.beginRoundedRect = function (x: any, y: any, w: any, h: any, r: any): any {
|
||||
const logger = createLogger("draw_utils");
|
||||
export function initDrawUtils() {
|
||||
CanvasRenderingContext2D.prototype.beginRoundedRect = function (x, y, w, h, r) {
|
||||
this.beginPath();
|
||||
if (r < 0.05) {
|
||||
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, x + w, y, r);
|
||||
};
|
||||
CanvasRenderingContext2D.prototype.beginCircle = function (x: any, y: any, r: any): any {
|
||||
CanvasRenderingContext2D.prototype.beginCircle = function (x, y, r) {
|
||||
this.beginPath();
|
||||
if (r < 0.05) {
|
||||
this.rect(x, y, 1, 1);
|
||||
@ -42,7 +42,7 @@ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offse
|
||||
size: number;
|
||||
offsetX: number=;
|
||||
offsetY: number=;
|
||||
}): any {
|
||||
}) {
|
||||
if (angle === 0) {
|
||||
sprite.drawCachedCentered(parameters, x + offsetX, y + offsetY, size);
|
||||
return;
|
||||
@ -53,7 +53,7 @@ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offse
|
||||
parameters.context.rotate(-angle);
|
||||
parameters.context.translate(-x, -y);
|
||||
}
|
||||
let warningsShown: any = 0;
|
||||
let warningsShown = 0;
|
||||
/**
|
||||
* Draws a sprite with clipping
|
||||
*/
|
||||
@ -66,9 +66,9 @@ export function drawSpriteClipped({ parameters, sprite, x, y, w, h, originalW, o
|
||||
h: number;
|
||||
originalW: number;
|
||||
originalH: number;
|
||||
}): any {
|
||||
const rect: any = new Rectangle(x, y, w, h);
|
||||
const intersection: any = rect.getIntersection(parameters.visibleRect);
|
||||
}) {
|
||||
const rect = new Rectangle(x, y, w, h);
|
||||
const intersection = rect.getIntersection(parameters.visibleRect);
|
||||
if (!intersection) {
|
||||
// Clipped
|
||||
if (++warningsShown % 200 === 1) {
|
||||
|
@ -4,25 +4,25 @@ export class ExplainedResult {
|
||||
|
||||
constructor(result = true, reason = null, additionalProps = {}) {
|
||||
// Copy additional props
|
||||
for (const key: any in additionalProps) {
|
||||
for (const key in additionalProps) {
|
||||
this[key] = additionalProps[key];
|
||||
}
|
||||
}
|
||||
isGood(): any {
|
||||
isGood() {
|
||||
return !!this.result;
|
||||
}
|
||||
isBad(): any {
|
||||
isBad() {
|
||||
return !this.result;
|
||||
}
|
||||
static good(): any {
|
||||
static good() {
|
||||
return new ExplainedResult(true);
|
||||
}
|
||||
static bad(reason: any, additionalProps: any): any {
|
||||
static bad(reason, additionalProps) {
|
||||
return new ExplainedResult(false, reason, additionalProps);
|
||||
}
|
||||
static requireAll(...args: any): any {
|
||||
for (let i: any = 0; i < args.length; ++i) {
|
||||
const subResult: any = args[i].call();
|
||||
static requireAll(...args) {
|
||||
for (let i = 0; i < args.length; ++i) {
|
||||
const subResult = args[i].call();
|
||||
if (!subResult.isGood()) {
|
||||
return subResult;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createLogger } from "./logging";
|
||||
const logger: any = createLogger("factory");
|
||||
const logger = createLogger("factory");
|
||||
// simple factory pattern
|
||||
export class Factory {
|
||||
public id = id;
|
||||
@ -9,12 +9,12 @@ export class Factory {
|
||||
|
||||
constructor(id) {
|
||||
}
|
||||
getId(): any {
|
||||
getId() {
|
||||
return this.id;
|
||||
}
|
||||
register(entry: any): any {
|
||||
register(entry) {
|
||||
// Extract id
|
||||
const id: any = entry.getId();
|
||||
const id = entry.getId();
|
||||
assert(id, "Factory: Invalid id for class: " + entry);
|
||||
// Check duplicates
|
||||
assert(!this.idToEntry[id], "Duplicate factory entry for " + id);
|
||||
@ -35,7 +35,7 @@ export class Factory {
|
||||
* {}
|
||||
*/
|
||||
findById(id: string): object {
|
||||
const entry: any = this.idToEntry[id];
|
||||
const entry = this.idToEntry[id];
|
||||
if (!entry) {
|
||||
logger.error("Object with id", id, "is not registered on factory", this.id, "!");
|
||||
assert(false, "Factory: Object with id '" + id + "' is not registered!");
|
||||
|
@ -9,7 +9,7 @@ import { InputReceiver } from "./input_receiver";
|
||||
import { waitNextFrame } from "./utils";
|
||||
import { RequestChannel } from "./request_channel";
|
||||
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
|
||||
*/
|
||||
@ -46,7 +46,7 @@ export class GameState {
|
||||
/**
|
||||
* Transfers to a new state
|
||||
*/
|
||||
moveToState(stateKey: string, payload: any = {}, skipFadeOut: any = false): any {
|
||||
moveToState(stateKey: string, payload = {}, skipFadeOut = false) {
|
||||
if (this.fadingOut) {
|
||||
logger.warn("Skipping move to '" + stateKey + "' since already fading out");
|
||||
return;
|
||||
@ -54,13 +54,13 @@ export class GameState {
|
||||
// Clean up event listeners
|
||||
this.internalCleanUpClickDetectors();
|
||||
// Fading
|
||||
const fadeTime: any = this.internalGetFadeInOutTime();
|
||||
const doFade: any = !skipFadeOut && this.getHasFadeOut() && fadeTime !== 0;
|
||||
const fadeTime = this.internalGetFadeInOutTime();
|
||||
const doFade = !skipFadeOut && this.getHasFadeOut() && fadeTime !== 0;
|
||||
logger.log("Moving to", stateKey, "(fading=", doFade, ")");
|
||||
if (doFade) {
|
||||
this.htmlElement.classList.remove("arrived");
|
||||
this.fadingOut = true;
|
||||
setTimeout((): any => {
|
||||
setTimeout(() => {
|
||||
this.stateManager.moveToState(stateKey, payload);
|
||||
}, fadeTime);
|
||||
}
|
||||
@ -72,8 +72,8 @@ export class GameState {
|
||||
* 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.
|
||||
*/
|
||||
trackClicks(element: Element, handler: function():void, args: import("./click_detector").ClickDetectorConstructorArgs= = {}): any {
|
||||
const detector: any = new ClickDetector(element, args);
|
||||
trackClicks(element: Element, handler: function():void, args: import("./click_detector").ClickDetectorConstructorArgs= = {}) {
|
||||
const detector = new ClickDetector(element, args);
|
||||
detector.click.add(handler, this);
|
||||
if (G_IS_DEV) {
|
||||
// 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
|
||||
*/
|
||||
cancelAllAsyncOperations(): any {
|
||||
cancelAllAsyncOperations() {
|
||||
this.asyncChannel.cancelAll();
|
||||
}
|
||||
//// CALLBACKS ////
|
||||
/**
|
||||
* Callback when entering the state, to be overriddemn
|
||||
*/
|
||||
onEnter(payload: any): any { }
|
||||
onEnter(payload: any) { }
|
||||
/**
|
||||
* Callback when leaving the state
|
||||
*/
|
||||
onLeave(): any { }
|
||||
onLeave() { }
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
onAppResume(): any { }
|
||||
onAppResume() { }
|
||||
/**
|
||||
* Render callback
|
||||
*/
|
||||
onRender(dt: number): any { }
|
||||
onRender(dt: number) { }
|
||||
/**
|
||||
* Background tick callback, called while the game is inactiev
|
||||
*/
|
||||
onBackgroundTick(dt: number): any { }
|
||||
onBackgroundTick(dt: number) { }
|
||||
/**
|
||||
* 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
|
||||
* the escape key is pressed
|
||||
*/
|
||||
onBackButton(): any { }
|
||||
onBackButton() { }
|
||||
//// INTERFACE ////
|
||||
/**
|
||||
* 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
|
||||
* "Are you sure you want to leave the page" message.
|
||||
*/
|
||||
getHasUnloadConfirmation(): any {
|
||||
getHasUnloadConfirmation() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
@ -198,7 +198,7 @@ export class GameState {
|
||||
/**
|
||||
* Internal callback from the manager. Do not override!
|
||||
*/
|
||||
internalRegisterCallback(stateManager: StateManager, app: any): any {
|
||||
internalRegisterCallback(stateManager: StateManager, app) {
|
||||
assert(stateManager, "No state manager");
|
||||
assert(app, "No app");
|
||||
this.stateManager = stateManager;
|
||||
@ -207,13 +207,13 @@ export class GameState {
|
||||
/**
|
||||
* 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");
|
||||
this.app.inputMgr.pushReciever(this.inputReciever);
|
||||
this.htmlElement = this.getDivElement();
|
||||
this.htmlElement.classList.add("active");
|
||||
// Apply classes in the next frame so the css transition keeps up
|
||||
waitNextFrame().then((): any => {
|
||||
waitNextFrame().then(() => {
|
||||
if (this.htmlElement) {
|
||||
this.htmlElement.classList.remove("fadingOut");
|
||||
this.htmlElement.classList.remove("fadingIn");
|
||||
@ -227,7 +227,7 @@ export class GameState {
|
||||
/**
|
||||
* Internal callback when the state is left. Do not override!
|
||||
*/
|
||||
internalLeaveCallback(): any {
|
||||
internalLeaveCallback() {
|
||||
this.onLeave();
|
||||
this.htmlElement.classList.remove("active");
|
||||
this.app.inputMgr.popReciever(this.inputReciever);
|
||||
@ -237,21 +237,21 @@ export class GameState {
|
||||
/**
|
||||
* Internal app pause callback
|
||||
*/
|
||||
internalOnAppPauseCallback(): any {
|
||||
internalOnAppPauseCallback() {
|
||||
this.onAppPause();
|
||||
}
|
||||
/**
|
||||
* Internal app resume callback
|
||||
*/
|
||||
internalOnAppResumeCallback(): any {
|
||||
internalOnAppResumeCallback() {
|
||||
this.onAppResume();
|
||||
}
|
||||
/**
|
||||
* Cleans up all click detectors
|
||||
*/
|
||||
internalCleanUpClickDetectors(): any {
|
||||
internalCleanUpClickDetectors() {
|
||||
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 = [];
|
||||
|
@ -17,6 +17,6 @@ export let gItemRegistry: FactoryTemplate<BaseItem> = new Factory("item");
|
||||
// Helpers
|
||||
export function initBuildingsByCategory(buildings: {
|
||||
[idx: string]: Array<Class<MetaBuilding>>;
|
||||
}): any {
|
||||
}) {
|
||||
gBuildingsByCategory = buildings;
|
||||
}
|
||||
|
@ -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!
|
||||
*/
|
||||
export let GLOBAL_APP: Application = null;
|
||||
export function setGlobalApp(app: Application): any {
|
||||
export function setGlobalApp(app: Application) {
|
||||
assert(!GLOBAL_APP, "Create application twice!");
|
||||
GLOBAL_APP = app;
|
||||
}
|
||||
export const BUILD_OPTIONS: any = {
|
||||
export const BUILD_OPTIONS = {
|
||||
HAVE_ASSERT: G_HAVE_ASSERT,
|
||||
APP_ENVIRONMENT: G_APP_ENVIRONMENT,
|
||||
IS_DEV: G_IS_DEV,
|
||||
|
@ -5,7 +5,7 @@ import type { InputReceiver } from "./input_receiver";
|
||||
import { Signal, STOP_PROPAGATION } from "./signal";
|
||||
import { createLogger } from "./logging";
|
||||
import { arrayDeleteValue, fastArrayDeleteValue } from "./utils";
|
||||
const logger: any = createLogger("input_distributor");
|
||||
const logger = createLogger("input_distributor");
|
||||
export class InputDistributor {
|
||||
public app = app;
|
||||
public recieverStack: Array<InputReceiver> = [];
|
||||
@ -18,16 +18,16 @@ export class InputDistributor {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* Removes an attached filter
|
||||
*/
|
||||
dismountFilter(filter: function(: boolean):boolean): any {
|
||||
dismountFilter(filter: function(: boolean):boolean) {
|
||||
fastArrayDeleteValue(this.filters, filter);
|
||||
}
|
||||
pushReciever(reciever: InputReceiver): any {
|
||||
pushReciever(reciever: InputReceiver) {
|
||||
if (this.isRecieverAttached(reciever)) {
|
||||
assert(false, "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);
|
||||
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) {
|
||||
assert(false, "Can not pop reciever " + reciever.context + " since its not contained");
|
||||
logger.error("Can not pop reciever", reciever.context, "since its not contained");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
isRecieverAttached(reciever: InputReceiver): any {
|
||||
isRecieverAttached(reciever: InputReceiver) {
|
||||
return this.recieverStack.indexOf(reciever) >= 0;
|
||||
}
|
||||
isRecieverOnTop(reciever: InputReceiver): any {
|
||||
isRecieverOnTop(reciever: InputReceiver) {
|
||||
return (this.isRecieverAttached(reciever) &&
|
||||
this.recieverStack[this.recieverStack.length - 1] === reciever);
|
||||
}
|
||||
makeSureAttachedAndOnTop(reciever: InputReceiver): any {
|
||||
makeSureAttachedAndOnTop(reciever: InputReceiver) {
|
||||
this.makeSureDetached(reciever);
|
||||
this.pushReciever(reciever);
|
||||
}
|
||||
makeSureDetached(reciever: InputReceiver): any {
|
||||
makeSureDetached(reciever: InputReceiver) {
|
||||
if (this.isRecieverAttached(reciever)) {
|
||||
arrayDeleteValue(this.recieverStack, reciever);
|
||||
}
|
||||
}
|
||||
destroyReceiver(reciever: InputReceiver): any {
|
||||
destroyReceiver(reciever: InputReceiver) {
|
||||
this.makeSureDetached(reciever);
|
||||
reciever.cleanup();
|
||||
}
|
||||
// Internal
|
||||
getTopReciever(): any {
|
||||
getTopReciever() {
|
||||
if (this.recieverStack.length > 0) {
|
||||
return this.recieverStack[this.recieverStack.length - 1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
bindToEvents(): any {
|
||||
bindToEvents() {
|
||||
window.addEventListener("popstate", this.handleBackButton.bind(this), false);
|
||||
document.addEventListener("backbutton", this.handleBackButton.bind(this), false);
|
||||
window.addEventListener("keydown", this.handleKeyMouseDown.bind(this));
|
||||
@ -86,23 +86,23 @@ export class InputDistributor {
|
||||
window.addEventListener("blur", this.handleBlur.bind(this));
|
||||
document.addEventListener("paste", this.handlePaste.bind(this));
|
||||
}
|
||||
forwardToReceiver(eventId: any, payload: any = null): any {
|
||||
forwardToReceiver(eventId, payload = null) {
|
||||
// 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)) {
|
||||
return STOP_PROPAGATION;
|
||||
}
|
||||
}
|
||||
const reciever: any = this.getTopReciever();
|
||||
const reciever = this.getTopReciever();
|
||||
if (!reciever) {
|
||||
logger.warn("Dismissing event because not reciever was found:", eventId);
|
||||
return;
|
||||
}
|
||||
const signal: any = reciever[eventId];
|
||||
const signal = reciever[eventId];
|
||||
assert(signal instanceof Signal, "Not a valid event id");
|
||||
return signal.dispatch(payload);
|
||||
}
|
||||
handleBackButton(event: Event): any {
|
||||
handleBackButton(event: Event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.forwardToReceiver("backButton");
|
||||
@ -110,16 +110,16 @@ export class InputDistributor {
|
||||
/**
|
||||
* Handles when the page got blurred
|
||||
*/
|
||||
handleBlur(): any {
|
||||
handleBlur() {
|
||||
this.forwardToReceiver("pageBlur", {});
|
||||
this.keysDown.clear();
|
||||
}
|
||||
|
||||
handlePaste(ev: any): any {
|
||||
handlePaste(ev) {
|
||||
this.forwardToReceiver("paste", ev);
|
||||
}
|
||||
handleKeyMouseDown(event: KeyboardEvent | MouseEvent): any {
|
||||
const keyCode: any = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
|
||||
handleKeyMouseDown(event: KeyboardEvent | MouseEvent) {
|
||||
const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
|
||||
if (keyCode === 4 || // MB4
|
||||
keyCode === 5 || // MB5
|
||||
keyCode === 9 || // TAB
|
||||
@ -130,7 +130,7 @@ export class InputDistributor {
|
||||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
const isInitial: any = !this.keysDown.has(keyCode);
|
||||
const isInitial = !this.keysDown.has(keyCode);
|
||||
this.keysDown.add(keyCode);
|
||||
if (this.forwardToReceiver("keydown", {
|
||||
keyCode: keyCode,
|
||||
@ -149,8 +149,8 @@ export class InputDistributor {
|
||||
return this.forwardToReceiver("backButton");
|
||||
}
|
||||
}
|
||||
handleKeyMouseUp(event: KeyboardEvent | MouseEvent): any {
|
||||
const keyCode: any = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
|
||||
handleKeyMouseUp(event: KeyboardEvent | MouseEvent) {
|
||||
const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
|
||||
this.keysDown.delete(keyCode);
|
||||
this.forwardToReceiver("keyup", {
|
||||
keyCode: keyCode,
|
||||
|
@ -10,7 +10,7 @@ export class InputReceiver {
|
||||
|
||||
constructor(context = "unknown") {
|
||||
}
|
||||
cleanup(): any {
|
||||
cleanup() {
|
||||
this.backButton.removeAll();
|
||||
this.keydown.removeAll();
|
||||
this.keyup.removeAll();
|
||||
|
@ -5,8 +5,8 @@ import { createLogger } from "./logging";
|
||||
export type Application = import("../application").Application;
|
||||
export type AtlasDefinition = import("./atlas_definitions").AtlasDefinition;
|
||||
|
||||
const logger: any = createLogger("loader");
|
||||
const missingSpriteIds: any = {};
|
||||
const logger = createLogger("loader");
|
||||
const missingSpriteIds = {};
|
||||
class LoaderImpl {
|
||||
public app = null;
|
||||
public sprites: Map<string, BaseSprite> = new Map();
|
||||
@ -14,7 +14,7 @@ class LoaderImpl {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
linkAppAfterBoot(app: Application): any {
|
||||
linkAppAfterBoot(app: Application) {
|
||||
this.app = app;
|
||||
this.makeSpriteNotFoundCanvas();
|
||||
}
|
||||
@ -23,7 +23,7 @@ class LoaderImpl {
|
||||
* {}
|
||||
*/
|
||||
getSpriteInternal(key: string): BaseSprite {
|
||||
const sprite: any = this.sprites.get(key);
|
||||
const sprite = this.sprites.get(key);
|
||||
if (!sprite) {
|
||||
if (!missingSpriteIds[key]) {
|
||||
// Only show error once
|
||||
@ -39,7 +39,7 @@ class LoaderImpl {
|
||||
* {}
|
||||
*/
|
||||
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");
|
||||
return sprite as AtlasSprite);
|
||||
}
|
||||
@ -48,7 +48,7 @@ class LoaderImpl {
|
||||
* {}
|
||||
*/
|
||||
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");
|
||||
return sprite as RegularSprite);
|
||||
}
|
||||
@ -58,14 +58,14 @@ class LoaderImpl {
|
||||
*/
|
||||
internalPreloadImage(key: string, progressHandler: (progress: number) => void): Promise<HTMLImageElement | null> {
|
||||
return this.app.backgroundResourceLoader
|
||||
.preloadWithProgress("res/" + key, (progress: any): any => {
|
||||
.preloadWithProgress("res/" + key, progress => {
|
||||
progressHandler(progress);
|
||||
})
|
||||
.then((url: any): any => {
|
||||
return new Promise((resolve: any, reject: any): any => {
|
||||
const image: any = new Image();
|
||||
image.addEventListener("load", (): any => resolve(image));
|
||||
image.addEventListener("error", (err: any): any => reject("Failed to load sprite " + key + ": " + err));
|
||||
.then(url => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const image = new Image();
|
||||
image.addEventListener("load", () => resolve(image));
|
||||
image.addEventListener("error", err => reject("Failed to load sprite " + key + ": " + err));
|
||||
image.src = url;
|
||||
});
|
||||
});
|
||||
@ -75,7 +75,7 @@ class LoaderImpl {
|
||||
* {}
|
||||
*/
|
||||
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) {
|
||||
// Allow access to regular sprites
|
||||
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> {
|
||||
return this.internalPreloadImage(atlas.getFullSourcePath(), progressHandler).then((image: any): any => {
|
||||
return this.internalPreloadImage(atlas.getFullSourcePath(), progressHandler).then(image => {
|
||||
// @ts-ignore
|
||||
image.label = atlas.sourceFileName;
|
||||
return this.internalParseAtlas(atlas, image);
|
||||
});
|
||||
}
|
||||
internalParseAtlas({ meta: { scale }, sourceData }: AtlasDefinition, loadedImage: HTMLImageElement): any {
|
||||
internalParseAtlas({ meta: { scale }, sourceData }: AtlasDefinition, loadedImage: HTMLImageElement) {
|
||||
this.rawImages.push(loadedImage);
|
||||
for (const spriteName: any in sourceData) {
|
||||
const { frame, sourceSize, spriteSourceSize }: any = sourceData[spriteName];
|
||||
let sprite: any = (this.sprites.get(spriteName) as AtlasSprite);
|
||||
for (const spriteName in sourceData) {
|
||||
const { frame, sourceSize, spriteSourceSize } = sourceData[spriteName];
|
||||
let sprite = this.sprites.get(spriteName) as AtlasSprite);
|
||||
if (!sprite) {
|
||||
sprite = new AtlasSprite(spriteName);
|
||||
this.sprites.set(spriteName, sprite);
|
||||
@ -106,7 +106,7 @@ class LoaderImpl {
|
||||
if (sprite.frozen) {
|
||||
continue;
|
||||
}
|
||||
const link: any = new SpriteAtlasLink({
|
||||
const link = new SpriteAtlasLink({
|
||||
packedX: frame.x,
|
||||
packedY: frame.y,
|
||||
packedW: frame.w,
|
||||
@ -123,9 +123,9 @@ class LoaderImpl {
|
||||
/**
|
||||
* Makes the canvas which shows the question mark, shown when a sprite was not found
|
||||
*/
|
||||
makeSpriteNotFoundCanvas(): any {
|
||||
const dims: any = 128;
|
||||
const [canvas, context]: any = makeOffscreenBuffer(dims, dims, {
|
||||
makeSpriteNotFoundCanvas() {
|
||||
const dims = 128;
|
||||
const [canvas, context] = makeOffscreenBuffer(dims, dims, {
|
||||
smooth: false,
|
||||
label: "not-found-sprite",
|
||||
});
|
||||
@ -139,8 +139,8 @@ class LoaderImpl {
|
||||
// TODO: Not sure why this is set here
|
||||
// @ts-ignore
|
||||
canvas.src = "not-found";
|
||||
const sprite: any = new AtlasSprite("not-found");
|
||||
["0.1", "0.25", "0.5", "0.75", "1"].forEach((resolution: any): any => {
|
||||
const sprite = new AtlasSprite("not-found");
|
||||
["0.1", "0.25", "0.5", "0.75", "1"].forEach(resolution => {
|
||||
sprite.linksByResolution[resolution] = new SpriteAtlasLink({
|
||||
packedX: 0,
|
||||
packedY: 0,
|
||||
@ -156,4 +156,4 @@ class LoaderImpl {
|
||||
this.spriteNotFoundSprite = sprite;
|
||||
}
|
||||
}
|
||||
export const Loader: any = new LoaderImpl();
|
||||
export const Loader = new LoaderImpl();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { globalConfig } from "./config";
|
||||
const circularJson: any = require("circular-json");
|
||||
const circularJson = require("circular-json");
|
||||
/*
|
||||
Logging functions
|
||||
- To be extended
|
||||
@ -12,23 +12,23 @@ class Logger {
|
||||
|
||||
constructor(context) {
|
||||
}
|
||||
debug(...args: any): any {
|
||||
debug(...args) {
|
||||
globalDebug(this.context, ...args);
|
||||
}
|
||||
log(...args: any): any {
|
||||
log(...args) {
|
||||
globalLog(this.context, ...args);
|
||||
}
|
||||
warn(...args: any): any {
|
||||
warn(...args) {
|
||||
globalWarn(this.context, ...args);
|
||||
}
|
||||
error(...args: any): any {
|
||||
error(...args) {
|
||||
globalError(this.context, ...args);
|
||||
}
|
||||
}
|
||||
export function createLogger(context: any): any {
|
||||
export function createLogger(context) {
|
||||
return new Logger(context);
|
||||
}
|
||||
function prepareObjectForLogging(obj: any, maxDepth: any = 1): any {
|
||||
function prepareObjectForLogging(obj, maxDepth = 1) {
|
||||
if (!window.Sentry) {
|
||||
// Not required without sentry
|
||||
return obj;
|
||||
@ -36,9 +36,9 @@ function prepareObjectForLogging(obj: any, maxDepth: any = 1): any {
|
||||
if (typeof obj !== "object" && !Array.isArray(obj)) {
|
||||
return obj;
|
||||
}
|
||||
const result: any = {};
|
||||
for (const key: any in obj) {
|
||||
const val: any = obj[key];
|
||||
const result = {};
|
||||
for (const key in obj) {
|
||||
const val = obj[key];
|
||||
if (typeof val === "object") {
|
||||
if (maxDepth > 0) {
|
||||
result[key] = prepareObjectForLogging(val, maxDepth - 1);
|
||||
@ -56,11 +56,11 @@ function prepareObjectForLogging(obj: any, maxDepth: any = 1): any {
|
||||
/**
|
||||
* Serializes an error
|
||||
*/
|
||||
export function serializeError(err: Error | ErrorEvent): any {
|
||||
export function serializeError(err: Error | ErrorEvent) {
|
||||
if (!err) {
|
||||
return null;
|
||||
}
|
||||
const result: any = {
|
||||
const result = {
|
||||
|
||||
type: err.constructor.name,
|
||||
};
|
||||
@ -91,8 +91,8 @@ export function serializeError(err: Error | ErrorEvent): any {
|
||||
/**
|
||||
* Serializes an event
|
||||
*/
|
||||
function serializeEvent(event: Event): any {
|
||||
let result: any = {
|
||||
function serializeEvent(event: Event) {
|
||||
let result = {
|
||||
type: "{type.Event:" + typeof event + "}",
|
||||
};
|
||||
result.eventType = event.type;
|
||||
@ -101,7 +101,7 @@ function serializeEvent(event: Event): any {
|
||||
/**
|
||||
* Prepares a json payload
|
||||
*/
|
||||
function preparePayload(key: string, value: any): any {
|
||||
function preparePayload(key: string, value: any) {
|
||||
if (value instanceof Error || value instanceof ErrorEvent) {
|
||||
return serializeError(value);
|
||||
}
|
||||
@ -116,44 +116,44 @@ function preparePayload(key: string, value: any): any {
|
||||
/**
|
||||
* Stringifies an object containing circular references and errors
|
||||
*/
|
||||
export function stringifyObjectContainingErrors(payload: any): any {
|
||||
export function stringifyObjectContainingErrors(payload: any) {
|
||||
return circularJson.stringify(payload, preparePayload);
|
||||
}
|
||||
export function globalDebug(context: any, ...args: any): any {
|
||||
export function globalDebug(context, ...args) {
|
||||
if (G_IS_DEV) {
|
||||
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
|
||||
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
|
||||
logInternal(context, console.warn, prepareArgsForLogging(args));
|
||||
}
|
||||
export function globalError(context: any, ...args: any): any {
|
||||
export function globalError(context, ...args) {
|
||||
args = prepareArgsForLogging(args);
|
||||
// eslint-disable-next-line no-console
|
||||
logInternal(context, console.error, args);
|
||||
if (window.Sentry) {
|
||||
window.Sentry.withScope((scope: any): any => {
|
||||
window.Sentry.withScope(scope => {
|
||||
scope.setExtra("args", args);
|
||||
window.Sentry.captureMessage(internalBuildStringFromArgs(args), "error");
|
||||
});
|
||||
}
|
||||
}
|
||||
function prepareArgsForLogging(args: any): any {
|
||||
let result: any = [];
|
||||
for (let i: any = 0; i < args.length; ++i) {
|
||||
function prepareArgsForLogging(args) {
|
||||
let result = [];
|
||||
for (let i = 0; i < args.length; ++i) {
|
||||
result.push(prepareObjectForLogging(args[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function internalBuildStringFromArgs(args: Array<any>): any {
|
||||
let result: any = [];
|
||||
for (let i: any = 0; i < args.length; ++i) {
|
||||
let arg: any = args[i];
|
||||
function internalBuildStringFromArgs(args: Array<any>) {
|
||||
let result = [];
|
||||
for (let i = 0; i < args.length; ++i) {
|
||||
let arg = args[i];
|
||||
if (typeof arg === "string" ||
|
||||
typeof arg === "number" ||
|
||||
typeof arg === "boolean" ||
|
||||
@ -170,17 +170,17 @@ function internalBuildStringFromArgs(args: Array<any>): any {
|
||||
}
|
||||
return result.join(" ");
|
||||
}
|
||||
export function logSection(name: any, color: any): any {
|
||||
export function logSection(name, color) {
|
||||
while (name.length <= 14) {
|
||||
name = " " + name + " ";
|
||||
}
|
||||
name = name.padEnd(19, " ");
|
||||
const lineCss: any = "letter-spacing: -3px; color: " + color + "; font-size: 6px; background: #eee; color: #eee;";
|
||||
const line: any = "%c----------------------------";
|
||||
const lineCss = "letter-spacing: -3px; color: " + color + "; font-size: 6px; background: #eee; color: #eee;";
|
||||
const line = "%c----------------------------";
|
||||
console.log("\n" + line + " %c" + name + " " + line + "\n", lineCss, "color: " + color, lineCss);
|
||||
}
|
||||
function extractHandleContext(handle: any): any {
|
||||
let context: any = handle || "unknown";
|
||||
function extractHandleContext(handle) {
|
||||
let context = handle || "unknown";
|
||||
|
||||
|
||||
if (handle && handle.constructor && handle.constructor.name) {
|
||||
@ -195,11 +195,11 @@ function extractHandleContext(handle: any): any {
|
||||
}
|
||||
return context + "";
|
||||
}
|
||||
function logInternal(handle: any, consoleMethod: any, args: any): any {
|
||||
const context: any = extractHandleContext(handle).padEnd(20, " ");
|
||||
const labelColor: any = handle && handle.LOG_LABEL_COLOR ? handle.LOG_LABEL_COLOR : "#aaa";
|
||||
function logInternal(handle, consoleMethod, args) {
|
||||
const context = extractHandleContext(handle).padEnd(20, " ");
|
||||
const labelColor = handle && handle.LOG_LABEL_COLOR ? handle.LOG_LABEL_COLOR : "#aaa";
|
||||
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);
|
||||
}
|
||||
else {
|
||||
|
@ -7,45 +7,45 @@
|
||||
// http://pieroxy.net/blog/pages/lz-string/testing.html
|
||||
//
|
||||
// LZ-based compression algorithm, version 1.4.4
|
||||
const fromCharCode: any = String.fromCharCode;
|
||||
const hasOwnProperty: any = Object.prototype.hasOwnProperty;
|
||||
const keyStrUriSafe: any = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
|
||||
const baseReverseDic: any = {};
|
||||
function getBaseValue(alphabet: any, character: any): any {
|
||||
const fromCharCode = String.fromCharCode;
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
const keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
|
||||
const baseReverseDic = {};
|
||||
function getBaseValue(alphabet, character) {
|
||||
if (!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;
|
||||
}
|
||||
}
|
||||
return baseReverseDic[alphabet][character];
|
||||
}
|
||||
//compress into uint8array (UCS-2 big endian format)
|
||||
export function compressU8(uncompressed: any): any {
|
||||
let compressed: any = compress(uncompressed);
|
||||
let buf: any = new Uint8Array(compressed.length * 2); // 2 bytes per character
|
||||
for (let i: any = 0, TotalLen: any = compressed.length; i < TotalLen; i++) {
|
||||
let current_value: any = compressed.charCodeAt(i);
|
||||
export function compressU8(uncompressed) {
|
||||
let compressed = compress(uncompressed);
|
||||
let buf = new Uint8Array(compressed.length * 2); // 2 bytes per character
|
||||
for (let i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
|
||||
let current_value = compressed.charCodeAt(i);
|
||||
buf[i * 2] = current_value >>> 8;
|
||||
buf[i * 2 + 1] = current_value % 256;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
// Compreses with header
|
||||
export function compressU8WHeader(uncompressed: string, header: number): any {
|
||||
let compressed: any = compress(uncompressed);
|
||||
let buf: any = new Uint8Array(2 + compressed.length * 2); // 2 bytes per character
|
||||
export function compressU8WHeader(uncompressed: string, header: number) {
|
||||
let compressed = compress(uncompressed);
|
||||
let buf = new Uint8Array(2 + compressed.length * 2); // 2 bytes per character
|
||||
buf[0] = header >>> 8;
|
||||
buf[1] = header % 256;
|
||||
for (let i: any = 0, TotalLen: any = compressed.length; i < TotalLen; i++) {
|
||||
let current_value: any = compressed.charCodeAt(i);
|
||||
for (let i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
|
||||
let current_value = compressed.charCodeAt(i);
|
||||
buf[2 + i * 2] = current_value >>> 8;
|
||||
buf[2 + i * 2 + 1] = current_value % 256;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
//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
|
||||
// for (let i = 0, TotalLen = buf.length; i < TotalLen; i++) {
|
||||
// buf[i] = compressed[i * 2] * 256 + compressed[i * 2 + 1];
|
||||
@ -54,42 +54,42 @@ export function decompressU8WHeader(compressed: Uint8Array): any {
|
||||
// buf.forEach(function (c) {
|
||||
// result.push(fromCharCode(c));
|
||||
// });
|
||||
let result: any = [];
|
||||
for (let i: any = 2, n: any = compressed.length; i < n; i += 2) {
|
||||
const code: any = compressed[i] * 256 + compressed[i + 1];
|
||||
let result = [];
|
||||
for (let i = 2, n = compressed.length; i < n; i += 2) {
|
||||
const code = compressed[i] * 256 + compressed[i + 1];
|
||||
result.push(fromCharCode(code));
|
||||
}
|
||||
return decompress(result.join(""));
|
||||
}
|
||||
//compress into a string that is already URI encoded
|
||||
export function compressX64(input: any): any {
|
||||
export function compressX64(input) {
|
||||
if (input == null)
|
||||
return "";
|
||||
return _compress(input, 6, function (a: any): any {
|
||||
return _compress(input, 6, function (a) {
|
||||
return keyStrUriSafe.charAt(a);
|
||||
});
|
||||
}
|
||||
//decompress from an output of compressToEncodedURIComponent
|
||||
export function decompressX64(input: any): any {
|
||||
export function decompressX64(input) {
|
||||
if (input == null)
|
||||
return "";
|
||||
if (input == "")
|
||||
return null;
|
||||
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));
|
||||
});
|
||||
}
|
||||
function compress(uncompressed: any): any {
|
||||
return _compress(uncompressed, 16, function (a: any): any {
|
||||
function compress(uncompressed) {
|
||||
return _compress(uncompressed, 16, function (a) {
|
||||
return fromCharCode(a);
|
||||
});
|
||||
}
|
||||
function _compress(uncompressed: any, bitsPerChar: any, getCharFromInt: any): any {
|
||||
function _compress(uncompressed, bitsPerChar, getCharFromInt) {
|
||||
if (uncompressed == null)
|
||||
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
|
||||
context_dictSize: any = 3, context_numBits: any = 2, context_data: any = [], context_data_val: any = 0, context_data_position: any = 0, ii: any;
|
||||
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 = 3, context_numBits = 2, context_data = [], context_data_val = 0, context_data_position = 0, ii;
|
||||
for (ii = 0; ii < uncompressed.length; ii += 1) {
|
||||
context_c = uncompressed.charAt(ii);
|
||||
if (!hasOwnProperty.call(context_dictionary, context_c)) {
|
||||
@ -300,17 +300,17 @@ function _compress(uncompressed: any, bitsPerChar: any, getCharFromInt: any): an
|
||||
}
|
||||
return context_data.join("");
|
||||
}
|
||||
function decompress(compressed: any): any {
|
||||
function decompress(compressed) {
|
||||
if (compressed == null)
|
||||
return "";
|
||||
if (compressed == "")
|
||||
return null;
|
||||
return _decompress(compressed.length, 32768, function (index: any): any {
|
||||
return _decompress(compressed.length, 32768, function (index) {
|
||||
return compressed.charCodeAt(index);
|
||||
});
|
||||
}
|
||||
function _decompress(length: any, resetValue: any, getNextValue: any): any {
|
||||
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 };
|
||||
function _decompress(length, resetValue, getNextValue) {
|
||||
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) {
|
||||
dictionary[i] = i;
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ import { T } from "../translations";
|
||||
*
|
||||
* ***************************************************
|
||||
*/
|
||||
const kbEnter: any = 13;
|
||||
const kbCancel: any = 27;
|
||||
const logger: any = createLogger("dialogs");
|
||||
const kbEnter = 13;
|
||||
const kbCancel = 27;
|
||||
const logger = createLogger("dialogs");
|
||||
/**
|
||||
* Basic text based dialog
|
||||
*/
|
||||
@ -48,11 +48,11 @@ export class Dialog {
|
||||
*/
|
||||
|
||||
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) {
|
||||
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.inputReciever.keydown.add(this.handleKeydown, this);
|
||||
@ -65,7 +65,7 @@ export class Dialog {
|
||||
shift: boolean;
|
||||
alt: boolean;
|
||||
ctrl: boolean;
|
||||
}): any {
|
||||
}) {
|
||||
if (keyCode === kbEnter && this.enterHandler) {
|
||||
this.internalButtonHandler(this.enterHandler);
|
||||
return STOP_PROPAGATION;
|
||||
@ -75,15 +75,15 @@ export class Dialog {
|
||||
return STOP_PROPAGATION;
|
||||
}
|
||||
}
|
||||
internalButtonHandler(id: any, ...payload: any): any {
|
||||
internalButtonHandler(id, ...payload) {
|
||||
this.app.inputMgr.popReciever(this.inputReciever);
|
||||
if (id !== "close-button") {
|
||||
this.buttonSignals[id].dispatch(...payload);
|
||||
}
|
||||
this.closeRequested.dispatch();
|
||||
}
|
||||
createElement(): any {
|
||||
const elem: any = document.createElement("div");
|
||||
createElement() {
|
||||
const elem = document.createElement("div");
|
||||
elem.classList.add("ingameDialog");
|
||||
this.dialogElem = document.createElement("div");
|
||||
this.dialogElem.classList.add("dialogInner");
|
||||
@ -91,45 +91,45 @@ export class Dialog {
|
||||
this.dialogElem.classList.add(this.type);
|
||||
}
|
||||
elem.appendChild(this.dialogElem);
|
||||
const title: any = document.createElement("h1");
|
||||
const title = document.createElement("h1");
|
||||
title.innerText = this.title;
|
||||
title.classList.add("title");
|
||||
this.dialogElem.appendChild(title);
|
||||
if (this.closeButton) {
|
||||
this.dialogElem.classList.add("hasCloseButton");
|
||||
const closeBtn: any = document.createElement("button");
|
||||
const closeBtn = document.createElement("button");
|
||||
closeBtn.classList.add("closeButton");
|
||||
this.trackClicks(closeBtn, (): any => this.internalButtonHandler("close-button"), {
|
||||
this.trackClicks(closeBtn, () => this.internalButtonHandler("close-button"), {
|
||||
applyCssClass: "pressedSmallElement",
|
||||
});
|
||||
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.innerHTML = this.contentHTML;
|
||||
this.dialogElem.appendChild(content);
|
||||
if (this.buttonIds.length > 0) {
|
||||
const buttons: any = document.createElement("div");
|
||||
const buttons = document.createElement("div");
|
||||
buttons.classList.add("buttons");
|
||||
// Create buttons
|
||||
for (let i: any = 0; i < this.buttonIds.length; ++i) {
|
||||
const [buttonId, buttonStyle, rawParams]: any = this.buttonIds[i].split(":");
|
||||
const button: any = document.createElement("button");
|
||||
for (let i = 0; i < this.buttonIds.length; ++i) {
|
||||
const [buttonId, buttonStyle, rawParams] = this.buttonIds[i].split(":");
|
||||
const button = document.createElement("button");
|
||||
button.classList.add("button");
|
||||
button.classList.add("styledButton");
|
||||
button.classList.add(buttonStyle);
|
||||
button.innerText = T.dialogs.buttons[buttonId];
|
||||
const params: any = (rawParams || "").split("/");
|
||||
const useTimeout: any = params.indexOf("timeout") >= 0;
|
||||
const isEnter: any = params.indexOf("enter") >= 0;
|
||||
const isEscape: any = params.indexOf("escape") >= 0;
|
||||
const params = (rawParams || "").split("/");
|
||||
const useTimeout = params.indexOf("timeout") >= 0;
|
||||
const isEnter = params.indexOf("enter") >= 0;
|
||||
const isEscape = params.indexOf("escape") >= 0;
|
||||
if (isEscape && this.closeButton) {
|
||||
logger.warn("Showing dialog with close button, and additional cancel button");
|
||||
}
|
||||
if (useTimeout) {
|
||||
button.classList.add("timedButton");
|
||||
const timeout: any = setTimeout((): any => {
|
||||
const timeout = setTimeout(() => {
|
||||
button.classList.remove("timedButton");
|
||||
arrayDeleteValue(this.timeouts, timeout);
|
||||
}, 1000);
|
||||
@ -138,7 +138,7 @@ export class Dialog {
|
||||
if (isEnter || isEscape) {
|
||||
// if (this.app.settings.getShowKeyboardShortcuts()) {
|
||||
// Show keybinding
|
||||
const spacer: any = document.createElement("code");
|
||||
const spacer = document.createElement("code");
|
||||
spacer.classList.add("keybinding");
|
||||
spacer.innerHTML = getStringForKeyCode(isEnter ? kbEnter : kbCancel);
|
||||
button.appendChild(spacer);
|
||||
@ -150,7 +150,7 @@ export class Dialog {
|
||||
this.escapeHandler = buttonId;
|
||||
}
|
||||
}
|
||||
this.trackClicks(button, (): any => this.internalButtonHandler(buttonId));
|
||||
this.trackClicks(button, () => this.internalButtonHandler(buttonId));
|
||||
buttons.appendChild(button);
|
||||
}
|
||||
this.dialogElem.appendChild(buttons);
|
||||
@ -162,10 +162,10 @@ export class Dialog {
|
||||
this.app.inputMgr.pushReciever(this.inputReciever);
|
||||
return this.element;
|
||||
}
|
||||
setIndex(index: any): any {
|
||||
setIndex(index) {
|
||||
this.element.style.zIndex = index;
|
||||
}
|
||||
destroy(): any {
|
||||
destroy() {
|
||||
if (!this.element) {
|
||||
assert(false, "Tried to destroy dialog twice");
|
||||
return;
|
||||
@ -174,21 +174,21 @@ export class Dialog {
|
||||
// dispatched to the modal dialogs, it will not call the internalButtonHandler,
|
||||
// and thus our receiver stays attached the whole time
|
||||
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 = [];
|
||||
this.element.remove();
|
||||
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]);
|
||||
}
|
||||
this.timeouts = [];
|
||||
}
|
||||
hide(): any {
|
||||
hide() {
|
||||
this.element.classList.remove("visible");
|
||||
}
|
||||
show(): any {
|
||||
show() {
|
||||
this.element.classList.add("visible");
|
||||
}
|
||||
/**
|
||||
@ -196,7 +196,7 @@ export class Dialog {
|
||||
* {}
|
||||
*/
|
||||
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);
|
||||
this.clickDetectors.push(detector);
|
||||
return detector;
|
||||
@ -220,18 +220,18 @@ export class DialogLoading extends Dialog {
|
||||
this.inputReciever.backButton.removeAll();
|
||||
this.inputReciever.context = "dialog-loading";
|
||||
}
|
||||
createElement(): any {
|
||||
const elem: any = document.createElement("div");
|
||||
createElement() {
|
||||
const elem = document.createElement("div");
|
||||
elem.classList.add("ingameDialog");
|
||||
elem.classList.add("loadingDialog");
|
||||
this.element = elem;
|
||||
if (this.text) {
|
||||
const text: any = document.createElement("div");
|
||||
const text = document.createElement("div");
|
||||
text.classList.add("text");
|
||||
text.innerText = this.text;
|
||||
elem.appendChild(text);
|
||||
}
|
||||
const loader: any = document.createElement("div");
|
||||
const loader = document.createElement("div");
|
||||
loader.classList.add("prefab_LoadingTextWithAnim");
|
||||
loader.classList.add("loadingIndicator");
|
||||
elem.appendChild(loader);
|
||||
@ -244,10 +244,10 @@ export class DialogOptionChooser extends Dialog {
|
||||
public initialOption = options.active;
|
||||
|
||||
constructor({ app, title, options }) {
|
||||
let html: any = "<div class='optionParent'>";
|
||||
options.options.forEach(({ value, text, desc = null, iconPrefix = null }: any): any => {
|
||||
const descHtml: any = desc ? `<span class="desc">${desc}</span>` : "";
|
||||
let iconHtml: any = iconPrefix ? `<span class="icon icon-${iconPrefix}-${value}"></span>` : "";
|
||||
let html = "<div class='optionParent'>";
|
||||
options.options.forEach(({ value, text, desc = null, iconPrefix = null }) => {
|
||||
const descHtml = desc ? `<span class="desc">${desc}</span>` : "";
|
||||
let iconHtml = iconPrefix ? `<span class="icon icon-${iconPrefix}-${value}"></span>` : "";
|
||||
html += `
|
||||
<div class='option ${value === options.active ? "active" : ""} ${iconPrefix ? "hasIcon" : ""}' data-optionvalue='${value}'>
|
||||
${iconHtml}
|
||||
@ -267,17 +267,17 @@ export class DialogOptionChooser extends Dialog {
|
||||
});
|
||||
this.buttonSignals.optionSelected = new Signal();
|
||||
}
|
||||
createElement(): any {
|
||||
const div: any = super.createElement();
|
||||
createElement() {
|
||||
const div = super.createElement();
|
||||
this.dialogElem.classList.add("optionChooserDialog");
|
||||
div.querySelectorAll("[data-optionvalue]").forEach((handle: any): any => {
|
||||
const value: any = handle.getAttribute("data-optionvalue");
|
||||
div.querySelectorAll("[data-optionvalue]").forEach(handle => {
|
||||
const value = handle.getAttribute("data-optionvalue");
|
||||
if (!handle) {
|
||||
logger.error("Failed to bind option value in dialog:", value);
|
||||
return;
|
||||
}
|
||||
// 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,
|
||||
preventDefault: false,
|
||||
clickSound: null,
|
||||
@ -286,8 +286,8 @@ export class DialogOptionChooser extends Dialog {
|
||||
});
|
||||
this.clickDetectors.push(detector);
|
||||
if (value !== this.initialOption) {
|
||||
detector.click.add((): any => {
|
||||
const selected: any = div.querySelector(".option.active");
|
||||
detector.click.add(() => {
|
||||
const selected = div.querySelector(".option.active");
|
||||
if (selected) {
|
||||
selected.classList.remove("active");
|
||||
}
|
||||
@ -309,9 +309,9 @@ export class DialogWithForm extends Dialog {
|
||||
public enterHandler = confirmButtonId;
|
||||
|
||||
constructor({ app, title, desc, formElements, buttons = ["cancel", "ok:good"], confirmButtonId = "ok", closeButton = true, }) {
|
||||
let html: any = "";
|
||||
let html = "";
|
||||
html += desc + "<br>";
|
||||
for (let i: any = 0; i < formElements.length; ++i) {
|
||||
for (let i = 0; i < formElements.length; ++i) {
|
||||
html += formElements[i].getHtml();
|
||||
}
|
||||
super({
|
||||
@ -323,11 +323,11 @@ export class DialogWithForm extends Dialog {
|
||||
closeButton,
|
||||
});
|
||||
}
|
||||
internalButtonHandler(id: any, ...payload: any): any {
|
||||
internalButtonHandler(id, ...payload) {
|
||||
if (id === this.confirmButtonId) {
|
||||
if (this.hasAnyInvalid()) {
|
||||
this.dialogElem.classList.remove("errorShake");
|
||||
waitNextFrame().then((): any => {
|
||||
waitNextFrame().then(() => {
|
||||
if (this.dialogElem) {
|
||||
this.dialogElem.classList.add("errorShake");
|
||||
}
|
||||
@ -338,23 +338,23 @@ export class DialogWithForm extends Dialog {
|
||||
}
|
||||
super.internalButtonHandler(id, payload);
|
||||
}
|
||||
hasAnyInvalid(): any {
|
||||
for (let i: any = 0; i < this.formElements.length; ++i) {
|
||||
hasAnyInvalid() {
|
||||
for (let i = 0; i < this.formElements.length; ++i) {
|
||||
if (!this.formElements[i].isValid()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
createElement(): any {
|
||||
const div: any = super.createElement();
|
||||
for (let i: any = 0; i < this.formElements.length; ++i) {
|
||||
const elem: any = this.formElements[i];
|
||||
createElement() {
|
||||
const div = super.createElement();
|
||||
for (let i = 0; i < this.formElements.length; ++i) {
|
||||
const elem = this.formElements[i];
|
||||
elem.bindEvents(div, this.clickDetectors);
|
||||
// elem.valueChosen.add(this.closeRequested.dispatch, this.closeRequested);
|
||||
elem.valueChosen.add(this.valueChosen.dispatch, this.valueChosen);
|
||||
}
|
||||
waitNextFrame().then((): any => {
|
||||
waitNextFrame().then(() => {
|
||||
this.formElements[this.formElements.length - 1].focus();
|
||||
});
|
||||
return div;
|
||||
|
@ -18,18 +18,18 @@ export class FormElement {
|
||||
|
||||
constructor(id, label) {
|
||||
}
|
||||
getHtml(): any {
|
||||
getHtml() {
|
||||
abstract;
|
||||
return "";
|
||||
}
|
||||
getFormElement(parent: any): any {
|
||||
getFormElement(parent) {
|
||||
return parent.querySelector("[data-formId='" + this.id + "']");
|
||||
}
|
||||
bindEvents(parent: any, clickTrackers: any): any {
|
||||
bindEvents(parent, clickTrackers) {
|
||||
abstract;
|
||||
}
|
||||
focus(): any { }
|
||||
isValid(): any {
|
||||
focus() { }
|
||||
isValid() {
|
||||
return true;
|
||||
}
|
||||
/** {} */
|
||||
@ -47,10 +47,10 @@ export class FormElementInput extends FormElement {
|
||||
constructor({ id, label = null, placeholder, defaultValue = "", inputType = "text", validator = null }) {
|
||||
super(id, label);
|
||||
}
|
||||
getHtml(): any {
|
||||
let classes: any = [];
|
||||
let inputType: any = "text";
|
||||
let maxlength: any = 256;
|
||||
getHtml() {
|
||||
let classes = [];
|
||||
let inputType = "text";
|
||||
let maxlength = 256;
|
||||
switch (this.inputType) {
|
||||
case "text": {
|
||||
classes.push("input-text");
|
||||
@ -85,25 +85,25 @@ export class FormElementInput extends FormElement {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
bindEvents(parent: any, clickTrackers: any): any {
|
||||
bindEvents(parent, clickTrackers) {
|
||||
this.element = this.getFormElement(parent);
|
||||
this.element.addEventListener("input", (event: any): any => this.updateErrorState());
|
||||
this.element.addEventListener("input", event => this.updateErrorState());
|
||||
this.updateErrorState();
|
||||
}
|
||||
updateErrorState(): any {
|
||||
updateErrorState() {
|
||||
this.element.classList.toggle("errored", !this.isValid());
|
||||
}
|
||||
isValid(): any {
|
||||
isValid() {
|
||||
return !this.validator || this.validator(this.element.value);
|
||||
}
|
||||
getValue(): any {
|
||||
getValue() {
|
||||
return this.element.value;
|
||||
}
|
||||
setValue(value: any): any {
|
||||
setValue(value) {
|
||||
this.element.value = value;
|
||||
this.updateErrorState();
|
||||
}
|
||||
focus(): any {
|
||||
focus() {
|
||||
this.element.focus();
|
||||
this.element.select();
|
||||
}
|
||||
@ -116,7 +116,7 @@ export class FormElementCheckbox extends FormElement {
|
||||
constructor({ id, label, defaultValue = true }) {
|
||||
super(id, label);
|
||||
}
|
||||
getHtml(): any {
|
||||
getHtml() {
|
||||
return `
|
||||
<div class="formElement checkBoxFormElem">
|
||||
${this.label ? `<label>${this.label}</label>` : ""}
|
||||
@ -126,23 +126,23 @@ export class FormElementCheckbox extends FormElement {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
bindEvents(parent: any, clickTrackers: any): any {
|
||||
bindEvents(parent, clickTrackers) {
|
||||
this.element = this.getFormElement(parent);
|
||||
const detector: any = new ClickDetector(this.element, {
|
||||
const detector = new ClickDetector(this.element, {
|
||||
consumeEvents: false,
|
||||
preventDefault: false,
|
||||
});
|
||||
clickTrackers.push(detector);
|
||||
detector.click.add(this.toggle, this);
|
||||
}
|
||||
getValue(): any {
|
||||
getValue() {
|
||||
return this.value;
|
||||
}
|
||||
toggle(): any {
|
||||
toggle() {
|
||||
this.value = !this.value;
|
||||
this.element.classList.toggle("checked", this.value);
|
||||
}
|
||||
focus(parent: any): any { }
|
||||
focus(parent) { }
|
||||
}
|
||||
export class FormElementItemChooser extends FormElement {
|
||||
public items = items;
|
||||
@ -152,8 +152,8 @@ export class FormElementItemChooser extends FormElement {
|
||||
constructor({ id, label, items = [] }) {
|
||||
super(id, label);
|
||||
}
|
||||
getHtml(): any {
|
||||
let classes: any = [];
|
||||
getHtml() {
|
||||
let classes = [];
|
||||
return `
|
||||
<div class="formElement">
|
||||
${this.label ? `<label>${this.label}</label>` : ""}
|
||||
@ -161,29 +161,29 @@ export class FormElementItemChooser extends FormElement {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
bindEvents(parent: HTMLElement, clickTrackers: Array<ClickDetector>): any {
|
||||
bindEvents(parent: HTMLElement, clickTrackers: Array<ClickDetector>) {
|
||||
this.element = this.getFormElement(parent);
|
||||
for (let i: any = 0; i < this.items.length; ++i) {
|
||||
const item: any = this.items[i];
|
||||
const canvas: any = document.createElement("canvas");
|
||||
for (let i = 0; i < this.items.length; ++i) {
|
||||
const item = this.items[i];
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = 128;
|
||||
canvas.height = 128;
|
||||
const context: any = canvas.getContext("2d");
|
||||
const context = canvas.getContext("2d");
|
||||
item.drawFullSizeOnCanvas(context, 128);
|
||||
this.element.appendChild(canvas);
|
||||
const detector: any = new ClickDetector(canvas, {});
|
||||
const detector = new ClickDetector(canvas, {});
|
||||
clickTrackers.push(detector);
|
||||
detector.click.add((): any => {
|
||||
detector.click.add(() => {
|
||||
this.chosenItem = item;
|
||||
this.valueChosen.dispatch(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
isValid(): any {
|
||||
isValid() {
|
||||
return true;
|
||||
}
|
||||
getValue(): any {
|
||||
getValue() {
|
||||
return null;
|
||||
}
|
||||
focus(): any { }
|
||||
focus() { }
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
function mathPolyfills(): any {
|
||||
function mathPolyfills() {
|
||||
// Converts from degrees to radians.
|
||||
Math.radians = function (degrees: any): any {
|
||||
Math.radians = function (degrees) {
|
||||
return (degrees * Math.PI) / 180.0;
|
||||
};
|
||||
// Converts from radians to degrees.
|
||||
Math.degrees = function (radians: any): any {
|
||||
Math.degrees = function (radians) {
|
||||
return (radians * 180.0) / Math.PI;
|
||||
};
|
||||
}
|
||||
function stringPolyfills(): any {
|
||||
function stringPolyfills() {
|
||||
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
|
||||
if (!String.prototype.padStart) {
|
||||
String.prototype.padStart = function padStart(targetLength: any, padString: any): any {
|
||||
String.prototype.padStart = function padStart(targetLength, padString) {
|
||||
targetLength = targetLength >> 0; //truncate if number, or convert non-number to 0;
|
||||
padString = String(typeof padString !== "undefined" ? padString : " ");
|
||||
if (this.length >= targetLength) {
|
||||
@ -30,7 +30,7 @@ function stringPolyfills(): any {
|
||||
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
|
||||
if (!String.prototype.padEnd) {
|
||||
String.prototype.padEnd = function padEnd(targetLength: any, padString: any): any {
|
||||
String.prototype.padEnd = function padEnd(targetLength, padString) {
|
||||
targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
|
||||
padString = String(typeof padString !== "undefined" ? padString : " ");
|
||||
if (this.length > targetLength) {
|
||||
@ -46,33 +46,33 @@ function stringPolyfills(): any {
|
||||
};
|
||||
}
|
||||
}
|
||||
function objectPolyfills(): any {
|
||||
function objectPolyfills() {
|
||||
// https://github.com/tc39/proposal-object-values-entries/blob/master/polyfill.js
|
||||
// @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
|
||||
const isEnumerable: any = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable);
|
||||
const isEnumerable = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable);
|
||||
// @ts-ignore
|
||||
const concat: any = Function.bind.call(Function.call, Array.prototype.concat);
|
||||
const keys: any = Reflect.ownKeys;
|
||||
const concat = Function.bind.call(Function.call, Array.prototype.concat);
|
||||
const keys = Reflect.ownKeys;
|
||||
// @ts-ignore
|
||||
if (!Object.values) {
|
||||
// @ts-ignore
|
||||
Object.values = function values(O: any): any {
|
||||
return reduce(keys(O), (v: any, k: any): any => concat(v, typeof k === "string" && isEnumerable(O, k) ? [O[k]] : []), []);
|
||||
Object.values = function values(O) {
|
||||
return reduce(keys(O), (v, k) => concat(v, typeof k === "string" && isEnumerable(O, k) ? [O[k]] : []), []);
|
||||
};
|
||||
}
|
||||
if (!Object.entries) {
|
||||
// @ts-ignore
|
||||
Object.entries = function entries(O: any): any {
|
||||
return reduce(keys(O), (e: any, k: any): any => concat(e, typeof k === "string" && isEnumerable(O, k) ? [[k, O[k]]] : []), []);
|
||||
Object.entries = function entries(O) {
|
||||
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
|
||||
(function (arr: any): any {
|
||||
arr.forEach(function (item: any): any {
|
||||
(function (arr) {
|
||||
arr.forEach(function (item) {
|
||||
if (item.hasOwnProperty("remove")) {
|
||||
return;
|
||||
}
|
||||
@ -80,22 +80,22 @@ function domPolyfills(): any {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: function remove(): any {
|
||||
value: function remove() {
|
||||
this.parentNode.removeChild(this);
|
||||
},
|
||||
});
|
||||
});
|
||||
})([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
|
||||
}
|
||||
function initPolyfills(): any {
|
||||
function initPolyfills() {
|
||||
mathPolyfills();
|
||||
stringPolyfills();
|
||||
objectPolyfills();
|
||||
domPolyfills();
|
||||
}
|
||||
function initExtensions(): any {
|
||||
String.prototype.replaceAll = function (search: any, replacement: any): any {
|
||||
var target: any = this;
|
||||
function initExtensions() {
|
||||
String.prototype.replaceAll = function (search, replacement) {
|
||||
var target = this;
|
||||
return target.split(search).join(replacement);
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
const queryString: any = require("query-string");
|
||||
const options: any = queryString.parse(location.search);
|
||||
export let queryParamOptions: any = {
|
||||
const queryString = require("query-string");
|
||||
const options = queryString.parse(location.search);
|
||||
export let queryParamOptions = {
|
||||
embedProvider: null,
|
||||
abtVariant: null,
|
||||
campaign: null,
|
||||
|
@ -10,9 +10,9 @@ import { ExplainedResult } from "./explained_result";
|
||||
import { decompressX64, compressX64 } from "./lzstring";
|
||||
import { asyncCompressor, compressionPrefix } from "./async_compression";
|
||||
import { compressObject, decompressObject } from "../savegame/savegame_compressor";
|
||||
const debounce: any = require("debounce-promise");
|
||||
const logger: any = createLogger("read_write_proxy");
|
||||
const salt: any = accessNestedPropertyReverse(globalConfig, ["file", "info"]);
|
||||
const debounce = require("debounce-promise");
|
||||
const logger = createLogger("read_write_proxy");
|
||||
const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]);
|
||||
// Helper which only writes / reads if verify() works. Also performs migration
|
||||
export class ReadWriteProxy {
|
||||
public app: Application = app;
|
||||
@ -23,47 +23,47 @@ export class ReadWriteProxy {
|
||||
constructor(app, filename) {
|
||||
// TODO: EXTREMELY HACKY! To verify we need to do this a step later
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
// -- Methods to override
|
||||
/** {} */
|
||||
verify(data: any): ExplainedResult {
|
||||
verify(data): ExplainedResult {
|
||||
abstract;
|
||||
return ExplainedResult.bad();
|
||||
}
|
||||
// Should return the default data
|
||||
getDefaultData(): any {
|
||||
getDefaultData() {
|
||||
abstract;
|
||||
return {};
|
||||
}
|
||||
// Should return the current version as an integer
|
||||
getCurrentVersion(): any {
|
||||
getCurrentVersion() {
|
||||
abstract;
|
||||
return 0;
|
||||
}
|
||||
// Should migrate the data (Modify in place)
|
||||
/** {} */
|
||||
migrate(data: any): ExplainedResult {
|
||||
migrate(data): ExplainedResult {
|
||||
abstract;
|
||||
return ExplainedResult.bad();
|
||||
}
|
||||
// -- / Methods
|
||||
// Resets whole data, returns promise
|
||||
resetEverythingAsync(): any {
|
||||
resetEverythingAsync() {
|
||||
logger.warn("Reset data to default");
|
||||
this.currentData = this.getDefaultData();
|
||||
return this.writeAsync();
|
||||
}
|
||||
static serializeObject(obj: object): any {
|
||||
const jsonString: any = JSON.stringify(compressObject(obj));
|
||||
const checksum: any = computeCrc(jsonString + salt);
|
||||
static serializeObject(obj: object) {
|
||||
const jsonString = JSON.stringify(compressObject(obj));
|
||||
const checksum = computeCrc(jsonString + salt);
|
||||
return compressionPrefix + compressX64(checksum + jsonString);
|
||||
}
|
||||
static deserializeObject(text: object): any {
|
||||
const decompressed: any = decompressX64(text.substr(compressionPrefix.length));
|
||||
static deserializeObject(text: object) {
|
||||
const decompressed = decompressX64(text.substr(compressionPrefix.length));
|
||||
if (!decompressed) {
|
||||
// LZ string decompression failure
|
||||
throw new Error("bad-content / decompression-failed");
|
||||
@ -73,17 +73,17 @@ export class ReadWriteProxy {
|
||||
throw new Error("bad-content / payload-too-small");
|
||||
}
|
||||
// Compare stored checksum with actual checksum
|
||||
const checksum: any = decompressed.substring(0, 40);
|
||||
const jsonString: any = decompressed.substr(40);
|
||||
const desiredChecksum: any = checksum.startsWith(CRC_PREFIX)
|
||||
const checksum = decompressed.substring(0, 40);
|
||||
const jsonString = decompressed.substr(40);
|
||||
const desiredChecksum = checksum.startsWith(CRC_PREFIX)
|
||||
? computeCrc(jsonString + salt)
|
||||
: sha1(jsonString + salt);
|
||||
if (desiredChecksum !== checksum) {
|
||||
// Checksum mismatch
|
||||
throw new Error("bad-content / checksum-mismatch");
|
||||
}
|
||||
const parsed: any = JSON.parse(jsonString);
|
||||
const decoded: any = decompressObject(parsed);
|
||||
const parsed = JSON.parse(jsonString);
|
||||
const decoded = decompressObject(parsed);
|
||||
return decoded;
|
||||
}
|
||||
/**
|
||||
@ -92,7 +92,7 @@ export class ReadWriteProxy {
|
||||
* {}
|
||||
*/
|
||||
writeAsync(): Promise<void> {
|
||||
const verifyResult: any = this.internalVerifyEntry(this.currentData);
|
||||
const verifyResult = this.internalVerifyEntry(this.currentData);
|
||||
if (!verifyResult.result) {
|
||||
logger.error("Tried to write invalid data to", this.filename, "reason:", verifyResult.reason);
|
||||
return Promise.reject(verifyResult.reason);
|
||||
@ -106,24 +106,24 @@ export class ReadWriteProxy {
|
||||
doWriteAsync(): Promise<void> {
|
||||
return asyncCompressor
|
||||
.compressObjectAsync(this.currentData)
|
||||
.then((compressed: any): any => {
|
||||
.then(compressed => {
|
||||
return this.app.storage.writeFileAsync(this.filename, compressed);
|
||||
})
|
||||
.then((): any => {
|
||||
.then(() => {
|
||||
logger.log("📄 Wrote", this.filename);
|
||||
})
|
||||
.catch((err: any): any => {
|
||||
.catch(err => {
|
||||
logger.error("Failed to write", this.filename, ":", err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
// Reads the data asynchronously, fails if verify() fails
|
||||
readAsync(): any {
|
||||
readAsync() {
|
||||
// Start read request
|
||||
return (this.app.storage
|
||||
.readFileAsync(this.filename)
|
||||
// Check for errors during read
|
||||
.catch((err: any): any => {
|
||||
.catch(err => {
|
||||
if (err === FILE_NOT_FOUND) {
|
||||
logger.log("File not found, using default data");
|
||||
// File not found or unreadable, assume default file
|
||||
@ -133,13 +133,13 @@ export class ReadWriteProxy {
|
||||
})
|
||||
// Decrypt data (if its encrypted)
|
||||
// @ts-ignore
|
||||
.then((rawData: any): any => {
|
||||
.then(rawData => {
|
||||
if (rawData == null) {
|
||||
// So, the file has not been found, use default data
|
||||
return JSON.stringify(compressObject(this.getDefaultData()));
|
||||
}
|
||||
if (rawData.startsWith(compressionPrefix)) {
|
||||
const decompressed: any = decompressX64(rawData.substr(compressionPrefix.length));
|
||||
const decompressed = decompressX64(rawData.substr(compressionPrefix.length));
|
||||
if (!decompressed) {
|
||||
// LZ string decompression failure
|
||||
return Promise.reject("bad-content / decompression-failed");
|
||||
@ -149,9 +149,9 @@ export class ReadWriteProxy {
|
||||
return Promise.reject("bad-content / payload-too-small");
|
||||
}
|
||||
// Compare stored checksum with actual checksum
|
||||
const checksum: any = decompressed.substring(0, 40);
|
||||
const jsonString: any = decompressed.substr(40);
|
||||
const desiredChecksum: any = checksum.startsWith(CRC_PREFIX)
|
||||
const checksum = decompressed.substring(0, 40);
|
||||
const jsonString = decompressed.substr(40);
|
||||
const desiredChecksum = checksum.startsWith(CRC_PREFIX)
|
||||
? computeCrc(jsonString + salt)
|
||||
: sha1(jsonString + salt);
|
||||
if (desiredChecksum !== checksum) {
|
||||
@ -168,33 +168,33 @@ export class ReadWriteProxy {
|
||||
return rawData;
|
||||
})
|
||||
// Parse JSON, this could throw but that's fine
|
||||
.then((res: any): any => {
|
||||
.then(res => {
|
||||
try {
|
||||
return JSON.parse(res);
|
||||
}
|
||||
catch (ex: any) {
|
||||
catch (ex) {
|
||||
logger.error("Failed to parse file content of", this.filename, ":", ex, "(content was:", res, ")");
|
||||
throw new Error("invalid-serialized-data");
|
||||
}
|
||||
})
|
||||
// Decompress
|
||||
.then((compressed: any): any => decompressObject(compressed))
|
||||
.then(compressed => decompressObject(compressed))
|
||||
// Verify basic structure
|
||||
.then((contents: any): any => {
|
||||
const result: any = this.internalVerifyBasicStructure(contents);
|
||||
.then(contents => {
|
||||
const result = this.internalVerifyBasicStructure(contents);
|
||||
if (!result.isGood()) {
|
||||
return Promise.reject("verify-failed: " + result.reason);
|
||||
}
|
||||
return contents;
|
||||
})
|
||||
// Check version and migrate if required
|
||||
.then((contents: any): any => {
|
||||
.then(contents => {
|
||||
if (contents.version > this.getCurrentVersion()) {
|
||||
return Promise.reject("stored-data-is-newer");
|
||||
}
|
||||
if (contents.version < 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()) {
|
||||
return Promise.reject("migration-failed: " + migrationResult.reason);
|
||||
}
|
||||
@ -202,8 +202,8 @@ export class ReadWriteProxy {
|
||||
return contents;
|
||||
})
|
||||
// Verify
|
||||
.then((contents: any): any => {
|
||||
const verifyResult: any = this.internalVerifyEntry(contents);
|
||||
.then(contents => {
|
||||
const verifyResult = this.internalVerifyEntry(contents);
|
||||
if (!verifyResult.result) {
|
||||
logger.error("Read invalid data from", this.filename, "reason:", verifyResult.reason, "contents:", contents);
|
||||
return Promise.reject("invalid-data: " + verifyResult.reason);
|
||||
@ -211,13 +211,13 @@ export class ReadWriteProxy {
|
||||
return contents;
|
||||
})
|
||||
// Store
|
||||
.then((contents: any): any => {
|
||||
.then(contents => {
|
||||
this.currentData = contents;
|
||||
logger.log("📄 Read data with version", this.currentData.version, "from", this.filename);
|
||||
return contents;
|
||||
})
|
||||
// Catchall
|
||||
.catch((err: any): any => {
|
||||
.catch(err => {
|
||||
return Promise.reject("Failed to read " + this.filename + ": " + err);
|
||||
}));
|
||||
}
|
||||
@ -230,7 +230,7 @@ export class ReadWriteProxy {
|
||||
}
|
||||
// Internal
|
||||
/** {} */
|
||||
internalVerifyBasicStructure(data: any): ExplainedResult {
|
||||
internalVerifyBasicStructure(data): ExplainedResult {
|
||||
if (!data) {
|
||||
return ExplainedResult.bad("Data is empty");
|
||||
}
|
||||
@ -240,11 +240,11 @@ export class ReadWriteProxy {
|
||||
return ExplainedResult.good();
|
||||
}
|
||||
/** {} */
|
||||
internalVerifyEntry(data: any): ExplainedResult {
|
||||
internalVerifyEntry(data): ExplainedResult {
|
||||
if (data.version !== 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()) {
|
||||
return verifyStructureError;
|
||||
}
|
||||
|
@ -12,29 +12,29 @@ export class Rectangle {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
static fromTwoPoints(p1: Vector, p2: Vector): any {
|
||||
const left: any = Math.min(p1.x, p2.x);
|
||||
const top: any = Math.min(p1.y, p2.y);
|
||||
const right: any = Math.max(p1.x, p2.x);
|
||||
const bottom: any = Math.max(p1.y, p2.y);
|
||||
static fromTwoPoints(p1: Vector, p2: Vector) {
|
||||
const left = Math.min(p1.x, p2.x);
|
||||
const top = Math.min(p1.y, p2.y);
|
||||
const right = Math.max(p1.x, p2.x);
|
||||
const bottom = Math.max(p1.y, p2.y);
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
@ -54,7 +54,7 @@ export class Rectangle {
|
||||
/**
|
||||
* 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) &&
|
||||
epsilonCompare(this.y, other.y, epsilon) &&
|
||||
epsilonCompare(this.w, other.w, epsilon) &&
|
||||
@ -106,28 +106,28 @@ export class Rectangle {
|
||||
/**
|
||||
* Sets the right side of the rect without moving it
|
||||
*/
|
||||
setRight(right: number): any {
|
||||
setRight(right: number) {
|
||||
this.w = right - this.x;
|
||||
}
|
||||
/**
|
||||
* Sets the bottom side of the rect without moving it
|
||||
*/
|
||||
setBottom(bottom: number): any {
|
||||
setBottom(bottom: number) {
|
||||
this.h = bottom - this.y;
|
||||
}
|
||||
/**
|
||||
* Sets the top side of the rect without scaling it
|
||||
*/
|
||||
setTop(top: number): any {
|
||||
const bottom: any = this.bottom();
|
||||
setTop(top: number) {
|
||||
const bottom = this.bottom();
|
||||
this.y = top;
|
||||
this.setBottom(bottom);
|
||||
}
|
||||
/**
|
||||
* Sets the left side of the rect without scaling it
|
||||
*/
|
||||
setLeft(left: number): any {
|
||||
const right: any = this.right();
|
||||
setLeft(left: number) {
|
||||
const right = this.right();
|
||||
this.x = left;
|
||||
this.setRight(right);
|
||||
}
|
||||
@ -148,14 +148,14 @@ export class Rectangle {
|
||||
/**
|
||||
* Moves the rectangle by the given parameters
|
||||
*/
|
||||
moveBy(x: number, y: number): any {
|
||||
moveBy(x: number, y: number) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
}
|
||||
/**
|
||||
* Moves the rectangle by the given vector
|
||||
*/
|
||||
moveByVector(vec: Vector): any {
|
||||
moveByVector(vec: Vector) {
|
||||
this.x += vec.x;
|
||||
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
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
@ -212,10 +212,10 @@ export class Rectangle {
|
||||
* {}
|
||||
*/
|
||||
getIntersection(rect: Rectangle): Rectangle | null {
|
||||
const left: any = Math.max(this.x, rect.x);
|
||||
const top: any = Math.max(this.y, rect.y);
|
||||
const right: any = Math.min(this.x + this.w, rect.x + rect.w);
|
||||
const bottom: any = Math.min(this.y + this.h, rect.y + rect.h);
|
||||
const left = Math.max(this.x, rect.x);
|
||||
const top = Math.max(this.y, rect.y);
|
||||
const right = Math.min(this.x + this.w, rect.x + rect.w);
|
||||
const bottom = Math.min(this.y + this.h, rect.y + rect.h);
|
||||
if (right <= left || bottom <= top) {
|
||||
return null;
|
||||
}
|
||||
@ -224,14 +224,14 @@ export class Rectangle {
|
||||
/**
|
||||
* Returns whether the rectangle fully intersects the given rectangle
|
||||
*/
|
||||
intersectsFully(rect: Rectangle): any {
|
||||
const intersection: any = this.getIntersection(rect);
|
||||
intersectsFully(rect: Rectangle) {
|
||||
const intersection = this.getIntersection(rect);
|
||||
return intersection && Math.abs(intersection.w * intersection.h - rect.w * rect.h) < 0.001;
|
||||
}
|
||||
/**
|
||||
* Returns the union of this rectangle with another
|
||||
*/
|
||||
getUnion(rect: Rectangle): any {
|
||||
getUnion(rect: Rectangle) {
|
||||
if (this.isEmpty()) {
|
||||
// If this is rect is empty, return the other one
|
||||
return rect.clone();
|
||||
@ -241,16 +241,16 @@ export class Rectangle {
|
||||
return this.clone();
|
||||
}
|
||||
// Find contained area
|
||||
const left: any = Math.min(this.x, rect.x);
|
||||
const top: any = Math.min(this.y, rect.y);
|
||||
const right: any = Math.max(this.right(), rect.right());
|
||||
const bottom: any = Math.max(this.bottom(), rect.bottom());
|
||||
const left = Math.min(this.x, rect.x);
|
||||
const top = Math.min(this.y, rect.y);
|
||||
const right = Math.max(this.right(), rect.right());
|
||||
const bottom = Math.max(this.bottom(), rect.bottom());
|
||||
return Rectangle.fromTRBL(top, right, bottom, left);
|
||||
}
|
||||
/**
|
||||
* Good for caching stuff
|
||||
*/
|
||||
toCompareableString(): any {
|
||||
toCompareableString() {
|
||||
return (round2Digits(this.x) +
|
||||
"/" +
|
||||
round2Digits(this.y) +
|
||||
@ -262,7 +262,7 @@ export class Rectangle {
|
||||
/**
|
||||
* Good for printing stuff
|
||||
*/
|
||||
toString(): any {
|
||||
toString() {
|
||||
return ("[x:" +
|
||||
round2Digits(this.x) +
|
||||
"| y:" +
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { createLogger } from "./logging";
|
||||
import { fastArrayDeleteValueIfContained } from "./utils";
|
||||
const logger: any = createLogger("request_channel");
|
||||
const logger = createLogger("request_channel");
|
||||
// Thrown when a request is aborted
|
||||
export const PROMISE_ABORTED: any = "promise-aborted";
|
||||
export const PROMISE_ABORTED = "promise-aborted";
|
||||
export class RequestChannel {
|
||||
public pendingPromises: Array<Promise> = [];
|
||||
|
||||
@ -14,9 +14,9 @@ export class RequestChannel {
|
||||
*/
|
||||
watch(promise: Promise<any>): Promise<any> {
|
||||
// log(this, "Added new promise:", promise, "(pending =", this.pendingPromises.length, ")");
|
||||
let cancelled: any = false;
|
||||
const wrappedPromise: any = new Promise((resolve: any, reject: any): any => {
|
||||
promise.then((result: any): any => {
|
||||
let cancelled = false;
|
||||
const wrappedPromise = new Promise((resolve, reject) => {
|
||||
promise.then(result => {
|
||||
// Remove from pending promises
|
||||
fastArrayDeleteValueIfContained(this.pendingPromises, wrappedPromise);
|
||||
// If not cancelled, resolve promise with same payload
|
||||
@ -27,7 +27,7 @@ export class RequestChannel {
|
||||
logger.warn("Not resolving because promise got cancelled");
|
||||
// reject.call(this, PROMISE_ABORTED);
|
||||
}
|
||||
}, (err: any): any => {
|
||||
}, err => {
|
||||
// Remove from pending promises
|
||||
fastArrayDeleteValueIfContained(this.pendingPromises, wrappedPromise);
|
||||
// If not cancelled, reject promise with same payload
|
||||
@ -42,17 +42,17 @@ export class RequestChannel {
|
||||
});
|
||||
// Add cancel handler
|
||||
// @ts-ignore
|
||||
wrappedPromise.cancel = function (): any {
|
||||
wrappedPromise.cancel = function () {
|
||||
cancelled = true;
|
||||
};
|
||||
this.pendingPromises.push(wrappedPromise);
|
||||
return wrappedPromise;
|
||||
}
|
||||
cancelAll(): any {
|
||||
cancelAll() {
|
||||
if (this.pendingPromises.length > 0) {
|
||||
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
|
||||
this.pendingPromises[i].cancel();
|
||||
}
|
||||
|
@ -11,23 +11,23 @@ export class RestrictionManager extends ReadWriteProxy {
|
||||
super(app, "restriction-flags.bin");
|
||||
}
|
||||
// -- RW Proxy Impl
|
||||
verify(data: any): any {
|
||||
verify(data: any) {
|
||||
return ExplainedResult.good();
|
||||
}
|
||||
|
||||
getDefaultData(): any {
|
||||
getDefaultData() {
|
||||
return {
|
||||
version: this.getCurrentVersion(),
|
||||
};
|
||||
}
|
||||
|
||||
getCurrentVersion(): any {
|
||||
getCurrentVersion() {
|
||||
return 1;
|
||||
}
|
||||
migrate(data: any): any {
|
||||
migrate(data: any) {
|
||||
return ExplainedResult.good();
|
||||
}
|
||||
initialize(): any {
|
||||
initialize() {
|
||||
return this.readAsync();
|
||||
}
|
||||
// -- End RW Proxy Impl
|
||||
|
@ -1,11 +1,11 @@
|
||||
// ALEA RNG
|
||||
function Mash(): any {
|
||||
var n: any = 0xefc8249d;
|
||||
return function (data: any): any {
|
||||
function Mash() {
|
||||
var n = 0xefc8249d;
|
||||
return function (data) {
|
||||
data = data.toString();
|
||||
for (var i: any = 0; i < data.length; i++) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
n += data.charCodeAt(i);
|
||||
var h: any = 0.02519603282416938 * n;
|
||||
var h = 0.02519603282416938 * n;
|
||||
n = h >>> 0;
|
||||
h -= n;
|
||||
h *= n;
|
||||
@ -16,13 +16,13 @@ function Mash(): any {
|
||||
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
|
||||
var c: any = 1;
|
||||
var mash: any = Mash();
|
||||
let s0: any = mash(" ");
|
||||
let s1: any = mash(" ");
|
||||
let s2: any = mash(" ");
|
||||
var c = 1;
|
||||
var mash = Mash();
|
||||
let s0 = mash(" ");
|
||||
let s1 = mash(" ");
|
||||
let s2 = mash(" ");
|
||||
s0 -= mash(seed);
|
||||
if (s0 < 0) {
|
||||
s0 += 1;
|
||||
@ -36,16 +36,16 @@ function makeNewRng(seed: number | string): any {
|
||||
s2 += 1;
|
||||
}
|
||||
mash = null;
|
||||
var random: any = function (): any {
|
||||
var t: any = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
|
||||
var random = function () {
|
||||
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
|
||||
s0 = s1;
|
||||
s1 = s2;
|
||||
return (s2 = t - (c = t | 0));
|
||||
};
|
||||
random.exportState = function (): any {
|
||||
random.exportState = function () {
|
||||
return [s0, s1, s2, c];
|
||||
};
|
||||
random.importState = function (i: any): any {
|
||||
random.importState = function (i) {
|
||||
s0 = +i[0] || 0;
|
||||
s1 = +i[1] || 0;
|
||||
s2 = +i[2] || 0;
|
||||
@ -61,7 +61,7 @@ export class RandomNumberGenerator {
|
||||
/**
|
||||
* Re-seeds the generator
|
||||
*/
|
||||
reseed(seed: number | string): any {
|
||||
reseed(seed: number | string) {
|
||||
this.internalRng = makeNewRng(seed || Math.random());
|
||||
}
|
||||
/**
|
||||
@ -73,8 +73,8 @@ export class RandomNumberGenerator {
|
||||
/**
|
||||
* Random choice of an array
|
||||
*/
|
||||
choice(array: array): any {
|
||||
const index: any = this.nextIntRange(0, array.length);
|
||||
choice(array: array) {
|
||||
const index = this.nextIntRange(0, array.length);
|
||||
return array[index];
|
||||
}
|
||||
/**
|
||||
@ -96,7 +96,7 @@ export class RandomNumberGenerator {
|
||||
/**
|
||||
* Updates the seed
|
||||
*/
|
||||
setSeed(seed: number): any {
|
||||
setSeed(seed: number) {
|
||||
this.internalRng = makeNewRng(seed);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { createHash } from "rusha";
|
||||
import crc32 from "crc/crc32";
|
||||
import { decompressX64 } from "./lzstring";
|
||||
export function sha1(str: any): any {
|
||||
export function sha1(str) {
|
||||
return createHash().update(str).digest("hex");
|
||||
}
|
||||
// Window.location.host
|
||||
export function getNameOfProvider(): any {
|
||||
export function getNameOfProvider() {
|
||||
return window[decompressX64("DYewxghgLgliB2Q")][decompressX64("BYewzgLgdghgtgUyA")];
|
||||
}
|
||||
// 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
|
||||
*/
|
||||
export function computeCrc(str: string): any {
|
||||
export function computeCrc(str: string) {
|
||||
return CRC_PREFIX + crc32(str).toString(16).padStart(8, "0");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export const STOP_PROPAGATION: any = "stop_propagation";
|
||||
export const STOP_PROPAGATION = "stop_propagation";
|
||||
export class Signal {
|
||||
public receivers = [];
|
||||
public modifyCount = 0;
|
||||
@ -8,7 +8,7 @@ export class Signal {
|
||||
/**
|
||||
* Adds a new signal listener
|
||||
*/
|
||||
add(receiver: function, scope: object = null): any {
|
||||
add(receiver: function, scope: object = null) {
|
||||
assert(receiver, "receiver is null");
|
||||
this.receivers.push({ receiver, scope });
|
||||
++this.modifyCount;
|
||||
@ -16,7 +16,7 @@ export class Signal {
|
||||
/**
|
||||
* Adds a new signal listener
|
||||
*/
|
||||
addToTop(receiver: function, scope: object = null): any {
|
||||
addToTop(receiver: function, scope: object = null) {
|
||||
assert(receiver, "receiver is null");
|
||||
this.receivers.unshift({ receiver, scope });
|
||||
++this.modifyCount;
|
||||
@ -25,11 +25,11 @@ export class Signal {
|
||||
* Dispatches the signal
|
||||
* @param {} payload
|
||||
*/
|
||||
dispatch(): any {
|
||||
const modifyState: any = this.modifyCount;
|
||||
const n: any = this.receivers.length;
|
||||
for (let i: any = 0; i < n; ++i) {
|
||||
const { receiver, scope }: any = this.receivers[i];
|
||||
dispatch() {
|
||||
const modifyState = this.modifyCount;
|
||||
const n = this.receivers.length;
|
||||
for (let i = 0; i < n; ++i) {
|
||||
const { receiver, scope } = this.receivers[i];
|
||||
if (receiver.apply(scope, arguments) === STOP_PROPAGATION) {
|
||||
return STOP_PROPAGATION;
|
||||
}
|
||||
@ -42,10 +42,10 @@ export class Signal {
|
||||
/**
|
||||
* Removes a receiver
|
||||
*/
|
||||
remove(receiver: function): any {
|
||||
let index: any = null;
|
||||
const n: any = this.receivers.length;
|
||||
for (let i: any = 0; i < n; ++i) {
|
||||
remove(receiver: function) {
|
||||
let index = null;
|
||||
const n = this.receivers.length;
|
||||
for (let i = 0; i < n; ++i) {
|
||||
if (this.receivers[i].receiver === receiver) {
|
||||
index = i;
|
||||
break;
|
||||
@ -58,7 +58,7 @@ export class Signal {
|
||||
/**
|
||||
* Removes all receivers
|
||||
*/
|
||||
removeAll(): any {
|
||||
removeAll() {
|
||||
this.receivers = [];
|
||||
++this.modifyCount;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createLogger } from "./logging";
|
||||
const logger: any = createLogger("singleton_factory");
|
||||
const logger = createLogger("singleton_factory");
|
||||
// simple factory pattern
|
||||
export class SingletonFactory {
|
||||
public id = id;
|
||||
@ -8,14 +8,14 @@ export class SingletonFactory {
|
||||
|
||||
constructor(id) {
|
||||
}
|
||||
getId(): any {
|
||||
getId() {
|
||||
return this.id;
|
||||
}
|
||||
register(classHandle: any): any {
|
||||
register(classHandle) {
|
||||
// First, construct instance
|
||||
const instance: any = new classHandle();
|
||||
const instance = new classHandle();
|
||||
// Extract id
|
||||
const id: any = instance.getId();
|
||||
const id = instance.getId();
|
||||
assert(id, "Factory: Invalid id for class " + classHandle.name + ": " + id);
|
||||
// Check duplicates
|
||||
assert(!this.idToEntry[id], "Duplicate factory entry for " + id);
|
||||
@ -35,7 +35,7 @@ export class SingletonFactory {
|
||||
* {}
|
||||
*/
|
||||
findById(id: string): object {
|
||||
const entry: any = this.idToEntry[id];
|
||||
const entry = this.idToEntry[id];
|
||||
if (!entry) {
|
||||
logger.error("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 {
|
||||
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) {
|
||||
return this.entries[i];
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { DrawParameters } from "./draw_parameters";
|
||||
import { Rectangle } from "./rectangle";
|
||||
import { round3Digits } from "./utils";
|
||||
export const ORIGINAL_SPRITE_SCALE: any = "0.75";
|
||||
export const FULL_CLIP_RECT: any = new Rectangle(0, 0, 1, 1);
|
||||
const EXTRUDE: any = 0.1;
|
||||
export const ORIGINAL_SPRITE_SCALE = "0.75";
|
||||
export const FULL_CLIP_RECT = new Rectangle(0, 0, 1, 1);
|
||||
const EXTRUDE = 0.1;
|
||||
export class BaseSprite {
|
||||
/**
|
||||
* Returns the raw handle
|
||||
@ -17,7 +17,7 @@ export class BaseSprite {
|
||||
/**
|
||||
* 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
|
||||
abstract;
|
||||
}
|
||||
@ -49,18 +49,18 @@ export class AtlasSprite extends BaseSprite {
|
||||
constructor(spriteName = "sprite") {
|
||||
super();
|
||||
}
|
||||
getRawTexture(): any {
|
||||
getRawTexture() {
|
||||
return this.linksByResolution[ORIGINAL_SPRITE_SCALE].atlas;
|
||||
}
|
||||
/**
|
||||
* Draws the sprite onto a regular context using no contexts
|
||||
* @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) {
|
||||
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) {
|
||||
throw new Error("draw: Link for " +
|
||||
this.spriteName +
|
||||
@ -70,30 +70,30 @@ export class AtlasSprite extends BaseSprite {
|
||||
Object.keys(this.linksByResolution) +
|
||||
")");
|
||||
}
|
||||
const width: any = w || link.w;
|
||||
const height: any = h || link.h;
|
||||
const scaleW: any = width / link.w;
|
||||
const scaleH: any = height / link.h;
|
||||
const width = w || link.w;
|
||||
const height = h || link.h;
|
||||
const scaleW = width / link.w;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* 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) {
|
||||
assert(parameters instanceof DrawParameters, "Not a valid context");
|
||||
assert(!!w && w > 0, "Not a valid width:" + w);
|
||||
assert(!!h && h > 0, "Not a valid height:" + h);
|
||||
}
|
||||
const visibleRect: any = parameters.visibleRect;
|
||||
const scale: any = parameters.desiredAtlasScale;
|
||||
const link: any = this.linksByResolution[scale];
|
||||
const visibleRect = parameters.visibleRect;
|
||||
const scale = parameters.desiredAtlasScale;
|
||||
const link = this.linksByResolution[scale];
|
||||
if (!link) {
|
||||
throw new Error("drawCached: Link for " +
|
||||
this.spriteName +
|
||||
@ -103,19 +103,19 @@ export class AtlasSprite extends BaseSprite {
|
||||
Object.keys(this.linksByResolution) +
|
||||
")");
|
||||
}
|
||||
const scaleW: any = w / link.w;
|
||||
const scaleH: any = h / link.h;
|
||||
let destX: any = x + link.packOffsetX * scaleW;
|
||||
let destY: any = y + link.packOffsetY * scaleH;
|
||||
let destW: any = link.packedW * scaleW;
|
||||
let destH: any = link.packedH * scaleH;
|
||||
let srcX: any = link.packedX;
|
||||
let srcY: any = link.packedY;
|
||||
let srcW: any = link.packedW;
|
||||
let srcH: any = link.packedH;
|
||||
let intersection: any = null;
|
||||
const scaleW = w / link.w;
|
||||
const scaleH = h / link.h;
|
||||
let destX = x + link.packOffsetX * scaleW;
|
||||
let destY = y + link.packOffsetY * scaleH;
|
||||
let destW = link.packedW * scaleW;
|
||||
let destH = link.packedH * scaleH;
|
||||
let srcX = link.packedX;
|
||||
let srcY = link.packedY;
|
||||
let srcW = link.packedW;
|
||||
let srcH = link.packedH;
|
||||
let intersection = null;
|
||||
if (clipping) {
|
||||
const rect: any = new Rectangle(destX, destY, destW, destH);
|
||||
const rect = new Rectangle(destX, destY, destW, destH);
|
||||
intersection = rect.getIntersection(visibleRect);
|
||||
if (!intersection) {
|
||||
return;
|
||||
@ -140,15 +140,15 @@ export class AtlasSprite extends BaseSprite {
|
||||
/**
|
||||
* 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) {
|
||||
assert(parameters instanceof DrawParameters, "Not a valid context");
|
||||
assert(!!w && w > 0, "Not a valid width:" + w);
|
||||
assert(!!h && h > 0, "Not a valid height:" + h);
|
||||
assert(clipRect, "No clip rect given!");
|
||||
}
|
||||
const scale: any = parameters.desiredAtlasScale;
|
||||
const link: any = this.linksByResolution[scale];
|
||||
const scale = parameters.desiredAtlasScale;
|
||||
const link = this.linksByResolution[scale];
|
||||
if (!link) {
|
||||
throw new Error("drawCachedWithClipRect: Link for " +
|
||||
this.spriteName +
|
||||
@ -158,16 +158,16 @@ export class AtlasSprite extends BaseSprite {
|
||||
Object.keys(this.linksByResolution) +
|
||||
")");
|
||||
}
|
||||
const scaleW: any = w / link.w;
|
||||
const scaleH: any = h / link.h;
|
||||
let destX: any = x + link.packOffsetX * scaleW + clipRect.x * w;
|
||||
let destY: any = y + link.packOffsetY * scaleH + clipRect.y * h;
|
||||
let destW: any = link.packedW * scaleW * clipRect.w;
|
||||
let destH: any = link.packedH * scaleH * clipRect.h;
|
||||
let srcX: any = link.packedX + clipRect.x * link.packedW;
|
||||
let srcY: any = link.packedY + clipRect.y * link.packedH;
|
||||
let srcW: any = link.packedW * clipRect.w;
|
||||
let srcH: any = link.packedH * clipRect.h;
|
||||
const scaleW = w / link.w;
|
||||
const scaleH = h / link.h;
|
||||
let destX = x + link.packOffsetX * scaleW + clipRect.x * w;
|
||||
let destY = y + link.packOffsetY * scaleH + clipRect.y * h;
|
||||
let destW = link.packedW * scaleW * clipRect.w;
|
||||
let destH = link.packedH * scaleH * clipRect.h;
|
||||
let srcX = link.packedX + clipRect.x * link.packedW;
|
||||
let srcY = link.packedY + clipRect.y * link.packedH;
|
||||
let srcW = link.packedW * clipRect.w;
|
||||
let srcH = link.packedH * clipRect.h;
|
||||
parameters.context.drawImage(link.atlas,
|
||||
// atlas src pos
|
||||
srcX, srcY,
|
||||
@ -179,15 +179,15 @@ export class AtlasSprite extends BaseSprite {
|
||||
/**
|
||||
* 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.innerHTML = this.getAsHTML(w, h);
|
||||
}
|
||||
/**
|
||||
* Returns the html to render as icon
|
||||
*/
|
||||
getAsHTML(w: number, h: number): any {
|
||||
const link: any = this.linksByResolution["0.5"];
|
||||
getAsHTML(w: number, h: number) {
|
||||
const link = this.linksByResolution["0.5"];
|
||||
if (!link) {
|
||||
throw new Error("getAsHTML: Link for " +
|
||||
this.spriteName +
|
||||
@ -197,30 +197,30 @@ export class AtlasSprite extends BaseSprite {
|
||||
")");
|
||||
}
|
||||
// Find out how much we have to scale it so that it fits
|
||||
const scaleX: any = w / link.w;
|
||||
const scaleY: any = h / link.h;
|
||||
const scaleX = w / link.w;
|
||||
const scaleY = h / link.h;
|
||||
// Find out how big the scaled atlas is
|
||||
const atlasW: any = link.atlas.width * scaleX;
|
||||
const atlasH: any = link.atlas.height * scaleY;
|
||||
const atlasW = link.atlas.width * scaleX;
|
||||
const atlasH = link.atlas.height * scaleY;
|
||||
// @ts-ignore
|
||||
const srcSafe: any = link.atlas.src.replaceAll("\\", "/");
|
||||
const srcSafe = link.atlas.src.replaceAll("\\", "/");
|
||||
// Find out how big we render the sprite
|
||||
const widthAbsolute: any = scaleX * link.packedW;
|
||||
const heightAbsolute: any = scaleY * link.packedH;
|
||||
const widthAbsolute = scaleX * link.packedW;
|
||||
const heightAbsolute = scaleY * link.packedH;
|
||||
// Compute the position in the relative container
|
||||
const leftRelative: any = (link.packOffsetX * scaleX) / w;
|
||||
const topRelative: any = (link.packOffsetY * scaleY) / h;
|
||||
const widthRelative: any = widthAbsolute / w;
|
||||
const heightRelative: any = heightAbsolute / h;
|
||||
const leftRelative = (link.packOffsetX * scaleX) / w;
|
||||
const topRelative = (link.packOffsetY * scaleY) / h;
|
||||
const widthRelative = widthAbsolute / w;
|
||||
const heightRelative = heightAbsolute / h;
|
||||
// Scale the atlas relative to the width and height of the element
|
||||
const bgW: any = atlasW / widthAbsolute;
|
||||
const bgH: any = atlasH / heightAbsolute;
|
||||
const bgW = atlasW / widthAbsolute;
|
||||
const bgH = atlasH / heightAbsolute;
|
||||
// Figure out what the position of the atlas is
|
||||
const bgX: any = link.packedX * scaleX;
|
||||
const bgY: any = link.packedY * scaleY;
|
||||
const bgX = link.packedX * scaleX;
|
||||
const bgY = link.packedY * scaleY;
|
||||
// Fuck you, whoever thought its a good idea to make background-position work like it does now
|
||||
const bgXRelative: any = -bgX / (widthAbsolute - atlasW);
|
||||
const bgYRelative: any = -bgY / (heightAbsolute - atlasH);
|
||||
const bgXRelative = -bgX / (widthAbsolute - atlasW);
|
||||
const bgYRelative = -bgY / (heightAbsolute - atlasH);
|
||||
return `
|
||||
<span class="spritesheetImage" style="
|
||||
background-image: url('${srcSafe}');
|
||||
@ -243,14 +243,14 @@ export class RegularSprite extends BaseSprite {
|
||||
constructor(sprite, w, h) {
|
||||
super();
|
||||
}
|
||||
getRawTexture(): any {
|
||||
getRawTexture() {
|
||||
return this.sprite;
|
||||
}
|
||||
/**
|
||||
* Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing
|
||||
* 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(x !== undefined, "No x 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
|
||||
* 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(x !== undefined, "No x given");
|
||||
assert(y !== undefined, "No y given");
|
||||
|
@ -3,7 +3,7 @@ import { Entity } from "../game/entity";
|
||||
import { globalConfig } from "./config";
|
||||
import { createLogger } from "./logging";
|
||||
import { Rectangle } from "./rectangle";
|
||||
const logger: any = createLogger("stale_areas");
|
||||
const logger = createLogger("stale_areas");
|
||||
export class StaleAreaDetector {
|
||||
public root = root;
|
||||
public name = name;
|
||||
@ -15,7 +15,7 @@ export class StaleAreaDetector {
|
||||
/**
|
||||
* Invalidates the given area
|
||||
*/
|
||||
invalidate(area: Rectangle): any {
|
||||
invalidate(area: Rectangle) {
|
||||
// logger.log(this.name, "invalidated", area.toString());
|
||||
if (this.staleArea) {
|
||||
this.staleArea = this.staleArea.getUnion(area);
|
||||
@ -28,20 +28,20 @@ export class StaleAreaDetector {
|
||||
* Makes this detector recompute the area of an entity whenever
|
||||
* it changes in any way
|
||||
*/
|
||||
recomputeOnComponentsChanged(components: Array<typeof Component>, tilesAround: number): any {
|
||||
const componentIds: any = components.map((component: any): any => component.getId());
|
||||
recomputeOnComponentsChanged(components: Array<typeof Component>, tilesAround: number) {
|
||||
const componentIds = components.map(component => component.getId());
|
||||
/**
|
||||
* Internal checker method
|
||||
*/
|
||||
const checker: any = (entity: Entity): any => {
|
||||
const checker = (entity: Entity) => {
|
||||
if (!this.root.gameInitialized) {
|
||||
return;
|
||||
}
|
||||
// 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]]) {
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
@ -56,7 +56,7 @@ export class StaleAreaDetector {
|
||||
/**
|
||||
* Updates the stale area
|
||||
*/
|
||||
update(): any {
|
||||
update() {
|
||||
if (this.staleArea) {
|
||||
if (G_IS_DEV && globalConfig.debug.renderChanges) {
|
||||
logger.log(this.name, "is recomputing", this.staleArea.toString());
|
||||
|
@ -5,7 +5,7 @@ import { GameState } from "./game_state";
|
||||
import { createLogger } from "./logging";
|
||||
import { waitNextFrame, removeAllChildren } from "./utils";
|
||||
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.
|
||||
*/
|
||||
@ -21,18 +21,18 @@ export class StateManager {
|
||||
/**
|
||||
* 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
|
||||
const dummy: any = new stateClass();
|
||||
const dummy = new stateClass();
|
||||
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!`);
|
||||
this.stateClasses[key] = stateClass;
|
||||
}
|
||||
/**
|
||||
* Constructs a new state or returns the instance from the cache
|
||||
*/
|
||||
constructState(key: string): any {
|
||||
constructState(key: string) {
|
||||
if (this.stateClasses[key]) {
|
||||
return new this.stateClasses[key]();
|
||||
}
|
||||
@ -41,7 +41,7 @@ export class StateManager {
|
||||
/**
|
||||
* Moves to a given state
|
||||
*/
|
||||
moveToState(key: string, payload: any = {}): any {
|
||||
moveToState(key: string, payload = {}) {
|
||||
if (window.APP_ERROR_OCCURED) {
|
||||
console.warn("Skipping state transition because of application crash");
|
||||
return;
|
||||
@ -53,7 +53,7 @@ export class StateManager {
|
||||
}
|
||||
this.currentState.internalLeaveCallback();
|
||||
// Remove all references
|
||||
for (const stateKey: any in this.currentState) {
|
||||
for (const stateKey in this.currentState) {
|
||||
if (this.currentState.hasOwnProperty(stateKey)) {
|
||||
delete this.currentState[stateKey];
|
||||
}
|
||||
@ -71,13 +71,13 @@ export class StateManager {
|
||||
if (this.currentState.getRemovePreviousContent()) {
|
||||
document.body.innerHTML = this.currentState.internalGetFullHtml();
|
||||
}
|
||||
const dialogParent: any = document.createElement("div");
|
||||
const dialogParent = document.createElement("div");
|
||||
dialogParent.classList.add("modalDialogParent");
|
||||
document.body.appendChild(dialogParent);
|
||||
try {
|
||||
this.currentState.internalEnterCallback(payload);
|
||||
}
|
||||
catch (ex: any) {
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
throw ex;
|
||||
}
|
||||
@ -88,7 +88,7 @@ export class StateManager {
|
||||
key,
|
||||
}, key);
|
||||
MOD_SIGNALS.stateEntered.dispatch(this.currentState);
|
||||
waitNextFrame().then((): any => {
|
||||
waitNextFrame().then(() => {
|
||||
document.body.classList.add("arrived");
|
||||
});
|
||||
return true;
|
||||
|
@ -1,45 +1,45 @@
|
||||
import { T } from "../translations";
|
||||
import { openStandaloneLink } from "./config";
|
||||
export let WEB_STEAM_SSO_AUTHENTICATED: any = false;
|
||||
export async function authorizeViaSSOToken(app: any, dialogs: any): any {
|
||||
export let WEB_STEAM_SSO_AUTHENTICATED = false;
|
||||
export async function authorizeViaSSOToken(app, dialogs) {
|
||||
if (G_IS_STANDALONE) {
|
||||
return;
|
||||
}
|
||||
if (window.location.search.includes("sso_logout_silent")) {
|
||||
window.localStorage.setItem("steam_sso_auth_token", "");
|
||||
window.location.replace("/");
|
||||
return new Promise((): any => null);
|
||||
return new Promise(() => null);
|
||||
}
|
||||
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", "");
|
||||
ok.add((): any => window.location.replace("/"));
|
||||
return new Promise((): any => null);
|
||||
ok.add(() => window.location.replace("/"));
|
||||
return new Promise(() => null);
|
||||
}
|
||||
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", "");
|
||||
getStandalone.add((): any => {
|
||||
getStandalone.add(() => {
|
||||
openStandaloneLink(app, "sso_ownership");
|
||||
window.location.replace("/");
|
||||
});
|
||||
ok.add((): any => window.location.replace("/"));
|
||||
return new Promise((): any => null);
|
||||
ok.add(() => window.location.replace("/"));
|
||||
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) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const apiUrl: any = app.clientApi.getEndpoint();
|
||||
const apiUrl = app.clientApi.getEndpoint();
|
||||
console.warn("Authorizing via token:", token);
|
||||
const verify: any = async (): any => {
|
||||
const token: any = window.localStorage.getItem("steam_sso_auth_token");
|
||||
const verify = async () => {
|
||||
const token = window.localStorage.getItem("steam_sso_auth_token");
|
||||
if (!token) {
|
||||
window.location.replace("?sso_logout");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response: any = await Promise.race([
|
||||
const response = await Promise.race([
|
||||
fetch(apiUrl + "/v1/sso/refresh", {
|
||||
method: "POST",
|
||||
body: token,
|
||||
@ -47,11 +47,11 @@ export async function authorizeViaSSOToken(app: any, dialogs: any): any {
|
||||
"x-api-key": "d5c54aaa491f200709afff082c153ef2",
|
||||
},
|
||||
}),
|
||||
new Promise((resolve: any, reject: any): any => {
|
||||
setTimeout((): any => reject("timeout exceeded"), 20000);
|
||||
new Promise((resolve, reject) => {
|
||||
setTimeout(() => reject("timeout exceeded"), 20000);
|
||||
}),
|
||||
]);
|
||||
const responseText: any = await response.json();
|
||||
const responseText = await response.json();
|
||||
if (!responseText.token) {
|
||||
console.warn("Failed to register");
|
||||
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;
|
||||
WEB_STEAM_SSO_AUTHENTICATED = true;
|
||||
}
|
||||
catch (ex: any) {
|
||||
catch (ex) {
|
||||
console.warn("Auth failure", ex);
|
||||
window.localStorage.setItem("steam_sso_auth_token", "");
|
||||
window.location.replace("/");
|
||||
return new Promise((): any => null);
|
||||
return new Promise(() => null);
|
||||
}
|
||||
};
|
||||
await verify();
|
||||
|
@ -22,7 +22,7 @@ export class TextualGameState extends GameState {
|
||||
/**
|
||||
* Should return the states HTML content.
|
||||
*/
|
||||
getMainContentHTML(): any {
|
||||
getMainContentHTML() {
|
||||
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,
|
||||
* or if coming from the game it moves back to the game again.
|
||||
*/
|
||||
onBackButton(): any {
|
||||
onBackButton() {
|
||||
if (this.backToStateId) {
|
||||
this.moveToState(this.backToStateId, this.backToStatePayload);
|
||||
}
|
||||
@ -49,13 +49,13 @@ export class TextualGameState extends GameState {
|
||||
/**
|
||||
* Returns the default state to go back to
|
||||
*/
|
||||
getDefaultPreviousState(): any {
|
||||
getDefaultPreviousState() {
|
||||
return "MainMenuState";
|
||||
}
|
||||
/**
|
||||
* Goes to a new state, telling him to go back to this state later
|
||||
*/
|
||||
moveToStateAddGoBack(stateId: string): any {
|
||||
moveToStateAddGoBack(stateId: string) {
|
||||
this.moveToState(stateId, {
|
||||
backToStateId: this.key,
|
||||
backToStatePayload: {
|
||||
@ -68,9 +68,9 @@ export class TextualGameState extends GameState {
|
||||
* Removes all click detectors, except the one on the back button. Useful when regenerating
|
||||
* content.
|
||||
*/
|
||||
clearClickDetectorsExceptHeader(): any {
|
||||
for (let i: any = 0; i < this.clickDetectors.length; ++i) {
|
||||
const detector: any = this.clickDetectors[i];
|
||||
clearClickDetectorsExceptHeader() {
|
||||
for (let i = 0; i < this.clickDetectors.length; ++i) {
|
||||
const detector = this.clickDetectors[i];
|
||||
if (detector.element === this.headerElement) {
|
||||
continue;
|
||||
}
|
||||
@ -82,8 +82,8 @@ export class TextualGameState extends GameState {
|
||||
/**
|
||||
* Overrides the GameState implementation to provide our own html
|
||||
*/
|
||||
internalGetFullHtml(): any {
|
||||
let headerHtml: any = "";
|
||||
internalGetFullHtml() {
|
||||
let headerHtml = "";
|
||||
if (this.getStateHeaderTitle()) {
|
||||
headerHtml = `
|
||||
<div class="headerBar">
|
||||
@ -103,14 +103,14 @@ export class TextualGameState extends GameState {
|
||||
/**
|
||||
* Overrides the GameState leave callback to cleanup stuff
|
||||
*/
|
||||
internalLeaveCallback(): any {
|
||||
internalLeaveCallback() {
|
||||
super.internalLeaveCallback();
|
||||
this.dialogs.cleanup();
|
||||
}
|
||||
/**
|
||||
* Overrides the GameState enter callback to setup required stuff
|
||||
*/
|
||||
internalEnterCallback(payload: any): any {
|
||||
internalEnterCallback(payload: any) {
|
||||
super.internalEnterCallback(payload, false);
|
||||
if (payload.backToStateId) {
|
||||
this.backToStateId = payload.backToStateId;
|
||||
@ -126,7 +126,7 @@ export class TextualGameState extends GameState {
|
||||
this.trackClicks(this.headerElement, this.onBackButton);
|
||||
}
|
||||
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.onEnter(payload);
|
||||
}
|
||||
|
@ -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) {
|
||||
// Copy value since the changeHandler call could actually modify our lastSeenValue
|
||||
const valueCopy: any = value;
|
||||
const valueCopy = value;
|
||||
this.lastSeenValue = value;
|
||||
if (changeHandler) {
|
||||
if (changeScope) {
|
||||
@ -30,10 +30,10 @@ export class TrackedState {
|
||||
}
|
||||
}
|
||||
}
|
||||
setSilent(value: any): any {
|
||||
setSilent(value) {
|
||||
this.lastSeenValue = value;
|
||||
}
|
||||
get(): any {
|
||||
get() {
|
||||
return this.lastSeenValue;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { T } from "../translations";
|
||||
import { rando } from "@nastyox/rando.js";
|
||||
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
|
||||
* {}
|
||||
@ -20,8 +20,8 @@ export function getPlatformName(): "android" | "browser" | "ios" | "standalone"
|
||||
* {}
|
||||
*/
|
||||
export function make2DUndefinedArray(w: number, h: number): Array<Array<any>> {
|
||||
const result: any = new Array(w);
|
||||
for (let x: any = 0; x < w; ++x) {
|
||||
const result = new Array(w);
|
||||
for (let x = 0; x < w; ++x) {
|
||||
result[x] = new Array(h);
|
||||
}
|
||||
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)
|
||||
*/
|
||||
export function newEmptyMap(): any {
|
||||
export function newEmptyMap() {
|
||||
return Object.create(null);
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* Access an object in a very annoying way, used for obsfuscation.
|
||||
*/
|
||||
export function accessNestedPropertyReverse(obj: any, keys: Array<string>): any {
|
||||
let result: any = obj;
|
||||
for (let i: any = keys.length - 1; i >= 0; --i) {
|
||||
export function accessNestedPropertyReverse(obj: any, keys: Array<string>) {
|
||||
let result = obj;
|
||||
for (let i = keys.length - 1; i >= 0; --i) {
|
||||
result = result[keys[i]];
|
||||
}
|
||||
return result;
|
||||
@ -59,14 +59,14 @@ export function randomChoice(arr: T[]): T {
|
||||
/**
|
||||
* 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) {
|
||||
throw new Error("Out of bounds");
|
||||
}
|
||||
// When the element is not the last element
|
||||
if (index !== array.length - 1) {
|
||||
// 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;
|
||||
}
|
||||
// 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
|
||||
* 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) {
|
||||
throw new Error("Tried to delete from non array!");
|
||||
}
|
||||
const index: any = array.indexOf(value);
|
||||
const index = array.indexOf(value);
|
||||
if (index < 0) {
|
||||
console.error("Value", value, "not contained in array:", array, "!");
|
||||
return value;
|
||||
@ -90,11 +90,11 @@ export function fastArrayDeleteValue(array: Array<any>, value: any): any {
|
||||
/**
|
||||
* @see fastArrayDeleteValue
|
||||
*/
|
||||
export function fastArrayDeleteValueIfContained(array: Array<any>, value: any): any {
|
||||
export function fastArrayDeleteValueIfContained(array: Array<any>, value: any) {
|
||||
if (array == null) {
|
||||
throw new Error("Tried to delete from non array!");
|
||||
}
|
||||
const index: any = array.indexOf(value);
|
||||
const index = array.indexOf(value);
|
||||
if (index < 0) {
|
||||
return value;
|
||||
}
|
||||
@ -103,7 +103,7 @@ export function fastArrayDeleteValueIfContained(array: Array<any>, value: any):
|
||||
/**
|
||||
* 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) {
|
||||
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
|
||||
*/
|
||||
export function arrayDeleteValue(array: Array<any>, value: any): any {
|
||||
export function arrayDeleteValue(array: Array<any>, value: any) {
|
||||
if (array == null) {
|
||||
throw new Error("Tried to delete from non array!");
|
||||
}
|
||||
const index: any = array.indexOf(value);
|
||||
const index = array.indexOf(value);
|
||||
if (index < 0) {
|
||||
console.error("Value", value, "not contained in array:", array, "!");
|
||||
return value;
|
||||
@ -127,26 +127,26 @@ export function arrayDeleteValue(array: Array<any>, value: any): any {
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* 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) {
|
||||
return num;
|
||||
}
|
||||
if (num < 0.00001) {
|
||||
return 0;
|
||||
}
|
||||
let roundAmount: any = 1;
|
||||
let roundAmount = 1;
|
||||
if (num > 50000) {
|
||||
roundAmount = 10000;
|
||||
}
|
||||
@ -168,7 +168,7 @@ export function findNiceValue(num: number): any {
|
||||
else if (num > 20) {
|
||||
roundAmount = 5;
|
||||
}
|
||||
const niceValue: any = Math.floor(num / roundAmount) * roundAmount;
|
||||
const niceValue = Math.floor(num / roundAmount) * roundAmount;
|
||||
if (num >= 10) {
|
||||
return Math.round(niceValue);
|
||||
}
|
||||
@ -181,7 +181,7 @@ export function findNiceValue(num: number): any {
|
||||
* Finds a nice integer value
|
||||
* @see findNiceValue
|
||||
*/
|
||||
export function findNiceIntegerValue(num: number): any {
|
||||
export function findNiceIntegerValue(num: number) {
|
||||
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 {
|
||||
const sign: any = num < 0 ? "-" : "";
|
||||
const sign = num < 0 ? "-" : "";
|
||||
num = Math.abs(num);
|
||||
if (num > 1e54) {
|
||||
return sign + T.global.infinite;
|
||||
@ -205,17 +205,17 @@ export function formatBigNumber(num: number, separator: string= = T.global.decim
|
||||
return sign + "" + num;
|
||||
}
|
||||
else {
|
||||
let leadingDigits: any = num;
|
||||
let suffix: any = "";
|
||||
for (let suffixIndex: any = 0; suffixIndex < bigNumberSuffixTranslationKeys.length; ++suffixIndex) {
|
||||
let leadingDigits = num;
|
||||
let suffix = "";
|
||||
for (let suffixIndex = 0; suffixIndex < bigNumberSuffixTranslationKeys.length; ++suffixIndex) {
|
||||
leadingDigits = leadingDigits / 1000;
|
||||
suffix = T.global.suffix[bigNumberSuffixTranslationKeys[suffixIndex]];
|
||||
if (leadingDigits < 1000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const leadingDigitsRounded: any = round1Digit(leadingDigits);
|
||||
const leadingDigitsNoTrailingDecimal: any = leadingDigitsRounded
|
||||
const leadingDigitsRounded = round1Digit(leadingDigits);
|
||||
const leadingDigitsNoTrailingDecimal = leadingDigitsRounded
|
||||
.toString()
|
||||
.replace(".0", "")
|
||||
.replace(".", separator);
|
||||
@ -233,8 +233,8 @@ export function formatBigNumberFull(num: number, divider: string= = T.global.tho
|
||||
if (num > 1e54) {
|
||||
return T.global.infinite;
|
||||
}
|
||||
let rest: any = num;
|
||||
let out: any = "";
|
||||
let rest = num;
|
||||
let out = "";
|
||||
while (rest >= 1000) {
|
||||
out = (rest % 1000).toString().padStart(3, "0") + divider + out;
|
||||
rest = Math.floor(rest / 1000);
|
||||
@ -247,9 +247,9 @@ export function formatBigNumberFull(num: number, divider: string= = T.global.tho
|
||||
* {}
|
||||
*/
|
||||
export function waitNextFrame(): Promise<void> {
|
||||
return new Promise(function (resolve: any): any {
|
||||
window.requestAnimationFrame(function (): any {
|
||||
window.requestAnimationFrame(function (): any {
|
||||
return new Promise(function (resolve) {
|
||||
window.requestAnimationFrame(function () {
|
||||
window.requestAnimationFrame(function () {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
@ -286,18 +286,18 @@ export function round4Digits(n: number): number {
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
/**
|
||||
* Helper method to create a new div element
|
||||
*/
|
||||
export function makeDivElement(id: string= = null, classes: Array<string>= = [], innerHTML: string= = ""): any {
|
||||
const div: any = document.createElement("div");
|
||||
export function makeDivElement(id: string= = null, classes: Array<string>= = [], innerHTML: string= = "") {
|
||||
const div = document.createElement("div");
|
||||
if (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.innerHTML = innerHTML;
|
||||
@ -306,17 +306,17 @@ export function makeDivElement(id: string= = null, classes: Array<string>= = [],
|
||||
/**
|
||||
* Helper method to create a new div
|
||||
*/
|
||||
export function makeDiv(parent: Element, id: string= = null, classes: Array<string>= = [], innerHTML: string= = ""): any {
|
||||
const div: any = makeDivElement(id, classes, innerHTML);
|
||||
export function makeDiv(parent: Element, id: string= = null, classes: Array<string>= = [], innerHTML: string= = "") {
|
||||
const div = makeDivElement(id, classes, innerHTML);
|
||||
parent.appendChild(div);
|
||||
return div;
|
||||
}
|
||||
/**
|
||||
* Helper method to create a new button element
|
||||
*/
|
||||
export function makeButtonElement(classes: Array<string>= = [], innerHTML: string= = ""): any {
|
||||
const element: any = document.createElement("button");
|
||||
for (let i: any = 0; i < classes.length; ++i) {
|
||||
export function makeButtonElement(classes: Array<string>= = [], innerHTML: string= = "") {
|
||||
const element = document.createElement("button");
|
||||
for (let i = 0; i < classes.length; ++i) {
|
||||
element.classList.add(classes[i]);
|
||||
}
|
||||
element.classList.add("styledButton");
|
||||
@ -326,17 +326,17 @@ export function makeButtonElement(classes: Array<string>= = [], innerHTML: strin
|
||||
/**
|
||||
* Helper method to create a new button
|
||||
*/
|
||||
export function makeButton(parent: Element, classes: Array<string>= = [], innerHTML: string= = ""): any {
|
||||
const element: any = makeButtonElement(classes, innerHTML);
|
||||
export function makeButton(parent: Element, classes: Array<string>= = [], innerHTML: string= = "") {
|
||||
const element = makeButtonElement(classes, innerHTML);
|
||||
parent.appendChild(element);
|
||||
return element;
|
||||
}
|
||||
/**
|
||||
* Removes all children of the given element
|
||||
*/
|
||||
export function removeAllChildren(elem: Element): any {
|
||||
export function removeAllChildren(elem: Element) {
|
||||
if (elem) {
|
||||
var range: any = document.createRange();
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(elem);
|
||||
range.deleteContents();
|
||||
}
|
||||
@ -344,7 +344,7 @@ export function removeAllChildren(elem: Element): any {
|
||||
/**
|
||||
* Returns if the game supports this browser
|
||||
*/
|
||||
export function isSupportedBrowser(): any {
|
||||
export function isSupportedBrowser() {
|
||||
// please note,
|
||||
// that IE11 now returns undefined again for window.chrome
|
||||
// and new Opera 30 outputs true for window.chrome
|
||||
@ -356,12 +356,12 @@ export function isSupportedBrowser(): any {
|
||||
return true;
|
||||
}
|
||||
// @ts-ignore
|
||||
var isChromium: any = window.chrome;
|
||||
var winNav: any = window.navigator;
|
||||
var vendorName: any = winNav.vendor;
|
||||
var isChromium = window.chrome;
|
||||
var winNav = window.navigator;
|
||||
var vendorName = winNav.vendor;
|
||||
// @ts-ignore
|
||||
var isIEedge: any = winNav.userAgent.indexOf("Edge") > -1;
|
||||
var isIOSChrome: any = winNav.userAgent.match("CriOS");
|
||||
var isIEedge = winNav.userAgent.indexOf("Edge") > -1;
|
||||
var isIOSChrome = winNav.userAgent.match("CriOS");
|
||||
if (isIOSChrome) {
|
||||
// is Google Chrome on IOS
|
||||
return false;
|
||||
@ -383,10 +383,10 @@ export function isSupportedBrowser(): any {
|
||||
* {}
|
||||
*/
|
||||
export function formatSecondsToTimeAgo(secs: number): string {
|
||||
const seconds: any = Math.floor(secs);
|
||||
const minutes: any = Math.floor(seconds / 60);
|
||||
const hours: any = Math.floor(minutes / 60);
|
||||
const days: any = Math.floor(hours / 24);
|
||||
const seconds = Math.floor(secs);
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const days = Math.floor(hours / 24);
|
||||
if (seconds < 60) {
|
||||
if (seconds === 1) {
|
||||
return T.global.time.oneSecondAgo;
|
||||
@ -417,34 +417,34 @@ export function formatSecondsToTimeAgo(secs: number): string {
|
||||
* {}
|
||||
*/
|
||||
export function formatSeconds(secs: number): string {
|
||||
const trans: any = T.global.time;
|
||||
const trans = T.global.time;
|
||||
secs = Math.ceil(secs);
|
||||
if (secs < 60) {
|
||||
return trans.secondsShort.replace("<seconds>", "" + secs);
|
||||
}
|
||||
else if (secs < 60 * 60) {
|
||||
const minutes: any = Math.floor(secs / 60);
|
||||
const seconds: any = secs % 60;
|
||||
const minutes = Math.floor(secs / 60);
|
||||
const seconds = secs % 60;
|
||||
return trans.minutesAndSecondsShort
|
||||
.replace("<seconds>", "" + seconds)
|
||||
.replace("<minutes>", "" + minutes);
|
||||
}
|
||||
else {
|
||||
const hours: any = Math.floor(secs / 3600);
|
||||
const minutes: any = Math.floor(secs / 60) % 60;
|
||||
const hours = Math.floor(secs / 3600);
|
||||
const minutes = Math.floor(secs / 60) % 60;
|
||||
return trans.hoursAndMinutesShort.replace("<minutes>", "" + minutes).replace("<hours>", "" + hours);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
? T.ingame.buildingPlacement.infoTexts.oneItemPerSecond
|
||||
: 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
|
||||
* 8 ru
|
||||
*/
|
||||
export function rotateFlatMatrix3x3(flatMatrix: Array<number>): any {
|
||||
export function rotateFlatMatrix3x3(flatMatrix: Array<number>) {
|
||||
return [
|
||||
flatMatrix[6],
|
||||
flatMatrix[3],
|
||||
@ -480,7 +480,7 @@ export function rotateFlatMatrix3x3(flatMatrix: Array<number>): any {
|
||||
* {}
|
||||
*/
|
||||
export function generateMatrixRotations(originalMatrix: Array<number>): Object<number, Array<number>> {
|
||||
const result: any = {
|
||||
const result = {
|
||||
0: originalMatrix,
|
||||
};
|
||||
originalMatrix = rotateFlatMatrix3x3(originalMatrix);
|
||||
@ -496,8 +496,8 @@ export function generateMatrixRotations(originalMatrix: Array<number>): Object<n
|
||||
* Rotates a directional object
|
||||
* {}
|
||||
*/
|
||||
export function rotateDirectionalObject(obj: DirectionalObject, rotation: any): DirectionalObject {
|
||||
const queue: any = [obj.top, obj.right, obj.bottom, obj.left];
|
||||
export function rotateDirectionalObject(obj: DirectionalObject, rotation): DirectionalObject {
|
||||
const queue = [obj.top, obj.right, obj.bottom, obj.left];
|
||||
while (rotation !== 0) {
|
||||
rotation -= 90;
|
||||
queue.push(queue.shift());
|
||||
@ -512,7 +512,7 @@ export function rotateDirectionalObject(obj: DirectionalObject, rotation: any):
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
@ -525,7 +525,7 @@ export function smoothPulse(time: number): number {
|
||||
/**
|
||||
* Fills in a <link> tag
|
||||
*/
|
||||
export function fillInLinkIntoTranslation(translation: string, link: string): any {
|
||||
export function fillInLinkIntoTranslation(translation: string, link: string) {
|
||||
return translation
|
||||
.replace("<link>", "<a href='" + link + "' target='_blank'>")
|
||||
.replace("</link>", "</a>");
|
||||
@ -533,8 +533,8 @@ export function fillInLinkIntoTranslation(translation: string, link: string): an
|
||||
/**
|
||||
* Generates a file download
|
||||
*/
|
||||
export function generateFileDownload(filename: string, text: string): any {
|
||||
var element: any = document.createElement("a");
|
||||
export function generateFileDownload(filename: string, text: string) {
|
||||
var element = document.createElement("a");
|
||||
element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
|
||||
element.setAttribute("download", filename);
|
||||
element.style.display = "none";
|
||||
@ -545,17 +545,17 @@ export function generateFileDownload(filename: string, text: string): any {
|
||||
/**
|
||||
* Starts a file chooser
|
||||
*/
|
||||
export function startFileChoose(acceptedType: string = ".bin"): any {
|
||||
var input: any = document.createElement("input");
|
||||
export function startFileChoose(acceptedType: string = ".bin") {
|
||||
var input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = acceptedType;
|
||||
return new Promise((resolve: any): any => {
|
||||
input.onchange = (_: any): any => resolve(input.files[0]);
|
||||
return new Promise(resolve => {
|
||||
input.onchange = _ => resolve(input.files[0]);
|
||||
input.click();
|
||||
});
|
||||
}
|
||||
const MAX_ROMAN_NUMBER: any = 49;
|
||||
const romanLiteralsCache: any = ["0"];
|
||||
const MAX_ROMAN_NUMBER = 49;
|
||||
const romanLiteralsCache = ["0"];
|
||||
/**
|
||||
*
|
||||
* {}
|
||||
@ -568,7 +568,7 @@ export function getRomanNumber(number: number): string {
|
||||
if (number > MAX_ROMAN_NUMBER) {
|
||||
return String(number);
|
||||
}
|
||||
function formatDigit(digit: any, unit: any, quintuple: any, decuple: any): any {
|
||||
function formatDigit(digit, unit, quintuple, decuple) {
|
||||
switch (digit) {
|
||||
case 0:
|
||||
return "";
|
||||
@ -587,26 +587,26 @@ export function getRomanNumber(number: number): string {
|
||||
return quintuple + formatDigit(digit - 5, unit, quintuple, decuple);
|
||||
}
|
||||
}
|
||||
let thousands: any = Math.floor(number / 1000);
|
||||
let thousandsPart: any = "";
|
||||
let thousands = Math.floor(number / 1000);
|
||||
let thousandsPart = "";
|
||||
while (thousands > 0) {
|
||||
thousandsPart += "M";
|
||||
thousands -= 1;
|
||||
}
|
||||
const hundreds: any = Math.floor((number % 1000) / 100);
|
||||
const hundredsPart: any = formatDigit(hundreds, "C", "D", "M");
|
||||
const tens: any = Math.floor((number % 100) / 10);
|
||||
const tensPart: any = formatDigit(tens, "X", "L", "C");
|
||||
const units: any = number % 10;
|
||||
const unitsPart: any = formatDigit(units, "I", "V", "X");
|
||||
const formatted: any = thousandsPart + hundredsPart + tensPart + unitsPart;
|
||||
const hundreds = Math.floor((number % 1000) / 100);
|
||||
const hundredsPart = formatDigit(hundreds, "C", "D", "M");
|
||||
const tens = Math.floor((number % 100) / 10);
|
||||
const tensPart = formatDigit(tens, "X", "L", "C");
|
||||
const units = number % 10;
|
||||
const unitsPart = formatDigit(units, "I", "V", "X");
|
||||
const formatted = thousandsPart + hundredsPart + tensPart + unitsPart;
|
||||
romanLiteralsCache[number] = formatted;
|
||||
return formatted;
|
||||
}
|
||||
/**
|
||||
* Returns the appropriate logo sprite path
|
||||
*/
|
||||
export function getLogoSprite(): any {
|
||||
export function getLogoSprite() {
|
||||
if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) {
|
||||
return "logo.png";
|
||||
}
|
||||
@ -618,10 +618,10 @@ export function getLogoSprite(): any {
|
||||
/**
|
||||
* 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([
|
||||
new Promise((resolve: any, reject: any): any => {
|
||||
setTimeout((): any => reject("timeout of " + timeout + " ms exceeded"), timeout);
|
||||
new Promise((resolve, reject) => {
|
||||
setTimeout(() => reject("timeout of " + timeout + " ms exceeded"), timeout);
|
||||
}),
|
||||
promise,
|
||||
]);
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { globalConfig } from "./config";
|
||||
import { safeModulo } from "./utils";
|
||||
const tileSize: any = globalConfig.tileSize;
|
||||
const halfTileSize: any = globalConfig.halfTileSize;
|
||||
const tileSize = globalConfig.tileSize;
|
||||
const halfTileSize = globalConfig.halfTileSize;
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export const enumDirection: any = {
|
||||
export const enumDirection = {
|
||||
top: "top",
|
||||
right: "right",
|
||||
bottom: "bottom",
|
||||
@ -14,7 +14,7 @@ export const enumDirection: any = {
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export const enumInvertedDirections: any = {
|
||||
export const enumInvertedDirections = {
|
||||
[enumDirection.top]: enumDirection.bottom,
|
||||
[enumDirection.right]: enumDirection.left,
|
||||
[enumDirection.bottom]: enumDirection.top,
|
||||
@ -23,7 +23,7 @@ export const enumInvertedDirections: any = {
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
export const enumDirectionToAngle: any = {
|
||||
export const enumDirectionToAngle = {
|
||||
[enumDirection.top]: 0,
|
||||
[enumDirection.right]: 90,
|
||||
[enumDirection.bottom]: 180,
|
||||
@ -32,7 +32,7 @@ export const enumDirectionToAngle: any = {
|
||||
/**
|
||||
* @enum {enumDirection}
|
||||
*/
|
||||
export const enumAngleToDirection: any = {
|
||||
export const enumAngleToDirection = {
|
||||
0: enumDirection.top,
|
||||
90: enumDirection.right,
|
||||
180: enumDirection.bottom,
|
||||
@ -224,8 +224,8 @@ export class Vector {
|
||||
* {}
|
||||
*/
|
||||
distanceSquare(v: Vector): number {
|
||||
const dx: any = this.x - v.x;
|
||||
const dy: any = this.y - v.y;
|
||||
const dx = this.x - v.x;
|
||||
const dy = this.y - v.y;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
/**
|
||||
@ -240,8 +240,8 @@ export class Vector {
|
||||
* {}
|
||||
*/
|
||||
centerPoint(v: Vector): Vector {
|
||||
const cx: any = this.x + v.x;
|
||||
const cy: any = this.y + v.y;
|
||||
const cx = this.x + v.x;
|
||||
const cy = this.y + v.y;
|
||||
return new Vector(cx / 2, cy / 2);
|
||||
}
|
||||
/**
|
||||
@ -305,7 +305,7 @@ export class 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);
|
||||
}
|
||||
/**
|
||||
@ -313,7 +313,7 @@ export class 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);
|
||||
}
|
||||
/**
|
||||
@ -321,9 +321,9 @@ export class Vector {
|
||||
* {}
|
||||
*/
|
||||
normalizedDirection(v: Vector): Vector {
|
||||
const dx: any = v.x - this.x;
|
||||
const dy: any = v.y - this.y;
|
||||
const len: any = Math.max(1e-5, Math.hypot(dx, dy));
|
||||
const dx = v.x - this.x;
|
||||
const dy = v.y - this.y;
|
||||
const len = Math.max(1e-5, Math.hypot(dx, dy));
|
||||
return new Vector(dx / len, dy / len);
|
||||
}
|
||||
/**
|
||||
@ -359,8 +359,8 @@ export class Vector {
|
||||
* {} new vector
|
||||
*/
|
||||
rotated(angle: number): Vector {
|
||||
const sin: any = Math.sin(angle);
|
||||
const cos: any = Math.cos(angle);
|
||||
const sin = Math.sin(angle);
|
||||
const cos = Math.cos(angle);
|
||||
return new Vector(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
|
||||
}
|
||||
/**
|
||||
@ -380,7 +380,7 @@ export class Vector {
|
||||
case 90: {
|
||||
// sin = 1;
|
||||
// cos = 0;
|
||||
const x: any = this.x;
|
||||
const x = this.x;
|
||||
this.x = -this.y;
|
||||
this.y = x;
|
||||
return this;
|
||||
@ -395,7 +395,7 @@ export class Vector {
|
||||
case 270: {
|
||||
// sin = -1
|
||||
// cos = 0
|
||||
const x: any = this.x;
|
||||
const x = this.x;
|
||||
this.x = this.y;
|
||||
this.y = -x;
|
||||
return this;
|
||||
@ -504,7 +504,7 @@ export class Vector {
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
@ -524,7 +524,7 @@ export class Vector {
|
||||
/**
|
||||
* Creates a simple representation of the vector
|
||||
*/
|
||||
serializeSimple(): any {
|
||||
serializeSimple() {
|
||||
return { x: this.x, y: this.y };
|
||||
}
|
||||
/**
|
||||
@ -538,8 +538,8 @@ export class Vector {
|
||||
* {}
|
||||
*/
|
||||
static deserializeTileFromInt(i: number): Vector {
|
||||
const x: any = i % 256;
|
||||
const y: any = Math.floor(i / 256);
|
||||
const x = i % 256;
|
||||
const y = Math.floor(i / 256);
|
||||
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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Mapping from string direction to actual vector
|
||||
* @enum {Vector}
|
||||
*/
|
||||
export const enumDirectionToVector: any = {
|
||||
export const enumDirectionToVector = {
|
||||
top: new Vector(0, -1),
|
||||
right: new Vector(1, 0),
|
||||
bottom: new Vector(0, 1),
|
||||
|
@ -6,9 +6,9 @@ import { globalConfig } from "../core/config";
|
||||
import { createLogger } from "../core/logging";
|
||||
import { ACHIEVEMENTS } from "../platform/achievement_provider";
|
||||
import { getBuildingDataFromCode } from "./building_codes";
|
||||
const logger: any = createLogger("achievement_proxy");
|
||||
const ROTATER: any = "rotater";
|
||||
const DEFAULT: any = "default";
|
||||
const logger = createLogger("achievement_proxy");
|
||||
const ROTATER = "rotater";
|
||||
const DEFAULT = "default";
|
||||
export class AchievementProxy {
|
||||
public root = root;
|
||||
public provider = this.root.app.achievementProvider;
|
||||
@ -24,7 +24,7 @@ export class AchievementProxy {
|
||||
}
|
||||
this.root.signals.postLoadHook.add(this.onLoad, this);
|
||||
}
|
||||
onLoad(): any {
|
||||
onLoad() {
|
||||
if (!this.root.gameMode.hasAchievements()) {
|
||||
logger.log("Disabling achievements because game mode does not have achievements");
|
||||
this.disabled = true;
|
||||
@ -32,17 +32,17 @@ export class AchievementProxy {
|
||||
}
|
||||
this.provider
|
||||
.onLoad(this.root)
|
||||
.then((): any => {
|
||||
.then(() => {
|
||||
this.disabled = false;
|
||||
logger.log("Recieving achievement signals");
|
||||
this.initialize();
|
||||
})
|
||||
.catch((err: any): any => {
|
||||
.catch(err => {
|
||||
this.disabled = true;
|
||||
logger.error("Ignoring achievement signals", err);
|
||||
});
|
||||
}
|
||||
initialize(): any {
|
||||
initialize() {
|
||||
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.darkMode, null);
|
||||
if (this.has(ACHIEVEMENTS.mam)) {
|
||||
this.root.signals.entityAdded.add(this.onMamFailure, this);
|
||||
@ -54,11 +54,11 @@ export class AchievementProxy {
|
||||
}
|
||||
this.startSlice();
|
||||
}
|
||||
startSlice(): any {
|
||||
startSlice() {
|
||||
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);
|
||||
}
|
||||
update(): any {
|
||||
update() {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
@ -75,11 +75,11 @@ export class AchievementProxy {
|
||||
}
|
||||
return this.provider.collection.map.has(key);
|
||||
}
|
||||
onEntityAdded(entity: Entity): any {
|
||||
onEntityAdded(entity: Entity) {
|
||||
if (!entity.components.StaticMapEntity) {
|
||||
return;
|
||||
}
|
||||
const building: any = getBuildingDataFromCode(entity.components.StaticMapEntity.code);
|
||||
const building = getBuildingDataFromCode(entity.components.StaticMapEntity.code);
|
||||
if (building.metaInstance.id !== ROTATER) {
|
||||
return;
|
||||
}
|
||||
@ -89,7 +89,7 @@ export class AchievementProxy {
|
||||
this.root.savegame.currentData.stats.usedInverseRotater = true;
|
||||
this.root.signals.entityAdded.remove(this.onEntityAdded);
|
||||
}
|
||||
onStoryGoalCompleted(level: number): any {
|
||||
onStoryGoalCompleted(level: number) {
|
||||
if (level > 26) {
|
||||
this.root.signals.entityAdded.add(this.onMamFailure, this);
|
||||
this.root.signals.entityDestroyed.add(this.onMamFailure, this);
|
||||
@ -98,7 +98,7 @@ export class AchievementProxy {
|
||||
// reset on every level
|
||||
this.root.savegame.currentData.stats.failedMam = false;
|
||||
}
|
||||
onMamFailure(): any {
|
||||
onMamFailure() {
|
||||
this.root.savegame.currentData.stats.failedMam = true;
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import { GameRoot } from "./root";
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
export const enumSavePriority: any = {
|
||||
export const enumSavePriority = {
|
||||
regular: 2,
|
||||
asap: 100,
|
||||
};
|
||||
const logger: any = createLogger("autosave");
|
||||
const logger = createLogger("autosave");
|
||||
export class AutomaticSave {
|
||||
public root: GameRoot = root;
|
||||
public saveImportance = enumSavePriority.regular;
|
||||
@ -17,30 +17,30 @@ export class AutomaticSave {
|
||||
|
||||
constructor(root) {
|
||||
}
|
||||
setSaveImportance(importance: any): any {
|
||||
setSaveImportance(importance) {
|
||||
this.saveImportance = Math.max(this.saveImportance, importance);
|
||||
}
|
||||
doSave(): any {
|
||||
doSave() {
|
||||
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
|
||||
return;
|
||||
}
|
||||
this.root.gameState.doSave();
|
||||
this.saveImportance = enumSavePriority.regular;
|
||||
}
|
||||
update(): any {
|
||||
update() {
|
||||
if (!this.root.gameInitialized) {
|
||||
// Bad idea
|
||||
return;
|
||||
}
|
||||
const saveInterval: any = this.root.app.settings.getAutosaveIntervalSeconds();
|
||||
const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds();
|
||||
if (!saveInterval) {
|
||||
// Disabled
|
||||
return;
|
||||
}
|
||||
// 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 secondsSinceLastSave: any = (Date.now() - lastSaveTime) / 1000.0;
|
||||
let shouldSave: any = false;
|
||||
const lastSaveTime = Math.max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate());
|
||||
const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0;
|
||||
let shouldSave = false;
|
||||
switch (this.saveImportance) {
|
||||
case enumSavePriority.asap:
|
||||
// High always should save
|
||||
|
@ -10,7 +10,7 @@ export class BaseItem extends BasicSerializableObject {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "base_item";
|
||||
}
|
||||
/** {} */
|
||||
@ -54,13 +54,13 @@ export class BaseItem extends BasicSerializableObject {
|
||||
* Draws the item to a canvas
|
||||
* @abstract
|
||||
*/
|
||||
drawFullSizeOnCanvas(context: CanvasRenderingContext2D, size: number): any {
|
||||
drawFullSizeOnCanvas(context: CanvasRenderingContext2D, size: number) {
|
||||
abstract;
|
||||
}
|
||||
/**
|
||||
* 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)) {
|
||||
this.drawItemCenteredImpl(x, y, parameters, diameter);
|
||||
}
|
||||
@ -69,10 +69,10 @@ export class BaseItem extends BasicSerializableObject {
|
||||
* INTERNAL
|
||||
* @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;
|
||||
}
|
||||
getBackgroundColorAsResource(): any {
|
||||
getBackgroundColorAsResource() {
|
||||
abstract;
|
||||
return "";
|
||||
}
|
||||
|
@ -11,17 +11,17 @@ import { BaseItem } from "./base_item";
|
||||
import { Entity } from "./entity";
|
||||
import { typeItemSingleton } from "./item_resolver";
|
||||
import { GameRoot } from "./root";
|
||||
const logger: any = createLogger("belt_path");
|
||||
const logger = createLogger("belt_path");
|
||||
// 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
|
||||
*/
|
||||
export class BeltPath extends BasicSerializableObject {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "BeltPath";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
entityPath: types.array(types.entity),
|
||||
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 {
|
||||
|
||||
// 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;
|
||||
// Deserialize the data
|
||||
const errorCodeDeserialize: any = fakeObject.deserialize(data);
|
||||
const errorCodeDeserialize = fakeObject.deserialize(data);
|
||||
if (errorCodeDeserialize) {
|
||||
return errorCodeDeserialize;
|
||||
}
|
||||
@ -68,7 +68,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
/**
|
||||
* Initializes the path by computing the properties which are not saved
|
||||
*/
|
||||
init(computeSpacing: boolean = true): any {
|
||||
init(computeSpacing: boolean = true) {
|
||||
this.onPathChanged();
|
||||
this.totalLength = this.computeTotalLength();
|
||||
if (computeSpacing) {
|
||||
@ -79,14 +79,14 @@ export class BeltPath extends BasicSerializableObject {
|
||||
*/
|
||||
this.worldBounds = this.computeBounds();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Clears all items
|
||||
*/
|
||||
clearAllItems(): any {
|
||||
clearAllItems() {
|
||||
this.items = [];
|
||||
this.spacingToFirstItem = this.totalLength;
|
||||
this.numCompressedItemsAfterFirstItem = 0;
|
||||
@ -101,15 +101,15 @@ export class BeltPath extends BasicSerializableObject {
|
||||
/**
|
||||
* Tries to accept the item
|
||||
*/
|
||||
tryAcceptItem(item: BaseItem): any {
|
||||
tryAcceptItem(item: BaseItem) {
|
||||
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
|
||||
// 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 *
|
||||
globalConfig.itemSpacingOnBelts;
|
||||
// First, compute how much progress we can make *at max*
|
||||
const maxProgress: any = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts);
|
||||
const initialProgress: any = Math.min(maxProgress, beltProgressPerTick);
|
||||
const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts);
|
||||
const initialProgress = Math.min(maxProgress, beltProgressPerTick);
|
||||
this.items.unshift([this.spacingToFirstItem - initialProgress, item]);
|
||||
this.spacingToFirstItem = initialProgress;
|
||||
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
|
||||
@ -132,10 +132,10 @@ export class BeltPath extends BasicSerializableObject {
|
||||
* {}
|
||||
*/
|
||||
computeBounds(): Rectangle {
|
||||
let bounds: any = this.entityPath[0].components.StaticMapEntity.getTileSpaceBounds();
|
||||
for (let i: any = 1; i < this.entityPath.length; ++i) {
|
||||
const staticComp: any = this.entityPath[i].components.StaticMapEntity;
|
||||
const otherBounds: any = staticComp.getTileSpaceBounds();
|
||||
let bounds = this.entityPath[0].components.StaticMapEntity.getTileSpaceBounds();
|
||||
for (let i = 1; i < this.entityPath.length; ++i) {
|
||||
const staticComp = this.entityPath[i].components.StaticMapEntity;
|
||||
const otherBounds = staticComp.getTileSpaceBounds();
|
||||
bounds = bounds.getUnion(otherBounds);
|
||||
}
|
||||
return bounds.allScaled(globalConfig.tileSize);
|
||||
@ -143,7 +143,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
/**
|
||||
* Recomputes cache variables once the path was changed
|
||||
*/
|
||||
onPathChanged(): any {
|
||||
onPathChanged() {
|
||||
this.boundAcceptor = this.computeAcceptingEntityAndSlot().acceptor;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
onSurroundingsChanged(): any {
|
||||
onSurroundingsChanged() {
|
||||
this.onPathChanged();
|
||||
}
|
||||
/**
|
||||
@ -165,34 +165,34 @@ export class BeltPath extends BasicSerializableObject {
|
||||
entity?: Entity;
|
||||
} {
|
||||
DEBUG && !debug_Silent && logger.log("Recomputing acceptor target");
|
||||
const lastEntity: any = this.entityPath[this.entityPath.length - 1];
|
||||
const lastStatic: any = lastEntity.components.StaticMapEntity;
|
||||
const lastBeltComp: any = lastEntity.components.Belt;
|
||||
const lastEntity = this.entityPath[this.entityPath.length - 1];
|
||||
const lastStatic = lastEntity.components.StaticMapEntity;
|
||||
const lastBeltComp = lastEntity.components.Belt;
|
||||
// Figure out where and into which direction we eject items
|
||||
const ejectSlotWsTile: any = lastStatic.localTileToWorld(new Vector(0, 0));
|
||||
const ejectSlotWsDirection: any = lastStatic.localDirectionToWorld(lastBeltComp.direction);
|
||||
const ejectSlotWsDirectionVector: any = enumDirectionToVector[ejectSlotWsDirection];
|
||||
const ejectSlotTargetWsTile: any = ejectSlotWsTile.add(ejectSlotWsDirectionVector);
|
||||
const ejectSlotWsTile = lastStatic.localTileToWorld(new Vector(0, 0));
|
||||
const ejectSlotWsDirection = lastStatic.localDirectionToWorld(lastBeltComp.direction);
|
||||
const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection];
|
||||
const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector);
|
||||
// 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) {
|
||||
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);
|
||||
const targetStaticComp: any = targetEntity.components.StaticMapEntity;
|
||||
const targetBeltComp: any = targetEntity.components.Belt;
|
||||
const targetStaticComp = targetEntity.components.StaticMapEntity;
|
||||
const targetBeltComp = targetEntity.components.Belt;
|
||||
// Check for belts (special case)
|
||||
if (targetBeltComp) {
|
||||
const beltAcceptingDirection: any = targetStaticComp.localDirectionToWorld(enumDirection.top);
|
||||
const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top);
|
||||
DEBUG &&
|
||||
!debug_Silent &&
|
||||
logger.log(" Entity is accepting items from", ejectSlotWsDirection, "vs", beltAcceptingDirection, "Rotation:", targetStaticComp.rotation);
|
||||
if (ejectSlotWsDirection === beltAcceptingDirection) {
|
||||
return {
|
||||
entity: targetEntity,
|
||||
acceptor: (item: any): any => {
|
||||
const path: any = targetBeltComp.assignedPath;
|
||||
acceptor: item => {
|
||||
const path = targetBeltComp.assignedPath;
|
||||
assert(path, "belt has no path");
|
||||
return path.tryAcceptItem(item);
|
||||
},
|
||||
@ -200,27 +200,27 @@ export class BeltPath extends BasicSerializableObject {
|
||||
}
|
||||
}
|
||||
// Check for item acceptors
|
||||
const targetAcceptorComp: any = targetEntity.components.ItemAcceptor;
|
||||
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
|
||||
if (!targetAcceptorComp) {
|
||||
// Entity doesn't accept items
|
||||
return {};
|
||||
}
|
||||
const ejectingDirection: any = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection);
|
||||
const matchingSlot: any = targetAcceptorComp.findMatchingSlot(targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), ejectingDirection);
|
||||
const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection);
|
||||
const matchingSlot = targetAcceptorComp.findMatchingSlot(targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), ejectingDirection);
|
||||
if (!matchingSlot) {
|
||||
// No matching slot found
|
||||
return {};
|
||||
}
|
||||
const matchingSlotIndex: any = matchingSlot.index;
|
||||
const passOver: any = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex);
|
||||
const matchingSlotIndex = matchingSlot.index;
|
||||
const passOver = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex);
|
||||
if (!passOver) {
|
||||
return {};
|
||||
}
|
||||
const matchingDirection: any = enumInvertedDirections[ejectingDirection];
|
||||
const filter: any = matchingSlot.slot.filter;
|
||||
const matchingDirection = enumInvertedDirections[ejectingDirection];
|
||||
const filter = matchingSlot.slot.filter;
|
||||
return {
|
||||
entity: targetEntity,
|
||||
acceptor: function (item: any, remainingProgress: any = 0.0): any {
|
||||
acceptor: function (item, remainingProgress = 0.0) {
|
||||
// Check if the acceptor has a filter
|
||||
if (filter && item._type !== filter) {
|
||||
return false;
|
||||
@ -242,13 +242,13 @@ export class BeltPath extends BasicSerializableObject {
|
||||
* {}
|
||||
*/
|
||||
computePassOverFunctionWithoutBelts(entity: Entity, matchingSlotIndex: number): (item: BaseItem, slotIndex: number) => boolean | void {
|
||||
const systems: any = this.root.systemMgr.systems;
|
||||
const hubGoals: any = this.root.hubGoals;
|
||||
const systems = this.root.systemMgr.systems;
|
||||
const hubGoals = this.root.hubGoals;
|
||||
// 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) {
|
||||
// Its an item processor ..
|
||||
return function (item: any): any {
|
||||
return function (item) {
|
||||
// Check for potential filters
|
||||
if (!systems.itemProcessor.checkRequirements(entity, item, matchingSlotIndex)) {
|
||||
return;
|
||||
@ -256,28 +256,28 @@ export class BeltPath extends BasicSerializableObject {
|
||||
return itemProcessorComp.tryTakeItem(item, matchingSlotIndex);
|
||||
};
|
||||
}
|
||||
const undergroundBeltComp: any = entity.components.UndergroundBelt;
|
||||
const undergroundBeltComp = entity.components.UndergroundBelt;
|
||||
if (undergroundBeltComp) {
|
||||
// Its an underground belt. yay.
|
||||
return function (item: any): any {
|
||||
return function (item) {
|
||||
return undergroundBeltComp.tryAcceptExternalItem(item, hubGoals.getUndergroundBeltBaseSpeed());
|
||||
};
|
||||
}
|
||||
const storageComp: any = entity.components.Storage;
|
||||
const storageComp = entity.components.Storage;
|
||||
if (storageComp) {
|
||||
// It's a storage
|
||||
return function (item: any): any {
|
||||
return function (item) {
|
||||
if (storageComp.canAcceptItem(item)) {
|
||||
storageComp.takeItem(item);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
const filterComp: any = entity.components.Filter;
|
||||
const filterComp = entity.components.Filter;
|
||||
if (filterComp) {
|
||||
// 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.
|
||||
return function (item: any): any {
|
||||
return function (item) {
|
||||
if (systems.filter.tryAcceptItem(entity, matchingSlotIndex, item)) {
|
||||
return true;
|
||||
}
|
||||
@ -289,30 +289,30 @@ export class BeltPath extends BasicSerializableObject {
|
||||
/**
|
||||
* Helper to throw an error on mismatch
|
||||
*/
|
||||
debug_failIntegrity(change: string, ...reason: Array<any>): any {
|
||||
throw new Error("belt path invalid (" + change + "): " + reason.map((i: any): any => "" + i).join(" "));
|
||||
debug_failIntegrity(change: string, ...reason: Array<any>) {
|
||||
throw new Error("belt path invalid (" + change + "): " + reason.map(i => "" + i).join(" "));
|
||||
}
|
||||
/**
|
||||
* Checks if this path is valid
|
||||
*/
|
||||
debug_checkIntegrity(currentChange: any = "change"): any {
|
||||
const fail: any = (...args: any): any => this.debug_failIntegrity(currentChange, ...args);
|
||||
debug_checkIntegrity(currentChange = "change") {
|
||||
const fail = (...args) => this.debug_failIntegrity(currentChange, ...args);
|
||||
// Check for empty path
|
||||
if (this.entityPath.length === 0) {
|
||||
return fail("Belt path is empty");
|
||||
}
|
||||
// Check for mismatching length
|
||||
const totalLength: any = this.computeTotalLength();
|
||||
const totalLength = this.computeTotalLength();
|
||||
if (!epsilonCompare(this.totalLength, totalLength, 0.01)) {
|
||||
return this.debug_failIntegrity(currentChange, "Total length mismatch, stored =", this.totalLength, "but correct is", totalLength);
|
||||
}
|
||||
// Check for misconnected entities
|
||||
for (let i: any = 0; i < this.entityPath.length - 1; ++i) {
|
||||
const entity: any = this.entityPath[i];
|
||||
for (let i = 0; i < this.entityPath.length - 1; ++i) {
|
||||
const entity = this.entityPath[i];
|
||||
if (entity.destroyed) {
|
||||
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) {
|
||||
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, ")");
|
||||
}
|
||||
// Check items etc
|
||||
let currentPos: any = this.spacingToFirstItem;
|
||||
for (let i: any = 0; i < this.items.length; ++i) {
|
||||
const item: any = this.items[i];
|
||||
let currentPos = this.spacingToFirstItem;
|
||||
for (let i = 0; i < this.items.length; ++i) {
|
||||
const item = this.items[i];
|
||||
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, ")");
|
||||
}
|
||||
@ -342,21 +342,21 @@ export class BeltPath extends BasicSerializableObject {
|
||||
}
|
||||
// Check the total sum matches
|
||||
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
|
||||
const actualBounds: any = this.computeBounds();
|
||||
const actualBounds = this.computeBounds();
|
||||
if (!actualBounds.equalsEpsilon(this.worldBounds, 0.01)) {
|
||||
return fail("Bounds are stale");
|
||||
}
|
||||
// Check acceptor
|
||||
const acceptor: any = this.computeAcceptingEntityAndSlot(true).acceptor;
|
||||
const acceptor = this.computeAcceptingEntityAndSlot(true).acceptor;
|
||||
if (!!acceptor !== !!this.boundAcceptor) {
|
||||
return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.boundAcceptor);
|
||||
}
|
||||
// Check first nonzero offset
|
||||
let firstNonzero: any = 0;
|
||||
for (let i: any = this.items.length - 2; i >= 0; --i) {
|
||||
let firstNonzero = 0;
|
||||
for (let i = this.items.length - 2; i >= 0; --i) {
|
||||
if (this.items[i][0 /* nextDistance */] < globalConfig.itemSpacingOnBelts + 1e-5) {
|
||||
++firstNonzero;
|
||||
}
|
||||
@ -378,14 +378,14 @@ export class BeltPath extends BasicSerializableObject {
|
||||
/**
|
||||
* 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);
|
||||
const beltComp: any = entity.components.Belt;
|
||||
const beltComp = entity.components.Belt;
|
||||
// Append the entity
|
||||
this.entityPath.push(entity);
|
||||
this.onPathChanged();
|
||||
// Extend the path length
|
||||
const additionalLength: any = beltComp.getEffectiveLengthTiles();
|
||||
const additionalLength = beltComp.getEffectiveLengthTiles();
|
||||
this.totalLength += additionalLength;
|
||||
DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength);
|
||||
// If we have no item, just update the distance to the first item
|
||||
@ -395,7 +395,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
}
|
||||
else {
|
||||
// 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 &&
|
||||
logger.log(" Extended spacing of last item from", lastItem[0 /* nextDistance */], "to", 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
|
||||
*/
|
||||
extendOnBeginning(entity: Entity): any {
|
||||
const beltComp: any = entity.components.Belt;
|
||||
extendOnBeginning(entity: Entity) {
|
||||
const beltComp = entity.components.Belt;
|
||||
DEBUG && logger.log("Extending the path on the beginning");
|
||||
// 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
|
||||
this.totalLength += length;
|
||||
// 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 {
|
||||
DEBUG && logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin);
|
||||
// First, find where the current path ends
|
||||
const beltComp: any = entity.components.Belt;
|
||||
const beltComp = entity.components.Belt;
|
||||
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 is first");
|
||||
assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last");
|
||||
let firstPathEntityCount: any = 0;
|
||||
let firstPathLength: any = 0;
|
||||
let firstPathEndEntity: any = null;
|
||||
for (let i: any = 0; i < this.entityPath.length; ++i) {
|
||||
const otherEntity: any = this.entityPath[i];
|
||||
let firstPathEntityCount = 0;
|
||||
let firstPathLength = 0;
|
||||
let firstPathEndEntity = null;
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const otherEntity = this.entityPath[i];
|
||||
if (otherEntity === entity) {
|
||||
DEBUG && logger.log("Found entity at", i, "of length", firstPathLength);
|
||||
break;
|
||||
@ -474,23 +474,23 @@ export class BeltPath extends BasicSerializableObject {
|
||||
DEBUG &&
|
||||
logger.log("First path ends at", firstPathLength, "and entity", firstPathEndEntity.components.StaticMapEntity.origin, "and has", firstPathEntityCount, "entities");
|
||||
// Compute length of second path
|
||||
const secondPathLength: any = this.totalLength - firstPathLength - entityLength;
|
||||
const secondPathStart: any = firstPathLength + entityLength;
|
||||
const secondEntities: any = this.entityPath.splice(firstPathEntityCount + 1);
|
||||
const secondPathLength = this.totalLength - firstPathLength - entityLength;
|
||||
const secondPathStart = firstPathLength + entityLength;
|
||||
const secondEntities = this.entityPath.splice(firstPathEntityCount + 1);
|
||||
DEBUG &&
|
||||
logger.log("Second path starts at", secondPathStart, "and has a length of ", secondPathLength, "with", secondEntities.length, "entities");
|
||||
// Remove the last item
|
||||
this.entityPath.pop();
|
||||
DEBUG && logger.log("Splitting", this.items.length, "items");
|
||||
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
|
||||
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
|
||||
let itemPos: any = this.spacingToFirstItem;
|
||||
for (let i: any = 0; i < this.items.length; ++i) {
|
||||
const item: any = this.items[i];
|
||||
const distanceToNext: any = item[0 /* nextDistance */];
|
||||
let itemPos = this.spacingToFirstItem;
|
||||
for (let i = 0; i < this.items.length; ++i) {
|
||||
const item = this.items[i];
|
||||
const distanceToNext = item[0 /* nextDistance */];
|
||||
DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next");
|
||||
// Check if this item is past the first path
|
||||
if (itemPos >= firstPathLength) {
|
||||
@ -518,7 +518,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
else {
|
||||
// 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
|
||||
const clampedDistanceToNext: any = Math.min(itemPos + distanceToNext, firstPathLength) - itemPos;
|
||||
const clampedDistanceToNext = Math.min(itemPos + distanceToNext, firstPathLength) - itemPos;
|
||||
if (clampedDistanceToNext < distanceToNext) {
|
||||
DEBUG &&
|
||||
logger.log("Correcting next distance (first path) from", distanceToNext, "to", clampedDistanceToNext);
|
||||
@ -529,9 +529,9 @@ export class BeltPath extends BasicSerializableObject {
|
||||
itemPos += distanceToNext;
|
||||
}
|
||||
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 &&
|
||||
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
|
||||
this.totalLength = firstPathLength;
|
||||
// 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
|
||||
*/
|
||||
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) + ")");
|
||||
// Ok, first remove the entity
|
||||
const beltComp: any = entity.components.Belt;
|
||||
const beltLength: any = beltComp.getEffectiveLengthTiles();
|
||||
const beltComp = entity.components.Belt;
|
||||
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||
DEBUG &&
|
||||
logger.log("Deleting last entity on path with length", this.entityPath.length, "(reducing", this.totalLength, " by", beltLength, ")");
|
||||
this.totalLength -= beltLength;
|
||||
@ -572,11 +572,11 @@ export class BeltPath extends BasicSerializableObject {
|
||||
}
|
||||
else {
|
||||
// Ok, make sure we simply drop all items which are no longer contained
|
||||
let itemOffset: any = this.spacingToFirstItem;
|
||||
let lastItemOffset: any = itemOffset;
|
||||
let itemOffset = this.spacingToFirstItem;
|
||||
let lastItemOffset = itemOffset;
|
||||
DEBUG && logger.log(" Adjusting", this.items.length, "items");
|
||||
for (let i: any = 0; i < this.items.length; ++i) {
|
||||
const item: any = this.items[i];
|
||||
for (let i = 0; i < this.items.length; ++i) {
|
||||
const item = this.items[i];
|
||||
// Get rid of items past this path
|
||||
if (itemOffset >= this.totalLength) {
|
||||
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 (this.items.length > 0) {
|
||||
// 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: " +
|
||||
lastDistance +
|
||||
" -> Total length was " +
|
||||
@ -619,11 +619,11 @@ export class BeltPath extends BasicSerializableObject {
|
||||
* Deletes the entity of the start of the path
|
||||
* @see deleteEntityOnEnd
|
||||
*/
|
||||
deleteEntityOnStart(entity: Entity): any {
|
||||
deleteEntityOnStart(entity: Entity) {
|
||||
assert(entity === this.entityPath[0], "Not actually the start entity (instead " + this.entityPath.indexOf(entity) + ")");
|
||||
// Ok, first remove the entity
|
||||
const beltComp: any = entity.components.Belt;
|
||||
const beltLength: any = beltComp.getEffectiveLengthTiles();
|
||||
const beltComp = entity.components.Belt;
|
||||
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||
DEBUG &&
|
||||
logger.log("Deleting first entity on path with length", this.entityPath.length, "(reducing", this.totalLength, " by", beltLength, ")");
|
||||
this.totalLength -= beltLength;
|
||||
@ -651,11 +651,11 @@ export class BeltPath extends BasicSerializableObject {
|
||||
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");
|
||||
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
|
||||
let itemOffset: any = this.spacingToFirstItem;
|
||||
for (let i: any = 0; i < this.items.length; ++i) {
|
||||
const item: any = this.items[i];
|
||||
let itemOffset = this.spacingToFirstItem;
|
||||
for (let i = 0; i < this.items.length; ++i) {
|
||||
const item = this.items[i];
|
||||
if (itemOffset <= beltLength) {
|
||||
DEBUG &&
|
||||
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
|
||||
*/
|
||||
extendByPath(otherPath: BeltPath): any {
|
||||
extendByPath(otherPath: BeltPath) {
|
||||
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");
|
||||
const oldLength: any = this.totalLength;
|
||||
const oldLength = this.totalLength;
|
||||
DEBUG && logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength);
|
||||
// First, append entities
|
||||
for (let i: any = 0; i < entities.length; ++i) {
|
||||
const entity: any = entities[i];
|
||||
const beltComp: any = entity.components.Belt;
|
||||
for (let i = 0; i < entities.length; ++i) {
|
||||
const entity = entities[i];
|
||||
const beltComp = entity.components.Belt;
|
||||
// Add to path and update references
|
||||
this.entityPath.push(entity);
|
||||
beltComp.assignedPath = this;
|
||||
// Update our length
|
||||
const additionalLength: any = beltComp.getEffectiveLengthTiles();
|
||||
const additionalLength = beltComp.getEffectiveLengthTiles();
|
||||
this.totalLength += additionalLength;
|
||||
}
|
||||
DEBUG &&
|
||||
logger.log(" Path is now", this.entityPath.length, "entities and has a length of", this.totalLength);
|
||||
// Now, update the distance of our last item
|
||||
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;
|
||||
DEBUG &&
|
||||
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");
|
||||
// Aaand push the other paths items
|
||||
for (let i: any = 0; i < otherPath.items.length; ++i) {
|
||||
const item: any = otherPath.items[i];
|
||||
for (let i = 0; i < otherPath.items.length; ++i) {
|
||||
const item = otherPath.items[i];
|
||||
this.items.push([item[0 /* nextDistance */], item[1 /* item */]]);
|
||||
}
|
||||
// Update bounds
|
||||
@ -742,9 +742,9 @@ export class BeltPath extends BasicSerializableObject {
|
||||
* {}
|
||||
*/
|
||||
computeTotalLength(): number {
|
||||
let length: any = 0;
|
||||
for (let i: any = 0; i < this.entityPath.length; ++i) {
|
||||
const entity: any = this.entityPath[i];
|
||||
let length = 0;
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const entity = this.entityPath[i];
|
||||
length += entity.components.Belt.getEffectiveLengthTiles();
|
||||
}
|
||||
return length;
|
||||
@ -752,7 +752,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
/**
|
||||
* Performs one tick
|
||||
*/
|
||||
update(): any {
|
||||
update() {
|
||||
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
|
||||
this.debug_checkIntegrity("pre-update");
|
||||
}
|
||||
@ -761,7 +761,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
return;
|
||||
}
|
||||
// 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 *
|
||||
globalConfig.itemSpacingOnBelts;
|
||||
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
|
||||
// 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
|
||||
let remainingVelocity: any = beltSpeed;
|
||||
let remainingVelocity = beltSpeed;
|
||||
// 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) {
|
||||
const nextDistanceAndItem: any = this.items[lastItemProcessed];
|
||||
const nextDistanceAndItem = this.items[lastItemProcessed];
|
||||
// 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
|
||||
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
|
||||
if (remainingVelocity < clampedProgress) {
|
||||
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
|
||||
// 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.
|
||||
const excessVelocity: any = beltSpeed - clampedProgress;
|
||||
const excessVelocity = beltSpeed - clampedProgress;
|
||||
// Try to directly get rid of the item
|
||||
if (this.boundAcceptor &&
|
||||
this.boundAcceptor(nextDistanceAndItem[1 /* item */], excessVelocity)) {
|
||||
this.items.pop();
|
||||
const itemBehind: any = this.items[lastItemProcessed - 1];
|
||||
const itemBehind = this.items[lastItemProcessed - 1];
|
||||
if (itemBehind && this.numCompressedItemsAfterFirstItem > 0) {
|
||||
// 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
|
||||
// every tick which causes the belt to be slower than it actually is.
|
||||
// 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
|
||||
itemBehind[0 /* nextDistance */] -= fixupProgress;
|
||||
remainingVelocity -= fixupProgress;
|
||||
@ -833,7 +833,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
// Compute compressed item count
|
||||
this.numCompressedItemsAfterFirstItem = Math.max(0, this.numCompressedItemsAfterFirstItem, this.items.length - 2 - lastItemProcessed);
|
||||
// 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 (this.boundAcceptor && this.boundAcceptor(lastItem[1 /* item */])) {
|
||||
this.items.pop();
|
||||
@ -849,34 +849,34 @@ export class BeltPath extends BasicSerializableObject {
|
||||
* {}
|
||||
*/
|
||||
computePositionFromProgress(progress: number): Vector {
|
||||
let currentLength: any = 0;
|
||||
let currentLength = 0;
|
||||
// floating point issues ..
|
||||
assert(progress <= this.totalLength + 0.02, "Progress too big: " + progress);
|
||||
for (let i: any = 0; i < this.entityPath.length; ++i) {
|
||||
const beltComp: any = this.entityPath[i].components.Belt;
|
||||
const localLength: any = beltComp.getEffectiveLengthTiles();
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const beltComp = this.entityPath[i].components.Belt;
|
||||
const localLength = beltComp.getEffectiveLengthTiles();
|
||||
if (currentLength + localLength >= progress || i === this.entityPath.length - 1) {
|
||||
// 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);
|
||||
const localSpace: any = beltComp.transformBeltToLocalSpace(localProgress);
|
||||
const localSpace = beltComp.transformBeltToLocalSpace(localProgress);
|
||||
return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace);
|
||||
}
|
||||
currentLength += localLength;
|
||||
}
|
||||
assert(false, "invalid progress: " + progress + " (max: " + this.totalLength + ")");
|
||||
}
|
||||
drawDebug(parameters: DrawParameters): any {
|
||||
drawDebug(parameters: DrawParameters) {
|
||||
if (!parameters.visibleRect.containsRect(this.worldBounds)) {
|
||||
return;
|
||||
}
|
||||
parameters.context.fillStyle = "#d79a25";
|
||||
parameters.context.strokeStyle = "#d79a25";
|
||||
parameters.context.beginPath();
|
||||
for (let i: any = 0; i < this.entityPath.length; ++i) {
|
||||
const entity: any = this.entityPath[i];
|
||||
const pos: any = entity.components.StaticMapEntity;
|
||||
const worldPos: any = pos.origin.toWorldSpaceCenterOfTile();
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const entity = this.entityPath[i];
|
||||
const pos = entity.components.StaticMapEntity;
|
||||
const worldPos = pos.origin.toWorldSpaceCenterOfTile();
|
||||
if (i === 0) {
|
||||
parameters.context.moveTo(worldPos.x, worldPos.y);
|
||||
}
|
||||
@ -886,10 +886,10 @@ export class BeltPath extends BasicSerializableObject {
|
||||
}
|
||||
parameters.context.stroke();
|
||||
// Items
|
||||
let progress: any = this.spacingToFirstItem;
|
||||
for (let i: any = 0; i < this.items.length; ++i) {
|
||||
const nextDistanceAndItem: any = this.items[i];
|
||||
const worldPos: any = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile();
|
||||
let progress = this.spacingToFirstItem;
|
||||
for (let i = 0; i < this.items.length; ++i) {
|
||||
const nextDistanceAndItem = this.items[i];
|
||||
const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile();
|
||||
parameters.context.fillStyle = "#268e4d";
|
||||
parameters.context.beginRoundedRect(worldPos.x - 5, worldPos.y - 5, 10, 10, 3);
|
||||
parameters.context.fill();
|
||||
@ -902,28 +902,28 @@ export class BeltPath extends BasicSerializableObject {
|
||||
parameters.context.fillRect(worldPos.x + 5, worldPos.y, 20, 3);
|
||||
}
|
||||
}
|
||||
for (let i: any = 0; i < this.entityPath.length; ++i) {
|
||||
const entity: any = this.entityPath[i];
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const entity = this.entityPath[i];
|
||||
parameters.context.fillStyle = "#d79a25";
|
||||
const pos: any = entity.components.StaticMapEntity;
|
||||
const worldPos: any = pos.origin.toWorldSpaceCenterOfTile();
|
||||
const pos = entity.components.StaticMapEntity;
|
||||
const worldPos = pos.origin.toWorldSpaceCenterOfTile();
|
||||
parameters.context.beginCircle(worldPos.x, worldPos.y, i === 0 ? 5 : 3);
|
||||
parameters.context.fill();
|
||||
}
|
||||
for (let progress: any = 0; progress <= this.totalLength + 0.01; progress += 0.2) {
|
||||
const worldPos: any = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile();
|
||||
for (let progress = 0; progress <= this.totalLength + 0.01; progress += 0.2) {
|
||||
const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile();
|
||||
parameters.context.fillStyle = "red";
|
||||
parameters.context.beginCircle(worldPos.x, worldPos.y, 1);
|
||||
parameters.context.fill();
|
||||
}
|
||||
const firstItemIndicator: any = this.computePositionFromProgress(this.spacingToFirstItem).toWorldSpaceCenterOfTile();
|
||||
const firstItemIndicator = this.computePositionFromProgress(this.spacingToFirstItem).toWorldSpaceCenterOfTile();
|
||||
parameters.context.fillStyle = "purple";
|
||||
parameters.context.fillRect(firstItemIndicator.x - 3, firstItemIndicator.y - 1, 6, 2);
|
||||
}
|
||||
/**
|
||||
* Checks if this belt path should render simplified
|
||||
*/
|
||||
checkIsPotatoMode(): any {
|
||||
checkIsPotatoMode() {
|
||||
// POTATO Mode: Only show items when belt is hovered
|
||||
if (!this.root.app.settings.getAllSettings().simplifiedBelts) {
|
||||
return false;
|
||||
@ -932,13 +932,13 @@ export class BeltPath extends BasicSerializableObject {
|
||||
// Not in regular layer
|
||||
return true;
|
||||
}
|
||||
const mousePos: any = this.root.app.mousePosition;
|
||||
const mousePos = this.root.app.mousePosition;
|
||||
if (!mousePos) {
|
||||
// Mouse not registered
|
||||
return true;
|
||||
}
|
||||
const tile: any = this.root.camera.screenToWorld(mousePos).toTileSpace();
|
||||
const contents: any = this.root.map.getLayerContentXY(tile.x, tile.y, "regular");
|
||||
const tile = this.root.camera.screenToWorld(mousePos).toTileSpace();
|
||||
const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular");
|
||||
if (!contents || !contents.components.Belt) {
|
||||
// Nothing below
|
||||
return true;
|
||||
@ -952,7 +952,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
/**
|
||||
* Draws the path
|
||||
*/
|
||||
draw(parameters: DrawParameters): any {
|
||||
draw(parameters: DrawParameters) {
|
||||
if (!parameters.visibleRect.containsRect(this.worldBounds)) {
|
||||
return;
|
||||
}
|
||||
@ -961,43 +961,43 @@ export class BeltPath extends BasicSerializableObject {
|
||||
return;
|
||||
}
|
||||
if (this.checkIsPotatoMode()) {
|
||||
const firstItem: any = this.items[0];
|
||||
const firstItem = this.items[0];
|
||||
if (this.entityPath.length > 1 && firstItem) {
|
||||
const medianBeltIndex: any = clamp(Math.round(this.entityPath.length / 2 - 1), 0, this.entityPath.length - 1);
|
||||
const medianBelt: any = this.entityPath[medianBeltIndex];
|
||||
const beltComp: any = medianBelt.components.Belt;
|
||||
const staticComp: any = medianBelt.components.StaticMapEntity;
|
||||
const centerPosLocal: any = beltComp.transformBeltToLocalSpace(this.entityPath.length % 2 === 0 ? beltComp.getEffectiveLengthTiles() : 0.5);
|
||||
const centerPos: any = staticComp.localTileToWorld(centerPosLocal).toWorldSpaceCenterOfTile();
|
||||
const medianBeltIndex = clamp(Math.round(this.entityPath.length / 2 - 1), 0, this.entityPath.length - 1);
|
||||
const medianBelt = this.entityPath[medianBeltIndex];
|
||||
const beltComp = medianBelt.components.Belt;
|
||||
const staticComp = medianBelt.components.StaticMapEntity;
|
||||
const centerPosLocal = beltComp.transformBeltToLocalSpace(this.entityPath.length % 2 === 0 ? beltComp.getEffectiveLengthTiles() : 0.5);
|
||||
const centerPos = staticComp.localTileToWorld(centerPosLocal).toWorldSpaceCenterOfTile();
|
||||
parameters.context.globalAlpha = 0.5;
|
||||
firstItem[1 /* item */].drawItemCenteredClipped(centerPos.x, centerPos.y, parameters);
|
||||
parameters.context.globalAlpha = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
let currentItemPos: any = this.spacingToFirstItem;
|
||||
let currentItemIndex: any = 0;
|
||||
let trackPos: any = 0.0;
|
||||
let currentItemPos = this.spacingToFirstItem;
|
||||
let currentItemIndex = 0;
|
||||
let trackPos = 0.0;
|
||||
let drawStack: Array<[
|
||||
Vector,
|
||||
BaseItem
|
||||
]> = [];
|
||||
let drawStackProp: any = "";
|
||||
let drawStackProp = "";
|
||||
// Iterate whole track and check items
|
||||
for (let i: any = 0; i < this.entityPath.length; ++i) {
|
||||
const entity: any = this.entityPath[i];
|
||||
const beltComp: any = entity.components.Belt;
|
||||
const beltLength: any = beltComp.getEffectiveLengthTiles();
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const entity = this.entityPath[i];
|
||||
const beltComp = entity.components.Belt;
|
||||
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||
// Check if the current items are on the belt
|
||||
while (trackPos + beltLength >= currentItemPos - 1e-5) {
|
||||
// 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 + ")");
|
||||
const localPos: any = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos);
|
||||
const worldPos: any = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile();
|
||||
const distanceAndItem: any = this.items[currentItemIndex];
|
||||
const item: any = distanceAndItem[1 /* item */];
|
||||
const nextItemDistance: any = distanceAndItem[0 /* nextDistance */];
|
||||
const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos);
|
||||
const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile();
|
||||
const distanceAndItem = this.items[currentItemIndex];
|
||||
const item = distanceAndItem[1 /* item */];
|
||||
const nextItemDistance = distanceAndItem[0 /* nextDistance */];
|
||||
if (!parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, globalConfig.defaultItemDiameter)) {
|
||||
// this one isn't visible, do not append it
|
||||
// Start a new stack
|
||||
@ -1008,7 +1008,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
else {
|
||||
if (drawStack.length > 1) {
|
||||
// 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) &&
|
||||
Math.abs(referenceItem[0][drawStackProp] - worldPos[drawStackProp]) < 0.001) {
|
||||
// Will continue stack
|
||||
@ -1021,11 +1021,11 @@ export class BeltPath extends BasicSerializableObject {
|
||||
}
|
||||
}
|
||||
else if (drawStack.length === 1) {
|
||||
const firstItem: any = drawStack[0];
|
||||
const firstItem = drawStack[0];
|
||||
// Check if we can make it a stack
|
||||
if (firstItem[1 /* item */].equals(item)) {
|
||||
// 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) {
|
||||
drawStackProp = "x";
|
||||
}
|
||||
@ -1079,23 +1079,23 @@ export class BeltPath extends BasicSerializableObject {
|
||||
]>;
|
||||
root: GameRoot;
|
||||
zoomLevel: number;
|
||||
}): any {
|
||||
}) {
|
||||
context.scale(dpi, dpi);
|
||||
if (G_IS_DEV && globalConfig.debug.showShapeGrouping) {
|
||||
context.fillStyle = "rgba(0, 0, 255, 0.5)";
|
||||
context.fillRect(0, 0, w, h);
|
||||
}
|
||||
const parameters: any = new DrawParameters({
|
||||
const parameters = new DrawParameters({
|
||||
context,
|
||||
desiredAtlasScale: ORIGINAL_SPRITE_SCALE,
|
||||
root,
|
||||
visibleRect: new Rectangle(-1000, -1000, 2000, 2000),
|
||||
zoomLevel,
|
||||
});
|
||||
const itemSize: any = globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
|
||||
const item: any = stack[0];
|
||||
const pos: any = new Vector(itemSize / 2, itemSize / 2);
|
||||
for (let i: any = 0; i < stack.length; i++) {
|
||||
const itemSize = globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
|
||||
const item = stack[0];
|
||||
const pos = new Vector(itemSize / 2, itemSize / 2);
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
item[1].drawItemCenteredClipped(pos.x, pos.y, parameters, globalConfig.defaultItemDiameter);
|
||||
pos[direction] += globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
|
||||
}
|
||||
@ -1103,23 +1103,23 @@ export class BeltPath extends BasicSerializableObject {
|
||||
drawDrawStack(stack: Array<[
|
||||
Vector,
|
||||
BaseItem
|
||||
]>, parameters: DrawParameters, directionProp: any): any {
|
||||
]>, parameters: DrawParameters, directionProp) {
|
||||
if (stack.length === 0) {
|
||||
return;
|
||||
}
|
||||
const firstItem: any = stack[0];
|
||||
const firstItemPos: any = firstItem[0];
|
||||
const firstItem = stack[0];
|
||||
const firstItemPos = firstItem[0];
|
||||
if (stack.length === 1) {
|
||||
firstItem[1].drawItemCenteredClipped(firstItemPos.x, firstItemPos.y, parameters, globalConfig.defaultItemDiameter);
|
||||
return;
|
||||
}
|
||||
const itemSize: any = globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
|
||||
const inverseDirection: any = directionProp === "x" ? "y" : "x";
|
||||
const dimensions: any = new Vector(itemSize, itemSize);
|
||||
const itemSize = globalConfig.itemSpacingOnBelts * globalConfig.tileSize;
|
||||
const inverseDirection = directionProp === "x" ? "y" : "x";
|
||||
const dimensions = new Vector(itemSize, itemSize);
|
||||
dimensions[inverseDirection] *= stack.length;
|
||||
const directionVector: any = firstItemPos.copy().sub(stack[1][0]);
|
||||
const dpi: any = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel);
|
||||
const sprite: any = this.root.buffers.getForKey({
|
||||
const directionVector = firstItemPos.copy().sub(stack[1][0]);
|
||||
const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel);
|
||||
const sprite = this.root.buffers.getForKey({
|
||||
key: "beltpaths",
|
||||
subKey: "stack-" +
|
||||
directionProp +
|
||||
@ -1142,7 +1142,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -23,21 +23,21 @@ export class Blueprint {
|
||||
/**
|
||||
* Creates a new blueprint from the given entity uids
|
||||
*/
|
||||
static fromUids(root: GameRoot, uids: Array<number>): any {
|
||||
const newEntities: any = [];
|
||||
let averagePosition: any = new Vector();
|
||||
static fromUids(root: GameRoot, uids: Array<number>) {
|
||||
const newEntities = [];
|
||||
let averagePosition = new Vector();
|
||||
// First, create a copy
|
||||
for (let i: any = 0; i < uids.length; ++i) {
|
||||
const entity: any = root.entityMgr.findByUid(uids[i]);
|
||||
for (let i = 0; i < uids.length; ++i) {
|
||||
const entity = root.entityMgr.findByUid(uids[i]);
|
||||
assert(entity, "Entity for blueprint not found:" + uids[i]);
|
||||
const clone: any = entity.clone();
|
||||
const clone = entity.clone();
|
||||
newEntities.push(clone);
|
||||
const pos: any = entity.components.StaticMapEntity.getTileSpaceBounds().getCenter();
|
||||
const pos = entity.components.StaticMapEntity.getTileSpaceBounds().getCenter();
|
||||
averagePosition.addInplace(pos);
|
||||
}
|
||||
averagePosition.divideScalarInplace(uids.length);
|
||||
const blueprintOrigin: any = averagePosition.subScalars(0.5, 0.5).floor();
|
||||
for (let i: any = 0; i < uids.length; ++i) {
|
||||
const blueprintOrigin = averagePosition.subScalars(0.5, 0.5).floor();
|
||||
for (let i = 0; i < uids.length; ++i) {
|
||||
newEntities[i].components.StaticMapEntity.origin.subInplace(blueprintOrigin);
|
||||
}
|
||||
// Now, make sure the origin is 0,0
|
||||
@ -46,7 +46,7 @@ export class Blueprint {
|
||||
/**
|
||||
* Returns the cost of this blueprint in shapes
|
||||
*/
|
||||
getCost(): any {
|
||||
getCost() {
|
||||
if (G_IS_DEV && globalConfig.debug.blueprintsNoCost) {
|
||||
return 0;
|
||||
}
|
||||
@ -55,13 +55,13 @@ export class Blueprint {
|
||||
/**
|
||||
* Draws the blueprint at the given origin
|
||||
*/
|
||||
draw(parameters: DrawParameters, tile: any): any {
|
||||
draw(parameters: DrawParameters, tile) {
|
||||
parameters.context.globalAlpha = 0.8;
|
||||
for (let i: any = 0; i < this.entities.length; ++i) {
|
||||
const entity: any = this.entities[i];
|
||||
const staticComp: any = entity.components.StaticMapEntity;
|
||||
const newPos: any = staticComp.origin.add(tile);
|
||||
const rect: any = staticComp.getTileSpaceBounds();
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
const entity = this.entities[i];
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const newPos = staticComp.origin.add(tile);
|
||||
const rect = staticComp.getTileSpaceBounds();
|
||||
rect.moveBy(tile.x, tile.y);
|
||||
if (!parameters.root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
|
||||
parameters.context.globalAlpha = 0.3;
|
||||
@ -76,10 +76,10 @@ export class Blueprint {
|
||||
/**
|
||||
* Rotates the blueprint clockwise
|
||||
*/
|
||||
rotateCw(): any {
|
||||
for (let i: any = 0; i < this.entities.length; ++i) {
|
||||
const entity: any = this.entities[i];
|
||||
const staticComp: any = entity.components.StaticMapEntity;
|
||||
rotateCw() {
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
const entity = this.entities[i];
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
// Actually keeping this in as an easter egg to rotate the trash can
|
||||
// if (staticComp.getMetaBuilding().getIsRotateable()) {
|
||||
staticComp.rotation = (staticComp.rotation + 90) % 360;
|
||||
@ -91,26 +91,26 @@ export class Blueprint {
|
||||
/**
|
||||
* Rotates the blueprint counter clock wise
|
||||
*/
|
||||
rotateCcw(): any {
|
||||
rotateCcw() {
|
||||
// Well ...
|
||||
for (let i: any = 0; i < 3; ++i) {
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
this.rotateCw();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks if the blueprint can be placed at the given tile
|
||||
*/
|
||||
canPlace(root: GameRoot, tile: Vector): any {
|
||||
let anyPlaceable: any = false;
|
||||
for (let i: any = 0; i < this.entities.length; ++i) {
|
||||
const entity: any = this.entities[i];
|
||||
canPlace(root: GameRoot, tile: Vector) {
|
||||
let anyPlaceable = false;
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
const entity = this.entities[i];
|
||||
if (root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
|
||||
anyPlaceable = true;
|
||||
}
|
||||
}
|
||||
return anyPlaceable;
|
||||
}
|
||||
canAfford(root: GameRoot): any {
|
||||
canAfford(root: GameRoot) {
|
||||
if (root.gameMode.getHasFreeCopyPaste()) {
|
||||
return true;
|
||||
}
|
||||
@ -119,16 +119,16 @@ export class Blueprint {
|
||||
/**
|
||||
* Attempts to place the blueprint at the given tile
|
||||
*/
|
||||
tryPlace(root: GameRoot, tile: Vector): any {
|
||||
return root.logic.performBulkOperation((): any => {
|
||||
return root.logic.performImmutableOperation((): any => {
|
||||
let count: any = 0;
|
||||
for (let i: any = 0; i < this.entities.length; ++i) {
|
||||
const entity: any = this.entities[i];
|
||||
tryPlace(root: GameRoot, tile: Vector) {
|
||||
return root.logic.performBulkOperation(() => {
|
||||
return root.logic.performImmutableOperation(() => {
|
||||
let count = 0;
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
const entity = this.entities[i];
|
||||
if (!root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
|
||||
continue;
|
||||
}
|
||||
const clone: any = entity.clone();
|
||||
const clone = entity.clone();
|
||||
clone.components.StaticMapEntity.origin.addInplace(tile);
|
||||
root.logic.freeEntityAreaBeforeBuild(clone);
|
||||
root.map.placeStaticEntity(clone);
|
||||
|
@ -30,7 +30,7 @@ const variantsCache: Map<string, number | string> = new Map();
|
||||
/**
|
||||
* 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);
|
||||
gBuildingVariants[code] = {
|
||||
metaClass: meta,
|
||||
@ -166,7 +166,7 @@ functiorateBuildingHash(build string, variant: strin
|
||||
* @param {number} rotationVariant
|
||||
* @returns
|
||||
*/
|
||||
function generateBuildingHash(buildingId: string, variant: string, rotationVariant: number): any {
|
||||
function generateBuildingHash(buildingId: string, variant: string, rotationVariant: number) {
|
||||
return buildingId + "/" + variant + "/" + rotationVariant;
|
||||
}
|
||||
/**
|
||||
@ -180,10 +180,10 @@ export function getBuildingDataFromCode(code: string | number): BuildingVariantI
|
||||
/**
|
||||
* Builds the cache for the codes
|
||||
*/
|
||||
export function buildBuildingCodeCache(): any {
|
||||
for (const code: any in gBuildingVariants) {
|
||||
const data: any = gBuildingVariants[code];
|
||||
const hash: any = generateBuildingHash(data.metaInstance.getId(), data.variant, data.rotationVariant);
|
||||
export function buildBuildingCodeCache() {
|
||||
for (const code in gBuildingVariants) {
|
||||
const data = gBuildingVariants[code];
|
||||
const hash = generateBuildingHash(data.metaInstance.getId(), data.variant, data.rotationVariant);
|
||||
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 {
|
||||
const hash: any = generateBuildingHash(metaBuilding.getId(), variant, rotationVariant);
|
||||
const result: any = variantsCache.get(hash);
|
||||
const hash = generateBuildingHash(metaBuilding.getId(), variant, rotationVariant);
|
||||
const result = variantsCache.get(hash);
|
||||
if (G_IS_DEV) {
|
||||
if (!result) {
|
||||
console.warn("Known hashes:", Array.from(variantsCache.keys()));
|
||||
|
@ -6,13 +6,13 @@ import { Entity } from "../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
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 {
|
||||
|
||||
constructor() {
|
||||
super("analyzer");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 43,
|
||||
@ -20,30 +20,30 @@ export class MetaAnalyzerBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#3a52bc";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing);
|
||||
}
|
||||
/** {} **/
|
||||
getLayer(): "wires" {
|
||||
return "wires";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getRenderPins(): any {
|
||||
getRenderPins() {
|
||||
// We already have it included
|
||||
return false;
|
||||
}
|
||||
getSpecialOverlayRenderMatrix(rotation: any, rotationVariant: any, variant: any): any {
|
||||
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
|
||||
return overlayMatrix[rotation];
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -10,13 +10,13 @@ import { T } from "../../translations";
|
||||
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
|
||||
import { BeltUnderlaysComponent } from "../components/belt_underlays";
|
||||
/** @enum {string} */
|
||||
export const enumBalancerVariants: any = {
|
||||
export const enumBalancerVariants = {
|
||||
merger: "merger",
|
||||
mergerInverse: "merger-inverse",
|
||||
splitter: "splitter",
|
||||
splitterInverse: "splitter-inverse",
|
||||
};
|
||||
const overlayMatrices: any = {
|
||||
const overlayMatrices = {
|
||||
[defaultBuildingVariant]: null,
|
||||
[enumBalancerVariants.merger]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 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() {
|
||||
super("balancer");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 4,
|
||||
@ -52,7 +52,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getDimensions(variant: any): any {
|
||||
getDimensions(variant) {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant:
|
||||
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 {
|
||||
const matrix: any = overlayMatrices[variant];
|
||||
const matrix = overlayMatrices[variant];
|
||||
if (matrix) {
|
||||
return matrix[rotation];
|
||||
}
|
||||
@ -85,7 +85,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
||||
if (root.gameMode.throughputDoesNotMatter()) {
|
||||
return [];
|
||||
}
|
||||
let speedMultiplier: any = 2;
|
||||
let speedMultiplier = 2;
|
||||
switch (variant) {
|
||||
case enumBalancerVariants.merger:
|
||||
case enumBalancerVariants.mergerInverse:
|
||||
@ -93,15 +93,15 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
||||
case enumBalancerVariants.splitterInverse:
|
||||
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)]];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#555759";
|
||||
}
|
||||
getAvailableVariants(root: GameRoot): any {
|
||||
const deterministic: any = root.gameMode.getIsDeterministic();
|
||||
let available: any = deterministic ? [] : [defaultBuildingVariant];
|
||||
getAvailableVariants(root: GameRoot) {
|
||||
const deterministic = root.gameMode.getIsDeterministic();
|
||||
let available = deterministic ? [] : [defaultBuildingVariant];
|
||||
if (!deterministic && root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_merger)) {
|
||||
available.push(enumBalancerVariants.merger, enumBalancerVariants.mergerInverse);
|
||||
}
|
||||
@ -110,13 +110,13 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
||||
}
|
||||
return available;
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_balancer);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemAcceptorComponent({
|
||||
slots: [], // set later
|
||||
}));
|
||||
@ -130,7 +130,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
||||
}));
|
||||
entity.addComponent(new BeltUnderlaysComponent({ underlays: [] }));
|
||||
}
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant: string): any {
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant: string) {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant: {
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
|
@ -8,8 +8,8 @@ import { Entity } from "../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { THEME } from "../theme";
|
||||
export const arrayBeltVariantToRotation: any = [enumDirection.top, enumDirection.left, enumDirection.right];
|
||||
export const beltOverlayMatrices: any = {
|
||||
export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right];
|
||||
export const beltOverlayMatrices = {
|
||||
[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.right]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
|
||||
@ -19,7 +19,7 @@ export class MetaBeltBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("belt");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 1,
|
||||
@ -38,25 +38,25 @@ export class MetaBeltBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return THEME.map.chunkOverview.beltColor;
|
||||
}
|
||||
getPlacementSound(): any {
|
||||
getPlacementSound() {
|
||||
return SOUNDS.placeBelt;
|
||||
}
|
||||
getHasDirectionLockAvailable(): any {
|
||||
getHasDirectionLockAvailable() {
|
||||
return true;
|
||||
}
|
||||
getStayInPlacementMode(): any {
|
||||
getStayInPlacementMode() {
|
||||
return true;
|
||||
}
|
||||
getRotateAutomaticallyWhilePlacing(): any {
|
||||
getRotateAutomaticallyWhilePlacing() {
|
||||
return true;
|
||||
}
|
||||
getSprite(): any {
|
||||
getSprite() {
|
||||
return null;
|
||||
}
|
||||
getIsReplaceable(): any {
|
||||
getIsReplaceable() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
@ -69,10 +69,10 @@ export class MetaBeltBuilding extends MetaBuilding {
|
||||
if (root.gameMode.throughputDoesNotMatter()) {
|
||||
return [];
|
||||
}
|
||||
const beltSpeed: any = root.hubGoals.getBeltBaseSpeed();
|
||||
const beltSpeed = root.hubGoals.getBeltBaseSpeed();
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
|
||||
}
|
||||
getPreviewSprite(rotationVariant: any): any {
|
||||
getPreviewSprite(rotationVariant) {
|
||||
switch (arrayBeltVariantToRotation[rotationVariant]) {
|
||||
case enumDirection.top: {
|
||||
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]) {
|
||||
case enumDirection.top: {
|
||||
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];
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new BeltComponent({
|
||||
direction: enumDirection.top, // updated later
|
||||
}));
|
||||
}
|
||||
updateVariants(entity: Entity, rotationVariant: number): any {
|
||||
updateVariants(entity: Entity, rotationVariant: number) {
|
||||
entity.components.Belt.direction = arrayBeltVariantToRotation[rotationVariant];
|
||||
}
|
||||
/**
|
||||
@ -133,20 +133,20 @@ export class MetaBeltBuilding extends MetaBuilding {
|
||||
rotationVariant: number;
|
||||
connectedEntities?: Array<Entity>;
|
||||
} {
|
||||
const topDirection: any = enumAngleToDirection[rotation];
|
||||
const rightDirection: any = enumAngleToDirection[(rotation + 90) % 360];
|
||||
const bottomDirection: any = enumAngleToDirection[(rotation + 180) % 360];
|
||||
const leftDirection: any = enumAngleToDirection[(rotation + 270) % 360];
|
||||
const { ejectors, acceptors }: any = root.logic.getEjectorsAndAcceptorsAtTile(tile);
|
||||
let hasBottomEjector: any = false;
|
||||
let hasRightEjector: any = false;
|
||||
let hasLeftEjector: any = false;
|
||||
let hasTopAcceptor: any = false;
|
||||
let hasLeftAcceptor: any = false;
|
||||
let hasRightAcceptor: any = false;
|
||||
const topDirection = enumAngleToDirection[rotation];
|
||||
const rightDirection = enumAngleToDirection[(rotation + 90) % 360];
|
||||
const bottomDirection = enumAngleToDirection[(rotation + 180) % 360];
|
||||
const leftDirection = enumAngleToDirection[(rotation + 270) % 360];
|
||||
const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile);
|
||||
let hasBottomEjector = false;
|
||||
let hasRightEjector = false;
|
||||
let hasLeftEjector = false;
|
||||
let hasTopAcceptor = false;
|
||||
let hasLeftAcceptor = false;
|
||||
let hasRightAcceptor = false;
|
||||
// Check all ejectors
|
||||
for (let i: any = 0; i < ejectors.length; ++i) {
|
||||
const ejector: any = ejectors[i];
|
||||
for (let i = 0; i < ejectors.length; ++i) {
|
||||
const ejector = ejectors[i];
|
||||
if (ejector.toDirection === topDirection) {
|
||||
hasBottomEjector = true;
|
||||
}
|
||||
@ -158,8 +158,8 @@ export class MetaBeltBuilding extends MetaBuilding {
|
||||
}
|
||||
}
|
||||
// Check all acceptors
|
||||
for (let i: any = 0; i < acceptors.length; ++i) {
|
||||
const acceptor: any = acceptors[i];
|
||||
for (let i = 0; i < acceptors.length; ++i) {
|
||||
const acceptor = acceptors[i];
|
||||
if (acceptor.fromDirection === bottomDirection) {
|
||||
hasTopAcceptor = true;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ export class MetaBlockBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("block");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 64,
|
||||
@ -15,7 +15,7 @@ export class MetaBlockBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#333";
|
||||
}
|
||||
/**
|
||||
@ -138,11 +138,11 @@ export class MetaBlockBuilding extends MetaBuilding {
|
||||
* @param {import("../../savegame/savegame_serializer").GameRoot} root
|
||||
* @returns
|
||||
*/
|
||||
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot): any {
|
||||
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot) {
|
||||
return root.gameMode.getIsEditor();
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any { }
|
||||
setupEntityComponents(entity: Entity) { }
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ export class MetaComparatorBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("comparator");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 46,
|
||||
@ -18,27 +18,27 @@ export class MetaComparatorBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#823cab";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing);
|
||||
}
|
||||
/** {} **/
|
||||
getLayer(): "wires" {
|
||||
return "wires";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getRenderPins(): any {
|
||||
getRenderPins() {
|
||||
// We already have it included
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ export class MetaConstantProducerBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("constant_producer");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 62,
|
||||
@ -19,7 +19,7 @@ export class MetaConstantProducerBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#bfd630";
|
||||
}
|
||||
/**
|
||||
@ -142,13 +142,13 @@ export class MetaConstantProducerBuilding extends MetaBuilding {
|
||||
* @param {import("../../savegame/savegame_serializer").GameRoot} root
|
||||
* @returns
|
||||
*/
|
||||
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot): any {
|
||||
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot) {
|
||||
return root.gameMode.getIsEditor();
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemEjectorComponent({
|
||||
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
|
||||
}));
|
||||
|
@ -6,13 +6,13 @@ import { GameRoot } from "../root";
|
||||
import { ConstantSignalComponent } from "../components/constant_signal";
|
||||
import { generateMatrixRotations } from "../../core/utils";
|
||||
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 {
|
||||
|
||||
constructor() {
|
||||
super("constant_signal");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 31,
|
||||
@ -20,29 +20,29 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#2b84fd";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_constant_signal);
|
||||
}
|
||||
/** {} **/
|
||||
getLayer(): "wires" {
|
||||
return "wires";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getRenderPins(): any {
|
||||
getRenderPins() {
|
||||
return false;
|
||||
}
|
||||
getSpecialOverlayRenderMatrix(rotation: any): any {
|
||||
getSpecialOverlayRenderMatrix(rotation) {
|
||||
return overlayMatrix[rotation];
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -9,13 +9,13 @@ import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
/** @enum {string} */
|
||||
export const enumCutterVariants: any = { quad: "quad" };
|
||||
export const enumCutterVariants = { quad: "quad" };
|
||||
export class MetaCutterBuilding extends MetaBuilding {
|
||||
|
||||
constructor() {
|
||||
super("cutter");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 9,
|
||||
@ -27,10 +27,10 @@ export class MetaCutterBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#7dcda2";
|
||||
}
|
||||
getDimensions(variant: any): any {
|
||||
getDimensions(variant) {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant:
|
||||
return new Vector(2, 1);
|
||||
@ -50,24 +50,24 @@ export class MetaCutterBuilding extends MetaBuilding {
|
||||
if (root.gameMode.throughputDoesNotMatter()) {
|
||||
return [];
|
||||
}
|
||||
const speed: any = root.hubGoals.getProcessorBaseSpeed(variant === enumCutterVariants.quad
|
||||
const speed = root.hubGoals.getProcessorBaseSpeed(variant === enumCutterVariants.quad
|
||||
? enumItemProcessorTypes.cutterQuad
|
||||
: enumItemProcessorTypes.cutter);
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||
}
|
||||
getAvailableVariants(root: GameRoot): any {
|
||||
getAvailableVariants(root: GameRoot) {
|
||||
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_quad)) {
|
||||
return [defaultBuildingVariant, enumCutterVariants.quad];
|
||||
}
|
||||
return super.getAvailableVariants(root);
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemProcessorComponent({
|
||||
inputsPerCharge: 1,
|
||||
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) {
|
||||
case defaultBuildingVariant: {
|
||||
entity.components.ItemEjector.setSlots([
|
||||
|
@ -10,7 +10,7 @@ export class MetaDisplayBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("display");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 40,
|
||||
@ -18,22 +18,22 @@ export class MetaDisplayBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#aaaaaa";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_display);
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getShowWiresLayerPreview(): any {
|
||||
getShowWiresLayerPreview() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ export class MetaFilterBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("filter");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 37,
|
||||
@ -22,16 +22,16 @@ export class MetaFilterBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#c45c2e";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_filter);
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(2, 1);
|
||||
}
|
||||
getShowWiresLayerPreview(): any {
|
||||
getShowWiresLayerPreview() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
@ -44,13 +44,13 @@ export class MetaFilterBuilding extends MetaBuilding {
|
||||
if (root.gameMode.throughputDoesNotMatter()) {
|
||||
return [];
|
||||
}
|
||||
const beltSpeed: any = root.hubGoals.getBeltBaseSpeed();
|
||||
const beltSpeed = root.hubGoals.getBeltBaseSpeed();
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("goal_acceptor");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 63,
|
||||
@ -19,7 +19,7 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#ce418a";
|
||||
}
|
||||
/**
|
||||
@ -142,13 +142,13 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding {
|
||||
* @param {import("../../savegame/savegame_serializer").GameRoot} root
|
||||
* @returns
|
||||
*/
|
||||
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot): any {
|
||||
getIsRemovable(root: import("../../savegame/savegame_serializer").GameRoot) {
|
||||
return root.gameMode.getIsEditor();
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemAcceptorComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -10,7 +10,7 @@ export class MetaHubBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("hub");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 26,
|
||||
@ -18,29 +18,29 @@ export class MetaHubBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(4, 4);
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#eb5555";
|
||||
}
|
||||
getIsRotateable(): any {
|
||||
getIsRotateable() {
|
||||
return false;
|
||||
}
|
||||
getBlueprintSprite(): any {
|
||||
getBlueprintSprite() {
|
||||
return null;
|
||||
}
|
||||
getSprite(): any {
|
||||
getSprite() {
|
||||
// We render it ourself
|
||||
return null;
|
||||
}
|
||||
getIsRemovable(): any {
|
||||
getIsRemovable() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new HubComponent());
|
||||
entity.addComponent(new ItemProcessorComponent({
|
||||
inputsPerCharge: 1,
|
||||
@ -56,7 +56,7 @@ export class MetaHubBuilding extends MetaBuilding {
|
||||
],
|
||||
}));
|
||||
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" });
|
||||
}
|
||||
entity.addComponent(new ItemAcceptorComponent({
|
||||
|
@ -9,7 +9,7 @@ export class MetaItemProducerBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("item_producer");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 61,
|
||||
@ -17,16 +17,16 @@ export class MetaItemProducerBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#b37dcd";
|
||||
}
|
||||
getShowWiresLayerPreview(): any {
|
||||
getShowWiresLayerPreview() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemEjectorComponent({
|
||||
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
|
||||
}));
|
||||
|
@ -10,7 +10,7 @@ export class MetaLeverBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("lever");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 33,
|
||||
@ -18,26 +18,26 @@ export class MetaLeverBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
// @todo: Render differently based on if its activated or not
|
||||
return "#1a678b";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers);
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getSprite(): any {
|
||||
getSprite() {
|
||||
return null;
|
||||
}
|
||||
getShowWiresLayerPreview(): any {
|
||||
getShowWiresLayerPreview() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -7,25 +7,25 @@ import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"
|
||||
import { generateMatrixRotations } from "../../core/utils";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
/** @enum {string} */
|
||||
export const enumLogicGateVariants: any = {
|
||||
export const enumLogicGateVariants = {
|
||||
not: "not",
|
||||
xor: "xor",
|
||||
or: "or",
|
||||
};
|
||||
/** @enum {string} */
|
||||
const enumVariantToGate: any = {
|
||||
const enumVariantToGate = {
|
||||
[defaultBuildingVariant]: enumLogicGateType.and,
|
||||
[enumLogicGateVariants.not]: enumLogicGateType.not,
|
||||
[enumLogicGateVariants.xor]: enumLogicGateType.xor,
|
||||
[enumLogicGateVariants.or]: enumLogicGateType.or,
|
||||
};
|
||||
const overlayMatrices: any = {
|
||||
const overlayMatrices = {
|
||||
[defaultBuildingVariant]: 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.not]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
|
||||
};
|
||||
const colors: any = {
|
||||
const colors = {
|
||||
[defaultBuildingVariant]: "#f48d41",
|
||||
[enumLogicGateVariants.xor]: "#f4a241",
|
||||
[enumLogicGateVariants.or]: "#f4d041",
|
||||
@ -36,7 +36,7 @@ export class MetaLogicGateBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("logic_gate");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 32,
|
||||
@ -56,23 +56,23 @@ export class MetaLogicGateBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(variant: any): any {
|
||||
getSilhouetteColor(variant) {
|
||||
return colors[variant];
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates);
|
||||
}
|
||||
/** {} **/
|
||||
getLayer(): "wires" {
|
||||
return "wires";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getSpecialOverlayRenderMatrix(rotation: any, rotationVariant: any, variant: any): any {
|
||||
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
|
||||
return overlayMatrices[variant][rotation];
|
||||
}
|
||||
getAvailableVariants(): any {
|
||||
getAvailableVariants() {
|
||||
return [
|
||||
defaultBuildingVariant,
|
||||
enumLogicGateVariants.or,
|
||||
@ -80,14 +80,14 @@ export class MetaLogicGateBuilding extends MetaBuilding {
|
||||
enumLogicGateVariants.xor,
|
||||
];
|
||||
}
|
||||
getRenderPins(): any {
|
||||
getRenderPins() {
|
||||
// We already have it included
|
||||
return false;
|
||||
}
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant: any): any {
|
||||
const gateType: any = enumVariantToGate[variant];
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant) {
|
||||
const gateType = enumVariantToGate[variant];
|
||||
entity.components.LogicGate.type = gateType;
|
||||
const pinComp: any = entity.components.WiredPins;
|
||||
const pinComp = entity.components.WiredPins;
|
||||
switch (gateType) {
|
||||
case enumLogicGateType.and:
|
||||
case enumLogicGateType.xor:
|
||||
@ -133,7 +133,7 @@ export class MetaLogicGateBuilding extends MetaBuilding {
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [],
|
||||
}));
|
||||
|
@ -8,8 +8,8 @@ import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
import { T } from "../../translations";
|
||||
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
|
||||
/** @enum {string} */
|
||||
export const enumMinerVariants: any = { chainable: "chainable" };
|
||||
const overlayMatrix: any = {
|
||||
export const enumMinerVariants = { chainable: "chainable" };
|
||||
const overlayMatrix = {
|
||||
[defaultBuildingVariant]: generateMatrixRotations([1, 1, 1, 1, 0, 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() {
|
||||
super("miner");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 7,
|
||||
@ -30,7 +30,7 @@ export class MetaMinerBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#b37dcd";
|
||||
}
|
||||
/**
|
||||
@ -43,28 +43,28 @@ export class MetaMinerBuilding extends MetaBuilding {
|
||||
if (root.gameMode.throughputDoesNotMatter()) {
|
||||
return [];
|
||||
}
|
||||
const speed: any = root.hubGoals.getMinerBaseSpeed();
|
||||
const speed = root.hubGoals.getMinerBaseSpeed();
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||
}
|
||||
getAvailableVariants(root: GameRoot): any {
|
||||
getAvailableVariants(root: GameRoot) {
|
||||
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) {
|
||||
return [enumMinerVariants.chainable];
|
||||
}
|
||||
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];
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new MinerComponent({}));
|
||||
entity.addComponent(new ItemEjectorComponent({
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export class MetaMixerBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("mixer");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 15,
|
||||
@ -21,13 +21,13 @@ export class MetaMixerBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(2, 1);
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#cdbb7d";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_mixer);
|
||||
}
|
||||
/**
|
||||
@ -40,13 +40,13 @@ export class MetaMixerBuilding extends MetaBuilding {
|
||||
if (root.gameMode.throughputDoesNotMatter()) {
|
||||
return [];
|
||||
}
|
||||
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.mixer);
|
||||
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.mixer);
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemProcessorComponent({
|
||||
inputsPerCharge: 2,
|
||||
processorType: enumItemProcessorTypes.mixer,
|
||||
|
@ -10,13 +10,13 @@ import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
|
||||
/** @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 {
|
||||
|
||||
constructor() {
|
||||
super("painter");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 16,
|
||||
@ -36,7 +36,7 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getDimensions(variant: any): any {
|
||||
getDimensions(variant) {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant:
|
||||
case enumPainterVariants.mirrored:
|
||||
@ -49,7 +49,7 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
assertAlways(false, "Unknown painter variant: " + variant);
|
||||
}
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#cd9b7d";
|
||||
}
|
||||
/**
|
||||
@ -65,21 +65,21 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant:
|
||||
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)]];
|
||||
}
|
||||
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)]];
|
||||
}
|
||||
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)]];
|
||||
}
|
||||
}
|
||||
}
|
||||
getAvailableVariants(root: GameRoot): any {
|
||||
let variants: any = [defaultBuildingVariant, enumPainterVariants.mirrored];
|
||||
getAvailableVariants(root: GameRoot) {
|
||||
let variants = [defaultBuildingVariant, enumPainterVariants.mirrored];
|
||||
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_double)) {
|
||||
variants.push(enumPainterVariants.double);
|
||||
}
|
||||
@ -89,13 +89,13 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemProcessorComponent({}));
|
||||
entity.addComponent(new ItemEjectorComponent({
|
||||
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) {
|
||||
case defaultBuildingVariant:
|
||||
case enumPainterVariants.mirrored: {
|
||||
|
@ -10,13 +10,13 @@ import { BeltUnderlaysComponent } from "../components/belt_underlays";
|
||||
import { BeltReaderComponent } from "../components/belt_reader";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
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 {
|
||||
|
||||
constructor() {
|
||||
super("reader");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 49,
|
||||
@ -24,16 +24,16 @@ export class MetaReaderBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#25fff2";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_belt_reader);
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getShowWiresLayerPreview(): any {
|
||||
getShowWiresLayerPreview() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
@ -45,7 +45,7 @@ export class MetaReaderBuilding extends MetaBuilding {
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -9,8 +9,8 @@ import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
/** @enum {string} */
|
||||
export const enumRotaterVariants: any = { ccw: "ccw", rotate180: "rotate180" };
|
||||
const overlayMatrices: any = {
|
||||
export const enumRotaterVariants = { ccw: "ccw", rotate180: "rotate180" };
|
||||
const overlayMatrices = {
|
||||
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 1, 1, 1, 0, 0, 1, 1]),
|
||||
[enumRotaterVariants.ccw]: generateMatrixRotations([1, 1, 0, 0, 1, 1, 1, 1, 0]),
|
||||
[enumRotaterVariants.rotate180]: generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]),
|
||||
@ -20,7 +20,7 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("rotater");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 11,
|
||||
@ -36,14 +36,14 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#7dc6cd";
|
||||
}
|
||||
/**
|
||||
* {}
|
||||
*/
|
||||
getSpecialOverlayRenderMatrix(rotation: number, rotationVariant: number, variant: string, entity: Entity): Array<number> | null {
|
||||
const matrix: any = overlayMatrices[variant];
|
||||
const matrix = overlayMatrices[variant];
|
||||
if (matrix) {
|
||||
return matrix[rotation];
|
||||
}
|
||||
@ -61,21 +61,21 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
||||
}
|
||||
switch (variant) {
|
||||
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)]];
|
||||
}
|
||||
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)]];
|
||||
}
|
||||
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)]];
|
||||
}
|
||||
}
|
||||
}
|
||||
getAvailableVariants(root: GameRoot): any {
|
||||
let variants: any = [defaultBuildingVariant];
|
||||
getAvailableVariants(root: GameRoot) {
|
||||
let variants = [defaultBuildingVariant];
|
||||
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) {
|
||||
variants.push(enumRotaterVariants.ccw);
|
||||
}
|
||||
@ -84,13 +84,13 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemProcessorComponent({
|
||||
inputsPerCharge: 1,
|
||||
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) {
|
||||
case defaultBuildingVariant: {
|
||||
entity.components.ItemProcessor.type = enumItemProcessorTypes.rotater;
|
||||
|
@ -13,7 +13,7 @@ export class MetaStackerBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("stacker");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 14,
|
||||
@ -21,10 +21,10 @@ export class MetaStackerBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#9fcd7d";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(2, 1);
|
||||
}
|
||||
/**
|
||||
@ -37,16 +37,16 @@ export class MetaStackerBuilding extends MetaBuilding {
|
||||
if (root.gameMode.throughputDoesNotMatter()) {
|
||||
return [];
|
||||
}
|
||||
const speed: any = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.stacker);
|
||||
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.stacker);
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_stacker);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemProcessorComponent({
|
||||
inputsPerCharge: 2,
|
||||
processorType: enumItemProcessorTypes.stacker,
|
||||
|
@ -9,13 +9,13 @@ import { Entity } from "../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
const storageSize: any = 5000;
|
||||
const storageSize = 5000;
|
||||
export class MetaStorageBuilding extends MetaBuilding {
|
||||
|
||||
constructor() {
|
||||
super("storage");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 21,
|
||||
@ -23,28 +23,28 @@ export class MetaStorageBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#bbdf6d";
|
||||
}
|
||||
/**
|
||||
* {}
|
||||
*/
|
||||
getAdditionalStatistics(root: any, variant: any): Array<[
|
||||
getAdditionalStatistics(root, variant): Array<[
|
||||
string,
|
||||
string
|
||||
]> {
|
||||
return [[T.ingame.buildingPlacement.infoTexts.storage, formatBigNumber(storageSize)]];
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(2, 2);
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_storage);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
// Required, since the item processor needs this.
|
||||
entity.addComponent(new ItemEjectorComponent({
|
||||
slots: [
|
||||
|
@ -7,10 +7,10 @@ import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
/** @enum {string} */
|
||||
export const enumTransistorVariants: any = {
|
||||
export const enumTransistorVariants = {
|
||||
mirrored: "mirrored",
|
||||
};
|
||||
const overlayMatrices: any = {
|
||||
const overlayMatrices = {
|
||||
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 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() {
|
||||
super("transistor");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 38,
|
||||
@ -31,37 +31,37 @@ export class MetaTransistorBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#bc3a61";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates);
|
||||
}
|
||||
/** {} **/
|
||||
getLayer(): "wires" {
|
||||
return "wires";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getAvailableVariants(): any {
|
||||
getAvailableVariants() {
|
||||
return [defaultBuildingVariant, enumTransistorVariants.mirrored];
|
||||
}
|
||||
getSpecialOverlayRenderMatrix(rotation: any, rotationVariant: any, variant: any): any {
|
||||
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
|
||||
return overlayMatrices[variant][rotation];
|
||||
}
|
||||
getRenderPins(): any {
|
||||
getRenderPins() {
|
||||
// We already have it included
|
||||
return false;
|
||||
}
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant: any): any {
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant) {
|
||||
entity.components.WiredPins.slots[1].direction =
|
||||
variant === enumTransistorVariants.mirrored ? enumDirection.right : enumDirection.left;
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -7,13 +7,13 @@ import { Entity } from "../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
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 {
|
||||
|
||||
constructor() {
|
||||
super("trash");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 20,
|
||||
@ -21,29 +21,29 @@ export class MetaTrashBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getIsRotateable(): any {
|
||||
getIsRotateable() {
|
||||
return false;
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#ed1d5d";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getSpecialOverlayRenderMatrix(rotation: any): any {
|
||||
getSpecialOverlayRenderMatrix(rotation) {
|
||||
return overlayMatrix[rotation];
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash);
|
||||
}
|
||||
addAchievementReceiver(entity: any): any {
|
||||
addAchievementReceiver(entity) {
|
||||
if (!entity.root) {
|
||||
return;
|
||||
}
|
||||
const itemProcessor: any = entity.components.ItemProcessor;
|
||||
const tryTakeItem: any = itemProcessor.tryTakeItem.bind(itemProcessor);
|
||||
itemProcessor.tryTakeItem = (): any => {
|
||||
const taken: any = tryTakeItem(...arguments);
|
||||
const itemProcessor = entity.components.ItemProcessor;
|
||||
const tryTakeItem = itemProcessor.tryTakeItem.bind(itemProcessor);
|
||||
itemProcessor.tryTakeItem = () => {
|
||||
const taken = tryTakeItem(...arguments);
|
||||
if (taken) {
|
||||
entity.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.trash1000, 1);
|
||||
}
|
||||
@ -53,7 +53,7 @@ export class MetaTrashBuilding extends MetaBuilding {
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new ItemAcceptorComponent({
|
||||
slots: [
|
||||
{
|
||||
|
@ -11,18 +11,18 @@ import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
|
||||
import { T } from "../../translations";
|
||||
/** @enum {string} */
|
||||
export const arrayUndergroundRotationVariantToMode: any = [
|
||||
export const arrayUndergroundRotationVariantToMode = [
|
||||
enumUndergroundBeltMode.sender,
|
||||
enumUndergroundBeltMode.receiver,
|
||||
];
|
||||
/** @enum {string} */
|
||||
export const enumUndergroundBeltVariants: any = { tier2: "tier2" };
|
||||
export const enumUndergroundBeltVariantToTier: any = {
|
||||
export const enumUndergroundBeltVariants = { tier2: "tier2" };
|
||||
export const enumUndergroundBeltVariantToTier = {
|
||||
[defaultBuildingVariant]: 0,
|
||||
[enumUndergroundBeltVariants.tier2]: 1,
|
||||
};
|
||||
const colorsByRotationVariant: any = ["#6d9dff", "#71ff9c"];
|
||||
const overlayMatrices: any = [
|
||||
const colorsByRotationVariant = ["#6d9dff", "#71ff9c"];
|
||||
const overlayMatrices = [
|
||||
// Sender
|
||||
generateMatrixRotations([1, 1, 1, 0, 1, 0, 0, 1, 0]),
|
||||
// Receiver
|
||||
@ -33,7 +33,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("underground_belt");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 22,
|
||||
@ -57,16 +57,16 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(variant: any, rotationVariant: any): any {
|
||||
getSilhouetteColor(variant, rotationVariant) {
|
||||
return colorsByRotationVariant[rotationVariant];
|
||||
}
|
||||
getFlipOrientationAfterPlacement(): any {
|
||||
getFlipOrientationAfterPlacement() {
|
||||
return true;
|
||||
}
|
||||
getStayInPlacementMode(): any {
|
||||
getStayInPlacementMode() {
|
||||
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];
|
||||
}
|
||||
/**
|
||||
@ -76,8 +76,8 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
string,
|
||||
string
|
||||
]> {
|
||||
const rangeTiles: any = globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]];
|
||||
const beltSpeed: any = root.hubGoals.getUndergroundBeltBaseSpeed();
|
||||
const rangeTiles = globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]];
|
||||
const beltSpeed = root.hubGoals.getUndergroundBeltBaseSpeed();
|
||||
const stats: Array<[
|
||||
string,
|
||||
string
|
||||
@ -93,14 +93,14 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
stats.push([T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]);
|
||||
return stats;
|
||||
}
|
||||
getAvailableVariants(root: GameRoot): any {
|
||||
getAvailableVariants(root: GameRoot) {
|
||||
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) {
|
||||
return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2];
|
||||
}
|
||||
return super.getAvailableVariants(root);
|
||||
}
|
||||
getPreviewSprite(rotationVariant: number, variant: string): any {
|
||||
let suffix: any = "";
|
||||
getPreviewSprite(rotationVariant: number, variant: string) {
|
||||
let suffix = "";
|
||||
if (variant !== defaultBuildingVariant) {
|
||||
suffix = "-" + variant;
|
||||
}
|
||||
@ -113,8 +113,8 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
assertAlways(false, "Invalid rotation variant");
|
||||
}
|
||||
}
|
||||
getBlueprintSprite(rotationVariant: number, variant: string): any {
|
||||
let suffix: any = "";
|
||||
getBlueprintSprite(rotationVariant: number, variant: string) {
|
||||
let suffix = "";
|
||||
if (variant !== defaultBuildingVariant) {
|
||||
suffix = "-" + variant;
|
||||
}
|
||||
@ -127,16 +127,16 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
assertAlways(false, "Invalid rotation variant");
|
||||
}
|
||||
}
|
||||
getSprite(rotationVariant: number, variant: string): any {
|
||||
getSprite(rotationVariant: number, variant: string) {
|
||||
return this.getPreviewSprite(rotationVariant, variant);
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_tunnel);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
// Required, since the item processor needs this.
|
||||
entity.addComponent(new ItemEjectorComponent({
|
||||
slots: [],
|
||||
@ -161,18 +161,18 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
rotationVariant: number;
|
||||
connectedEntities?: Array<Entity>;
|
||||
} {
|
||||
const searchDirection: any = enumAngleToDirection[rotation];
|
||||
const searchVector: any = enumDirectionToVector[searchDirection];
|
||||
const tier: any = enumUndergroundBeltVariantToTier[variant];
|
||||
const targetRotation: any = (rotation + 180) % 360;
|
||||
const targetSenderRotation: any = rotation;
|
||||
for (let searchOffset: any = 1; searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier]; ++searchOffset) {
|
||||
const searchDirection = enumAngleToDirection[rotation];
|
||||
const searchVector = enumDirectionToVector[searchDirection];
|
||||
const tier = enumUndergroundBeltVariantToTier[variant];
|
||||
const targetRotation = (rotation + 180) % 360;
|
||||
const targetSenderRotation = rotation;
|
||||
for (let searchOffset = 1; searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier]; ++searchOffset) {
|
||||
tile = tile.addScalars(searchVector.x, searchVector.y);
|
||||
const contents: any = root.map.getTileContent(tile, "regular");
|
||||
const contents = root.map.getTileContent(tile, "regular");
|
||||
if (contents) {
|
||||
const undergroundComp: any = contents.components.UndergroundBelt;
|
||||
const undergroundComp = contents.components.UndergroundBelt;
|
||||
if (undergroundComp && undergroundComp.tier === tier) {
|
||||
const staticComp: any = contents.components.StaticMapEntity;
|
||||
const staticComp = contents.components.StaticMapEntity;
|
||||
if (staticComp.rotation === targetRotation) {
|
||||
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
|
||||
@ -205,7 +205,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
rotationVariant: 0,
|
||||
};
|
||||
}
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant: string): any {
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant: string) {
|
||||
entity.components.UndergroundBelt.tier = enumUndergroundBeltVariantToTier[variant];
|
||||
switch (arrayUndergroundRotationVariantToMode[rotationVariant]) {
|
||||
case enumUndergroundBeltMode.sender: {
|
||||
|
@ -10,21 +10,21 @@ import { MetaPainterBuilding } from "./painter";
|
||||
import { MetaRotaterBuilding } from "./rotater";
|
||||
import { MetaStackerBuilding } from "./stacker";
|
||||
/** @enum {string} */
|
||||
export const enumVirtualProcessorVariants: any = {
|
||||
export const enumVirtualProcessorVariants = {
|
||||
rotater: "rotater",
|
||||
unstacker: "unstacker",
|
||||
stacker: "stacker",
|
||||
painter: "painter",
|
||||
};
|
||||
/** @enum {string} */
|
||||
const enumVariantToGate: any = {
|
||||
const enumVariantToGate = {
|
||||
[defaultBuildingVariant]: enumLogicGateType.cutter,
|
||||
[enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater,
|
||||
[enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker,
|
||||
[enumVirtualProcessorVariants.stacker]: enumLogicGateType.stacker,
|
||||
[enumVirtualProcessorVariants.painter]: enumLogicGateType.painter,
|
||||
};
|
||||
const colors: any = {
|
||||
const colors = {
|
||||
[defaultBuildingVariant]: new MetaCutterBuilding().getSilhouetteColor(),
|
||||
[enumVirtualProcessorVariants.rotater]: new MetaRotaterBuilding().getSilhouetteColor(),
|
||||
[enumVirtualProcessorVariants.unstacker]: new MetaStackerBuilding().getSilhouetteColor(),
|
||||
@ -36,7 +36,7 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("virtual_processor");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 42,
|
||||
@ -60,20 +60,20 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(variant: any): any {
|
||||
getSilhouetteColor(variant) {
|
||||
return colors[variant];
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing);
|
||||
}
|
||||
/** {} **/
|
||||
getLayer(): "wires" {
|
||||
return "wires";
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getAvailableVariants(): any {
|
||||
getAvailableVariants() {
|
||||
return [
|
||||
defaultBuildingVariant,
|
||||
enumVirtualProcessorVariants.rotater,
|
||||
@ -82,14 +82,14 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
|
||||
enumVirtualProcessorVariants.unstacker,
|
||||
];
|
||||
}
|
||||
getRenderPins(): any {
|
||||
getRenderPins() {
|
||||
// We already have it included
|
||||
return false;
|
||||
}
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant: any): any {
|
||||
const gateType: any = enumVariantToGate[variant];
|
||||
updateVariants(entity: Entity, rotationVariant: number, variant) {
|
||||
const gateType = enumVariantToGate[variant];
|
||||
entity.components.LogicGate.type = gateType;
|
||||
const pinComp: any = entity.components.WiredPins;
|
||||
const pinComp = entity.components.WiredPins;
|
||||
switch (gateType) {
|
||||
case enumLogicGateType.cutter:
|
||||
case enumLogicGateType.unstacker: {
|
||||
@ -155,7 +155,7 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [],
|
||||
}));
|
||||
|
@ -7,23 +7,23 @@ import { Entity } from "../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
export const arrayWireRotationVariantToType: any = [
|
||||
export const arrayWireRotationVariantToType = [
|
||||
enumWireType.forward,
|
||||
enumWireType.turn,
|
||||
enumWireType.split,
|
||||
enumWireType.cross,
|
||||
];
|
||||
export const wireOverlayMatrices: any = {
|
||||
export const wireOverlayMatrices = {
|
||||
[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.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
|
||||
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
|
||||
};
|
||||
/** @enum {string} */
|
||||
export const wireVariants: any = {
|
||||
export const wireVariants = {
|
||||
second: "second",
|
||||
};
|
||||
const enumWireVariantToVariant: any = {
|
||||
const enumWireVariantToVariant = {
|
||||
[defaultBuildingVariant]: enumWireVariant.first,
|
||||
[wireVariants.second]: enumWireVariant.second,
|
||||
};
|
||||
@ -32,7 +32,7 @@ export class MetaWireBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("wire");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 27,
|
||||
@ -76,51 +76,51 @@ export class MetaWireBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getHasDirectionLockAvailable(): any {
|
||||
getHasDirectionLockAvailable() {
|
||||
return true;
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#61ef6f";
|
||||
}
|
||||
getAvailableVariants(): any {
|
||||
getAvailableVariants() {
|
||||
return [defaultBuildingVariant, wireVariants.second];
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
getStayInPlacementMode(): any {
|
||||
getStayInPlacementMode() {
|
||||
return true;
|
||||
}
|
||||
getPlacementSound(): any {
|
||||
getPlacementSound() {
|
||||
return SOUNDS.placeBelt;
|
||||
}
|
||||
getRotateAutomaticallyWhilePlacing(): any {
|
||||
getRotateAutomaticallyWhilePlacing() {
|
||||
return true;
|
||||
}
|
||||
/** {} **/
|
||||
getLayer(): "wires" {
|
||||
return "wires";
|
||||
}
|
||||
getSprite(): any {
|
||||
getSprite() {
|
||||
return null;
|
||||
}
|
||||
getIsReplaceable(): any {
|
||||
getIsReplaceable() {
|
||||
return true;
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers);
|
||||
}
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
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.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];
|
||||
}
|
||||
/**
|
||||
@ -128,7 +128,7 @@ export class MetaWireBuilding extends MetaBuilding {
|
||||
* {}
|
||||
*/
|
||||
getPreviewSprite(rotationVariant: number, variant: string): import("../../core/draw_utils").AtlasSprite {
|
||||
const wireVariant: any = enumWireVariantToVariant[variant];
|
||||
const wireVariant = enumWireVariantToVariant[variant];
|
||||
switch (arrayWireRotationVariantToType[rotationVariant]) {
|
||||
case enumWireType.forward: {
|
||||
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);
|
||||
}
|
||||
/**
|
||||
@ -165,19 +165,19 @@ export class MetaWireBuilding extends MetaBuilding {
|
||||
rotationVariant: number;
|
||||
connectedEntities?: Array<Entity>;
|
||||
} {
|
||||
const wireVariant: any = enumWireVariantToVariant[variant];
|
||||
const connections: any = {
|
||||
const wireVariant = enumWireVariantToVariant[variant];
|
||||
const connections = {
|
||||
top: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.top }),
|
||||
right: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.right }),
|
||||
bottom: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.bottom }),
|
||||
left: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.left }),
|
||||
};
|
||||
let flag: any = 0;
|
||||
let flag = 0;
|
||||
flag |= connections.top ? 0x1000 : 0;
|
||||
flag |= connections.right ? 0x100 : 0;
|
||||
flag |= connections.bottom ? 0x10 : 0;
|
||||
flag |= connections.left ? 0x1 : 0;
|
||||
let targetType: any = enumWireType.forward;
|
||||
let targetType = enumWireType.forward;
|
||||
// First, reset rotation
|
||||
rotation = 0;
|
||||
switch (flag) {
|
||||
|
@ -5,13 +5,13 @@ import { Entity } from "../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
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 {
|
||||
|
||||
constructor() {
|
||||
super("wire_tunnel");
|
||||
}
|
||||
static getAllVariantCombinations(): any {
|
||||
static getAllVariantCombinations() {
|
||||
return [
|
||||
{
|
||||
internalId: 39,
|
||||
@ -19,19 +19,19 @@ export class MetaWireTunnelBuilding extends MetaBuilding {
|
||||
},
|
||||
];
|
||||
}
|
||||
getSilhouetteColor(): any {
|
||||
getSilhouetteColor() {
|
||||
return "#777a86";
|
||||
}
|
||||
getIsUnlocked(root: GameRoot): any {
|
||||
getIsUnlocked(root: GameRoot) {
|
||||
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];
|
||||
}
|
||||
getIsRotateable(): any {
|
||||
getIsRotateable() {
|
||||
return false;
|
||||
}
|
||||
getDimensions(): any {
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
/** {} **/
|
||||
@ -41,7 +41,7 @@ export class MetaWireTunnelBuilding extends MetaBuilding {
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
*/
|
||||
setupEntityComponents(entity: Entity): any {
|
||||
setupEntityComponents(entity: Entity) {
|
||||
entity.addComponent(new WireTunnelComponent());
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,19 @@ import { mixVector, Vector } from "../core/vector";
|
||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||
import { KEYMAPPINGS } from "./key_action_mapper";
|
||||
import { GameRoot } from "./root";
|
||||
const logger: any = createLogger("camera");
|
||||
export const USER_INTERACT_MOVE: any = "move";
|
||||
export const USER_INTERACT_ZOOM: any = "zoom";
|
||||
export const USER_INTERACT_TOUCHEND: any = "touchend";
|
||||
const velocitySmoothing: any = 0.5;
|
||||
const velocityFade: any = 0.98;
|
||||
const velocityStrength: any = 0.4;
|
||||
const velocityMax: any = 20;
|
||||
const ticksBeforeErasingVelocity: any = 10;
|
||||
const logger = createLogger("camera");
|
||||
export const USER_INTERACT_MOVE = "move";
|
||||
export const USER_INTERACT_ZOOM = "zoom";
|
||||
export const USER_INTERACT_TOUCHEND = "touchend";
|
||||
const velocitySmoothing = 0.5;
|
||||
const velocityFade = 0.98;
|
||||
const velocityStrength = 0.4;
|
||||
const velocityMax = 20;
|
||||
const ticksBeforeErasingVelocity = 10;
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export const enumMouseButton: any = {
|
||||
export const enumMouseButton = {
|
||||
left: "left",
|
||||
middle: "middle",
|
||||
right: "right",
|
||||
@ -63,7 +63,7 @@ export class Camera extends BasicSerializableObject {
|
||||
this.clampZoomLevel();
|
||||
this.bindKeys();
|
||||
if (G_IS_DEV) {
|
||||
window.addEventListener("keydown", (ev: any): any => {
|
||||
window.addEventListener("keydown", ev => {
|
||||
if (ev.key === "i") {
|
||||
this.zoomLevel = 3;
|
||||
}
|
||||
@ -71,17 +71,17 @@ export class Camera extends BasicSerializableObject {
|
||||
}
|
||||
}
|
||||
// Serialization
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Camera";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
zoomLevel: types.float,
|
||||
center: types.vector,
|
||||
};
|
||||
}
|
||||
deserialize(data: any): any {
|
||||
const errorCode: any = super.deserialize(data);
|
||||
deserialize(data) {
|
||||
const errorCode = super.deserialize(data);
|
||||
if (errorCode) {
|
||||
return errorCode;
|
||||
}
|
||||
@ -89,55 +89,55 @@ export class Camera extends BasicSerializableObject {
|
||||
this.clampZoomLevel();
|
||||
}
|
||||
// Simple getters & setters
|
||||
addScreenShake(amount: any): any {
|
||||
const currentShakeAmount: any = this.currentShake.length();
|
||||
const scale: any = 1 / (1 + 3 * currentShakeAmount);
|
||||
addScreenShake(amount) {
|
||||
const currentShakeAmount = this.currentShake.length();
|
||||
const scale = 1 / (1 + 3 * currentShakeAmount);
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* Sets a point in world space to focus on
|
||||
*/
|
||||
setDesiredCenter(center: Vector): any {
|
||||
setDesiredCenter(center: Vector) {
|
||||
this.desiredCenter = center.copy();
|
||||
this.currentlyMoving = false;
|
||||
}
|
||||
/**
|
||||
* Sets a desired zoom level
|
||||
*/
|
||||
setDesiredZoom(zoom: number): any {
|
||||
setDesiredZoom(zoom: number) {
|
||||
this.desiredZoom = zoom;
|
||||
}
|
||||
/**
|
||||
* Returns if this camera is currently moving by a non-user interaction
|
||||
*/
|
||||
isCurrentlyMovingToDesiredCenter(): any {
|
||||
isCurrentlyMovingToDesiredCenter() {
|
||||
return this.desiredCenter !== null;
|
||||
}
|
||||
/**
|
||||
* Sets the camera pan, every frame the camera will move by this amount
|
||||
*/
|
||||
setPan(pan: Vector): any {
|
||||
setPan(pan: Vector) {
|
||||
this.desiredPan = pan.copy();
|
||||
}
|
||||
/**
|
||||
* Finds a good initial zoom level
|
||||
*/
|
||||
findInitialZoom(): any {
|
||||
let desiredWorldSpaceWidth: any = 18 * globalConfig.tileSize;
|
||||
findInitialZoom() {
|
||||
let desiredWorldSpaceWidth = 18 * globalConfig.tileSize;
|
||||
if (window.innerWidth < 1000) {
|
||||
desiredWorldSpaceWidth = 12 * globalConfig.tileSize;
|
||||
}
|
||||
const zoomLevelX: any = this.root.gameWidth / desiredWorldSpaceWidth;
|
||||
const zoomLevelY: any = this.root.gameHeight / desiredWorldSpaceWidth;
|
||||
const finalLevel: any = Math.min(zoomLevelX, zoomLevelY);
|
||||
const zoomLevelX = this.root.gameWidth / desiredWorldSpaceWidth;
|
||||
const zoomLevelY = this.root.gameHeight / desiredWorldSpaceWidth;
|
||||
const finalLevel = Math.min(zoomLevelX, zoomLevelY);
|
||||
assert(Number.isFinite(finalLevel) && finalLevel > 0, "Invalid zoom level computed for initial zoom: " + finalLevel);
|
||||
return finalLevel;
|
||||
}
|
||||
/**
|
||||
* Clears all animations
|
||||
*/
|
||||
clearAnimations(): any {
|
||||
clearAnimations() {
|
||||
this.touchPostMoveVelocity.x = 0;
|
||||
this.touchPostMoveVelocity.y = 0;
|
||||
this.desiredCenter = null;
|
||||
@ -178,7 +178,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Cancels all interactions, that is user interaction and non user interaction
|
||||
*/
|
||||
cancelAllInteractions(): any {
|
||||
cancelAllInteractions() {
|
||||
this.touchPostMoveVelocity = new Vector(0, 0);
|
||||
this.desiredCenter = null;
|
||||
this.currentlyMoving = false;
|
||||
@ -188,37 +188,37 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Returns effective viewport width
|
||||
*/
|
||||
getViewportWidth(): any {
|
||||
getViewportWidth() {
|
||||
return this.root.gameWidth / this.zoomLevel;
|
||||
}
|
||||
/**
|
||||
* Returns effective viewport height
|
||||
*/
|
||||
getViewportHeight(): any {
|
||||
getViewportHeight() {
|
||||
return this.root.gameHeight / this.zoomLevel;
|
||||
}
|
||||
/**
|
||||
* Returns effective world space viewport left
|
||||
*/
|
||||
getViewportLeft(): any {
|
||||
getViewportLeft() {
|
||||
return this.center.x - this.getViewportWidth() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
|
||||
}
|
||||
/**
|
||||
* Returns effective world space viewport right
|
||||
*/
|
||||
getViewportRight(): any {
|
||||
getViewportRight() {
|
||||
return this.center.x + this.getViewportWidth() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
|
||||
}
|
||||
/**
|
||||
* Returns effective world space viewport top
|
||||
*/
|
||||
getViewportTop(): any {
|
||||
getViewportTop() {
|
||||
return this.center.y - this.getViewportHeight() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
|
||||
}
|
||||
/**
|
||||
* Returns effective world space viewport bottom
|
||||
*/
|
||||
getViewportBottom(): any {
|
||||
getViewportBottom() {
|
||||
return this.center.y + this.getViewportHeight() / 2 + (this.currentShake.x * 10) / this.zoomLevel;
|
||||
}
|
||||
/**
|
||||
@ -228,13 +228,13 @@ export class Camera extends BasicSerializableObject {
|
||||
getVisibleRect(): Rectangle {
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* Attaches all event listeners
|
||||
*/
|
||||
internalInitEvents(): any {
|
||||
internalInitEvents() {
|
||||
this.eventListenerTouchStart = this.onTouchStart.bind(this);
|
||||
this.eventListenerTouchEnd = this.onTouchEnd.bind(this);
|
||||
this.eventListenerTouchMove = this.onTouchMove.bind(this);
|
||||
@ -257,7 +257,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Cleans up all event listeners
|
||||
*/
|
||||
cleanup(): any {
|
||||
cleanup() {
|
||||
if (SUPPORT_TOUCH) {
|
||||
this.root.canvas.removeEventListener("touchstart", this.eventListenerTouchStart);
|
||||
this.root.canvas.removeEventListener("touchend", this.eventListenerTouchEnd);
|
||||
@ -273,21 +273,21 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Binds the arrow keys
|
||||
*/
|
||||
bindKeys(): any {
|
||||
const mapper: any = this.root.keyMapper;
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).add((): any => (this.keyboardForce.y = -1));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveDown).add((): any => (this.keyboardForce.y = 1));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).add((): any => (this.keyboardForce.x = 1));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveLeft).add((): any => (this.keyboardForce.x = -1));
|
||||
bindKeys() {
|
||||
const mapper = this.root.keyMapper;
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).add(() => (this.keyboardForce.y = -1));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveDown).add(() => (this.keyboardForce.y = 1));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).add(() => (this.keyboardForce.x = 1));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.mapMoveLeft).add(() => (this.keyboardForce.x = -1));
|
||||
mapper
|
||||
.getBinding(KEYMAPPINGS.navigation.mapZoomIn)
|
||||
.add((): any => (this.desiredZoom = this.zoomLevel * 1.2));
|
||||
.add(() => (this.desiredZoom = this.zoomLevel * 1.2));
|
||||
mapper
|
||||
.getBinding(KEYMAPPINGS.navigation.mapZoomOut)
|
||||
.add((): any => (this.desiredZoom = this.zoomLevel / 1.2));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.centerMap).add((): any => this.centerOnMap());
|
||||
.add(() => (this.desiredZoom = this.zoomLevel / 1.2));
|
||||
mapper.getBinding(KEYMAPPINGS.navigation.centerMap).add(() => this.centerOnMap());
|
||||
}
|
||||
centerOnMap(): any {
|
||||
centerOnMap() {
|
||||
this.desiredCenter = new Vector(0, 0);
|
||||
}
|
||||
/**
|
||||
@ -295,7 +295,7 @@ export class Camera extends BasicSerializableObject {
|
||||
* {} world space
|
||||
*/
|
||||
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);
|
||||
}
|
||||
/**
|
||||
@ -303,7 +303,7 @@ export class Camera extends BasicSerializableObject {
|
||||
* {} screen space
|
||||
*/
|
||||
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);
|
||||
}
|
||||
/**
|
||||
@ -311,13 +311,13 @@ export class Camera extends BasicSerializableObject {
|
||||
* {} true if its on screen
|
||||
*/
|
||||
isWorldPointOnScreen(point: Vector): boolean {
|
||||
const rect: any = this.getVisibleRect();
|
||||
const rect = this.getVisibleRect();
|
||||
return rect.containsPoint(point.x, point.y);
|
||||
}
|
||||
getMaximumZoom(): any {
|
||||
getMaximumZoom() {
|
||||
return this.root.gameMode.getMaximumZoom();
|
||||
}
|
||||
getMinimumZoom(): any {
|
||||
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
|
||||
* should get ignored
|
||||
*/
|
||||
checkPreventDoubleMouse(): any {
|
||||
checkPreventDoubleMouse() {
|
||||
if (performance.now() - clickDetectorGlobals.lastTouchTime < 1000.0) {
|
||||
return false;
|
||||
}
|
||||
@ -348,7 +348,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Mousedown handler
|
||||
*/
|
||||
onMouseDown(event: MouseEvent): any {
|
||||
onMouseDown(event: MouseEvent) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
@ -371,7 +371,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Mousemove handler
|
||||
*/
|
||||
onMouseMove(event: MouseEvent): any {
|
||||
onMouseMove(event: MouseEvent) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
@ -390,7 +390,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Mouseup handler
|
||||
*/
|
||||
onMouseUp(event: MouseEvent=): any {
|
||||
onMouseUp(event: MouseEvent=) {
|
||||
if (event) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
@ -406,27 +406,27 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Mousewheel event
|
||||
*/
|
||||
onMouseWheel(event: WheelEvent): any {
|
||||
onMouseWheel(event: WheelEvent) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
}
|
||||
const prevZoom: any = this.zoomLevel;
|
||||
const scale: any = 1 + 0.15 * this.root.app.settings.getScrollWheelSensitivity();
|
||||
const prevZoom = this.zoomLevel;
|
||||
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(this.zoomLevel), "Got invalid zoom level *before* wheel: " + this.zoomLevel);
|
||||
this.zoomLevel *= event.deltaY < 0 ? scale : 1 / scale;
|
||||
assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *after* wheel: " + this.zoomLevel);
|
||||
this.clampZoomLevel();
|
||||
this.desiredZoom = null;
|
||||
let mousePosition: any = this.root.app.mousePosition;
|
||||
let mousePosition = this.root.app.mousePosition;
|
||||
if (!this.root.app.settings.getAllSettings().zoomToCursor) {
|
||||
mousePosition = new Vector(this.root.gameWidth / 2, this.root.gameHeight / 2);
|
||||
}
|
||||
if (mousePosition) {
|
||||
const worldPos: any = this.root.camera.screenToWorld(mousePosition);
|
||||
const worldDelta: any = worldPos.sub(this.center);
|
||||
const actualDelta: any = this.zoomLevel / prevZoom - 1;
|
||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||
const worldDelta = worldPos.sub(this.center);
|
||||
const actualDelta = this.zoomLevel / prevZoom - 1;
|
||||
this.center = this.center.add(worldDelta.multiplyScalar(actualDelta));
|
||||
this.desiredCenter = null;
|
||||
}
|
||||
@ -435,7 +435,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Touch start handler
|
||||
*/
|
||||
onTouchStart(event: TouchEvent): any {
|
||||
onTouchStart(event: TouchEvent) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
@ -443,7 +443,7 @@ export class Camera extends BasicSerializableObject {
|
||||
clickDetectorGlobals.lastTouchTime = performance.now();
|
||||
this.touchPostMoveVelocity = new Vector(0, 0);
|
||||
if (event.touches.length === 1) {
|
||||
const touch: any = event.touches[0];
|
||||
const touch = event.touches[0];
|
||||
this.combinedSingleTouchStartHandler(touch.clientX, touch.clientY);
|
||||
}
|
||||
else if (event.touches.length === 2) {
|
||||
@ -451,8 +451,8 @@ export class Camera extends BasicSerializableObject {
|
||||
// // Something prevented pinching
|
||||
// return false;
|
||||
// }
|
||||
const touch1: any = event.touches[0];
|
||||
const touch2: any = event.touches[1];
|
||||
const touch1 = event.touches[0];
|
||||
const touch2 = event.touches[1];
|
||||
this.currentlyMoving = false;
|
||||
this.currentlyPinching = true;
|
||||
this.lastPinchPositions = [
|
||||
@ -465,35 +465,35 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Touch move handler
|
||||
*/
|
||||
onTouchMove(event: TouchEvent): any {
|
||||
onTouchMove(event: TouchEvent) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
}
|
||||
clickDetectorGlobals.lastTouchTime = performance.now();
|
||||
if (event.touches.length === 1) {
|
||||
const touch: any = event.touches[0];
|
||||
const touch = event.touches[0];
|
||||
this.combinedSingleTouchMoveHandler(touch.clientX, touch.clientY);
|
||||
}
|
||||
else if (event.touches.length === 2) {
|
||||
if (this.currentlyPinching) {
|
||||
const touch1: any = event.touches[0];
|
||||
const touch2: any = event.touches[1];
|
||||
const newPinchPositions: any = [
|
||||
const touch1 = event.touches[0];
|
||||
const touch2 = event.touches[1];
|
||||
const newPinchPositions = [
|
||||
new Vector(touch1.clientX, touch1.clientY),
|
||||
new Vector(touch2.clientX, touch2.clientY),
|
||||
];
|
||||
// Get distance of taps last time and now
|
||||
const lastDistance: any = this.lastPinchPositions[0].distance(this.lastPinchPositions[1]);
|
||||
const thisDistance: any = newPinchPositions[0].distance(newPinchPositions[1]);
|
||||
const lastDistance = this.lastPinchPositions[0].distance(this.lastPinchPositions[1]);
|
||||
const thisDistance = newPinchPositions[0].distance(newPinchPositions[1]);
|
||||
// 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
|
||||
let oldCenter: any = this.lastPinchPositions[0].centerPoint(this.lastPinchPositions[1]);
|
||||
let oldCenter = this.lastPinchPositions[0].centerPoint(this.lastPinchPositions[1]);
|
||||
// Find new center of zoom
|
||||
let center: any = newPinchPositions[0].centerPoint(newPinchPositions[1]);
|
||||
let center = newPinchPositions[0].centerPoint(newPinchPositions[1]);
|
||||
// Compute movement
|
||||
let movement: any = oldCenter.sub(center);
|
||||
let movement = oldCenter.sub(center);
|
||||
this.center.x += movement.x / this.zoomLevel;
|
||||
this.center.y += movement.y / this.zoomLevel;
|
||||
// Compute zoom
|
||||
@ -508,7 +508,7 @@ export class Camera extends BasicSerializableObject {
|
||||
")");
|
||||
this.zoomLevel *= difference;
|
||||
// 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.lastPinchPositions = newPinchPositions;
|
||||
this.userInteraction.dispatch(USER_INTERACT_MOVE);
|
||||
@ -525,7 +525,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Touch end and cancel handler
|
||||
*/
|
||||
onTouchEnd(event: TouchEvent=): any {
|
||||
onTouchEnd(event: TouchEvent=) {
|
||||
if (event) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
@ -536,15 +536,15 @@ export class Camera extends BasicSerializableObject {
|
||||
if (event.changedTouches.length === 0) {
|
||||
logger.warn("Touch end without changed touches");
|
||||
}
|
||||
const touch: any = event.changedTouches[0];
|
||||
const touch = event.changedTouches[0];
|
||||
this.combinedSingleTouchStopHandler(touch.clientX, touch.clientY);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Internal touch start handler
|
||||
*/
|
||||
combinedSingleTouchStartHandler(x: number, y: number): any {
|
||||
const pos: any = new Vector(x, y);
|
||||
combinedSingleTouchStartHandler(x: number, y: number) {
|
||||
const pos = new Vector(x, y);
|
||||
if (this.downPreHandler.dispatch(pos, enumMouseButton.left) === STOP_PROPAGATION) {
|
||||
// Somebody else captured it
|
||||
return;
|
||||
@ -559,8 +559,8 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Internal touch move handler
|
||||
*/
|
||||
combinedSingleTouchMoveHandler(x: number, y: number): any {
|
||||
const pos: any = new Vector(x, y);
|
||||
combinedSingleTouchMoveHandler(x: number, y: number) {
|
||||
const pos = new Vector(x, y);
|
||||
if (this.movePreHandler.dispatch(pos) === STOP_PROPAGATION) {
|
||||
// Somebody else captured it
|
||||
return;
|
||||
@ -568,7 +568,7 @@ export class Camera extends BasicSerializableObject {
|
||||
if (!this.currentlyMoving) {
|
||||
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) {
|
||||
// When testing culling, we see everything from the same distance
|
||||
delta = delta.multiplyScalar(this.zoomLevel * -2);
|
||||
@ -588,7 +588,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Internal touch stop handler
|
||||
*/
|
||||
combinedSingleTouchStopHandler(x: any, y: any): any {
|
||||
combinedSingleTouchStopHandler(x, y) {
|
||||
if (this.currentlyMoving || this.currentlyPinching) {
|
||||
this.currentlyMoving = false;
|
||||
this.currentlyPinching = false;
|
||||
@ -604,7 +604,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Clamps the camera zoom level within the allowed range
|
||||
*/
|
||||
clampZoomLevel(): any {
|
||||
clampZoomLevel() {
|
||||
if (G_IS_DEV && globalConfig.debug.disableZoomLimits) {
|
||||
return;
|
||||
}
|
||||
@ -618,25 +618,25 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Clamps the center within set boundaries
|
||||
*/
|
||||
clampToBounds(): any {
|
||||
const bounds: any = this.root.gameMode.getCameraBounds();
|
||||
clampToBounds() {
|
||||
const bounds = this.root.gameMode.getCameraBounds();
|
||||
if (!bounds) {
|
||||
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.y = clamp(this.center.y, tileScaleBounds.y, tileScaleBounds.y + tileScaleBounds.h);
|
||||
}
|
||||
/**
|
||||
* Updates the camera
|
||||
*/
|
||||
update(dt: number): any {
|
||||
update(dt: number) {
|
||||
dt = Math.min(dt, 33);
|
||||
this.cameraUpdateTimeBucket += dt;
|
||||
// Simulate movement of N FPS
|
||||
const updatesPerFrame: any = 4;
|
||||
const physicsStepSizeMs: any = 1000.0 / (60.0 * updatesPerFrame);
|
||||
let now: any = this.root.time.systemNow() - 3 * physicsStepSizeMs;
|
||||
const updatesPerFrame = 4;
|
||||
const physicsStepSizeMs = 1000.0 / (60.0 * updatesPerFrame);
|
||||
let now = this.root.time.systemNow() - 3 * physicsStepSizeMs;
|
||||
while (this.cameraUpdateTimeBucket > physicsStepSizeMs) {
|
||||
now += physicsStepSizeMs;
|
||||
this.cameraUpdateTimeBucket -= physicsStepSizeMs;
|
||||
@ -652,13 +652,13 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Prepares a context to transform it
|
||||
*/
|
||||
transform(context: CanvasRenderingContext2D): any {
|
||||
transform(context: CanvasRenderingContext2D) {
|
||||
if (G_IS_DEV && globalConfig.debug.testCulling) {
|
||||
context.transform(1, 0, 0, 1, 100, 100);
|
||||
return;
|
||||
}
|
||||
this.clampZoomLevel();
|
||||
const zoom: any = this.zoomLevel;
|
||||
const zoom = this.zoomLevel;
|
||||
context.transform(
|
||||
// Scale, skew, rotate
|
||||
zoom, 0, 0, zoom,
|
||||
@ -668,14 +668,14 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Internal shake handler
|
||||
*/
|
||||
internalUpdateShake(now: number, dt: number): any {
|
||||
internalUpdateShake(now: number, dt: number) {
|
||||
this.currentShake = this.currentShake.multiplyScalar(0.92);
|
||||
}
|
||||
/**
|
||||
* Internal pan handler
|
||||
*/
|
||||
internalUpdatePanning(now: number, dt: number): any {
|
||||
const baseStrength: any = velocityStrength * this.root.app.platformWrapper.getTouchPanStrength();
|
||||
internalUpdatePanning(now: number, dt: number) {
|
||||
const baseStrength = velocityStrength * this.root.app.platformWrapper.getTouchPanStrength();
|
||||
this.touchPostMoveVelocity = this.touchPostMoveVelocity.multiplyScalar(velocityFade);
|
||||
// Check if the camera is being dragged but standing still: if not, zero out `touchPostMoveVelocity`.
|
||||
if (this.currentlyMoving && this.desiredCenter === null) {
|
||||
@ -694,7 +694,7 @@ export class Camera extends BasicSerializableObject {
|
||||
}
|
||||
// Check influence of past points
|
||||
if (!this.currentlyMoving && !this.currentlyPinching) {
|
||||
const len: any = this.touchPostMoveVelocity.length();
|
||||
const len = this.touchPostMoveVelocity.length();
|
||||
if (len >= velocityMax) {
|
||||
this.touchPostMoveVelocity.x = (this.touchPostMoveVelocity.x * velocityMax) / len;
|
||||
this.touchPostMoveVelocity.y = (this.touchPostMoveVelocity.y * velocityMax) / len;
|
||||
@ -709,7 +709,7 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Internal screen panning handler
|
||||
*/
|
||||
internalUpdateMousePanning(now: number, dt: number): any {
|
||||
internalUpdateMousePanning(now: number, dt: number) {
|
||||
if (!this.root.app.focused) {
|
||||
return;
|
||||
}
|
||||
@ -717,7 +717,7 @@ export class Camera extends BasicSerializableObject {
|
||||
// Not enabled
|
||||
return;
|
||||
}
|
||||
const mousePos: any = this.root.app.mousePosition;
|
||||
const mousePos = this.root.app.mousePosition;
|
||||
if (!mousePos) {
|
||||
return;
|
||||
}
|
||||
@ -735,8 +735,8 @@ export class Camera extends BasicSerializableObject {
|
||||
// Out of screen
|
||||
return;
|
||||
}
|
||||
const panAreaPixels: any = 2;
|
||||
const panVelocity: any = new Vector();
|
||||
const panAreaPixels = 2;
|
||||
const panVelocity = new Vector();
|
||||
if (mousePos.x < panAreaPixels) {
|
||||
panVelocity.x -= 1;
|
||||
}
|
||||
@ -755,11 +755,11 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Updates the non user interaction zooming
|
||||
*/
|
||||
internalUpdateZooming(now: number, dt: number): any {
|
||||
internalUpdateZooming(now: number, dt: number) {
|
||||
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) {
|
||||
let fade: any = 0.94;
|
||||
let fade = 0.94;
|
||||
if (diff > 0) {
|
||||
// Zoom out faster than in
|
||||
fade = 0.9;
|
||||
@ -778,13 +778,13 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Updates the non user interaction centering
|
||||
*/
|
||||
internalUpdateCentering(now: number, dt: number): any {
|
||||
internalUpdateCentering(now: number, dt: number) {
|
||||
if (!this.currentlyMoving && this.desiredCenter !== null) {
|
||||
const diff: any = this.center.direction(this.desiredCenter);
|
||||
const length: any = diff.length();
|
||||
const tolerance: any = 1 / this.zoomLevel;
|
||||
const diff = this.center.direction(this.desiredCenter);
|
||||
const length = diff.length();
|
||||
const tolerance = 1 / this.zoomLevel;
|
||||
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.y += movement.y;
|
||||
}
|
||||
@ -796,13 +796,13 @@ export class Camera extends BasicSerializableObject {
|
||||
/**
|
||||
* Updates the keyboard forces
|
||||
*/
|
||||
internalUpdateKeyboardForce(now: number, dt: number): any {
|
||||
internalUpdateKeyboardForce(now: number, dt: number) {
|
||||
if (!this.currentlyMoving && this.desiredCenter == null) {
|
||||
const limitingDimension: any = Math.min(this.root.gameWidth, this.root.gameHeight);
|
||||
const moveAmount: any = ((limitingDimension / 2048) * dt) / this.zoomLevel;
|
||||
let forceX: any = 0;
|
||||
let forceY: any = 0;
|
||||
const actionMapper: any = this.root.keyMapper;
|
||||
const limitingDimension = Math.min(this.root.gameWidth, this.root.gameHeight);
|
||||
const moveAmount = ((limitingDimension / 2048) * dt) / this.zoomLevel;
|
||||
let forceX = 0;
|
||||
let forceY = 0;
|
||||
const actionMapper = this.root.keyMapper;
|
||||
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).pressed) {
|
||||
forceY -= 1;
|
||||
}
|
||||
@ -815,7 +815,7 @@ export class Camera extends BasicSerializableObject {
|
||||
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).pressed) {
|
||||
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);
|
||||
this.center.x += moveAmount * forceX * movementSpeed;
|
||||
this.center.y += moveAmount * forceY * movementSpeed;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/** @enum {string} */
|
||||
export const enumColors: any = {
|
||||
export const enumColors = {
|
||||
red: "red",
|
||||
green: "green",
|
||||
blue: "blue",
|
||||
@ -9,9 +9,9 @@ export const enumColors: any = {
|
||||
white: "white",
|
||||
uncolored: "uncolored",
|
||||
};
|
||||
const c: any = enumColors;
|
||||
const c = enumColors;
|
||||
/** @enum {string} */
|
||||
export const enumColorToShortcode: any = {
|
||||
export const enumColorToShortcode = {
|
||||
[c.red]: "r",
|
||||
[c.green]: "g",
|
||||
[c.blue]: "b",
|
||||
@ -22,12 +22,12 @@ export const enumColorToShortcode: any = {
|
||||
[c.uncolored]: "u",
|
||||
};
|
||||
/** @enum {enumColors} */
|
||||
export const enumShortcodeToColor: any = {};
|
||||
for (const key: any in enumColorToShortcode) {
|
||||
export const enumShortcodeToColor = {};
|
||||
for (const key in enumColorToShortcode) {
|
||||
enumShortcodeToColor[enumColorToShortcode[key]] = key;
|
||||
}
|
||||
/** @enum {string} */
|
||||
export const enumColorsToHexCode: any = {
|
||||
export const enumColorsToHexCode = {
|
||||
[c.red]: "#ff666a",
|
||||
[c.green]: "#78ff66",
|
||||
[c.blue]: "#66a7ff",
|
||||
@ -42,8 +42,8 @@ export const enumColorsToHexCode: any = {
|
||||
[c.uncolored]: "#aaaaaa",
|
||||
};
|
||||
/** @enum {Object.<string, string>} */
|
||||
export const enumColorMixingResults: any = {};
|
||||
const bitfieldToColor: any = [
|
||||
export const enumColorMixingResults = {};
|
||||
const bitfieldToColor = [
|
||||
/* 000 */ c.uncolored,
|
||||
/* 001 */ c.red,
|
||||
/* 010 */ c.green,
|
||||
@ -53,9 +53,9 @@ const bitfieldToColor: any = [
|
||||
/* 110 */ c.cyan,
|
||||
/* 111 */ c.white,
|
||||
];
|
||||
for (let i: any = 0; i < 1 << 3; ++i) {
|
||||
for (let i = 0; i < 1 << 3; ++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];
|
||||
}
|
||||
}
|
||||
|
@ -12,17 +12,17 @@ export class Component extends BasicSerializableObject {
|
||||
/**
|
||||
* Should return the schema used for serialization
|
||||
*/
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {};
|
||||
}
|
||||
/**
|
||||
* Copy the current state to another component
|
||||
*/
|
||||
copyAdditionalStateTo(otherComponent: Component): any { }
|
||||
copyAdditionalStateTo(otherComponent: Component) { }
|
||||
/**
|
||||
* Clears all items and state
|
||||
*/
|
||||
clear(): any { }
|
||||
clear() { }
|
||||
/* dev:start */
|
||||
/**
|
||||
* Fixes typeof DerivedComponent is not assignable to typeof Component, compiled out
|
||||
|
@ -20,8 +20,8 @@ import { BeltReaderComponent } from "./components/belt_reader";
|
||||
import { FilterComponent } from "./components/filter";
|
||||
import { ItemProducerComponent } from "./components/item_producer";
|
||||
import { GoalAcceptorComponent } from "./components/goal_acceptor";
|
||||
export function initComponentRegistry(): any {
|
||||
const components: any = [
|
||||
export function initComponentRegistry() {
|
||||
const components = [
|
||||
StaticMapEntityComponent,
|
||||
BeltComponent,
|
||||
ItemEjectorComponent,
|
||||
@ -44,7 +44,7 @@ export function initComponentRegistry(): any {
|
||||
ItemProducerComponent,
|
||||
GoalAcceptorComponent,
|
||||
];
|
||||
components.forEach((component: any): any => gComponentRegistry.register(component));
|
||||
components.forEach(component => gComponentRegistry.register(component));
|
||||
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS
|
||||
// Sanity check - If this is thrown, you forgot to add a new component here
|
||||
assert(
|
||||
|
@ -2,7 +2,7 @@ import { enumDirection, Vector } from "../../core/vector";
|
||||
import { types } from "../../savegame/serialization";
|
||||
import { BeltPath } from "../belt_path";
|
||||
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 = {
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.bottom,
|
||||
@ -30,7 +30,7 @@ export const FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION: {
|
||||
},
|
||||
};
|
||||
export class BeltComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Belt";
|
||||
}
|
||||
public direction = direction;
|
||||
@ -39,7 +39,7 @@ export class BeltComponent extends Component {
|
||||
constructor({ direction = enumDirection.top }) {
|
||||
super();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
if (this.assignedPath) {
|
||||
this.assignedPath.clearAllItems();
|
||||
}
|
||||
@ -79,12 +79,12 @@ export class BeltComponent extends Component {
|
||||
return new Vector(0, 0.5 - progress);
|
||||
case enumDirection.right: {
|
||||
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));
|
||||
}
|
||||
case enumDirection.left: {
|
||||
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));
|
||||
}
|
||||
default:
|
||||
|
@ -3,15 +3,15 @@ import { BaseItem } from "../base_item";
|
||||
import { typeItemSingleton } from "../item_resolver";
|
||||
import { types } from "../../savegame/serialization";
|
||||
/** @enum {string} */
|
||||
export const enumBeltReaderType: any = {
|
||||
export const enumBeltReaderType = {
|
||||
wired: "wired",
|
||||
wireless: "wireless",
|
||||
};
|
||||
export class BeltReaderComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "BeltReader";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
lastItem: types.nullable(typeItemSingleton),
|
||||
};
|
||||
@ -21,7 +21,7 @@ export class BeltReaderComponent extends Component {
|
||||
super();
|
||||
this.clear();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
/**
|
||||
* Which items went through the reader, we only store the time
|
||||
*/
|
||||
|
@ -9,7 +9,7 @@ import { Component } from "../component";
|
||||
* Top Only:
|
||||
* @enum {string}
|
||||
*/
|
||||
export const enumClippedBeltUnderlayType: any = {
|
||||
export const enumClippedBeltUnderlayType = {
|
||||
full: "full",
|
||||
bottomOnly: "bottomOnly",
|
||||
topOnly: "topOnly",
|
||||
@ -22,7 +22,7 @@ export type BeltUnderlayTile = {
|
||||
};
|
||||
|
||||
export class BeltUnderlaysComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "BeltUnderlays";
|
||||
}
|
||||
public underlays = underlays;
|
||||
|
@ -3,10 +3,10 @@ import { BaseItem } from "../base_item";
|
||||
import { Component } from "../component";
|
||||
import { typeItemSingleton } from "../item_resolver";
|
||||
export class ConstantSignalComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "ConstantSignal";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
signal: types.nullable(typeItemSingleton),
|
||||
};
|
||||
@ -14,7 +14,7 @@ export class ConstantSignalComponent extends Component {
|
||||
/**
|
||||
* Copy the current state to another component
|
||||
*/
|
||||
copyAdditionalStateTo(otherComponent: ConstantSignalComponent): any {
|
||||
copyAdditionalStateTo(otherComponent: ConstantSignalComponent) {
|
||||
otherComponent.signal = this.signal;
|
||||
}
|
||||
public signal = signal;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Component } from "../component";
|
||||
export class DisplayComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Display";
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,13 @@ export type PendingFilterItem = {
|
||||
};
|
||||
|
||||
export class FilterComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Filter";
|
||||
}
|
||||
duplicateWithoutContents(): any {
|
||||
duplicateWithoutContents() {
|
||||
return new FilterComponent();
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
pendingItemsToLeaveThrough: types.array(types.structured({
|
||||
item: typeItemSingleton,
|
||||
@ -31,7 +31,7 @@ export class FilterComponent extends Component {
|
||||
super();
|
||||
this.clear();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
/**
|
||||
* Items in queue to leave through
|
||||
*/
|
||||
|
@ -3,10 +3,10 @@ import { BaseItem } from "../base_item";
|
||||
import { Component } from "../component";
|
||||
import { typeItemSingleton } from "../item_resolver";
|
||||
export class GoalAcceptorComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "GoalAcceptor";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
item: typeItemSingleton,
|
||||
};
|
||||
@ -17,7 +17,7 @@ export class GoalAcceptorComponent extends Component {
|
||||
super();
|
||||
this.clear();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
/**
|
||||
* The last item we delivered
|
||||
*/
|
||||
@ -30,18 +30,18 @@ export class GoalAcceptorComponent extends Component {
|
||||
/**
|
||||
* Clears items but doesn't instantly reset the progress bar
|
||||
*/
|
||||
clearItems(): any {
|
||||
clearItems() {
|
||||
this.lastDelivery = null;
|
||||
this.currentDeliveredItems = 0;
|
||||
}
|
||||
getRequiredSecondsPerItem(): any {
|
||||
getRequiredSecondsPerItem() {
|
||||
return (globalConfig.goalAcceptorsPerProducer /
|
||||
(globalConfig.puzzleModeSpeed * globalConfig.beltSpeedItemsPerSecond));
|
||||
}
|
||||
/**
|
||||
* Copy the current state to another component
|
||||
*/
|
||||
copyAdditionalStateTo(otherComponent: GoalAcceptorComponent): any {
|
||||
copyAdditionalStateTo(otherComponent: GoalAcceptorComponent) {
|
||||
otherComponent.item = this.item;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Component } from "../component";
|
||||
export class HubComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Hub";
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ export type ItemAcceptorSlotConfig = {
|
||||
|
||||
|
||||
export class ItemAcceptorComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "ItemAcceptor";
|
||||
}
|
||||
|
||||
@ -29,16 +29,16 @@ export class ItemAcceptorComponent extends Component {
|
||||
this.setSlots(slots);
|
||||
this.clear();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
/**
|
||||
* Fixes belt animations
|
||||
*/
|
||||
this.itemConsumptionAnimations = [];
|
||||
}
|
||||
setSlots(slots: Array<ItemAcceptorSlotConfig>): any {
|
||||
setSlots(slots: Array<ItemAcceptorSlotConfig>) {
|
||||
this.slots = [];
|
||||
for (let i: any = 0; i < slots.length; ++i) {
|
||||
const slot: any = slots[i];
|
||||
for (let i = 0; i < slots.length; ++i) {
|
||||
const slot = slots[i];
|
||||
this.slots.push({
|
||||
pos: slot.pos,
|
||||
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
|
||||
*/
|
||||
canAcceptItem(slotIndex: number, item: BaseItem=): any {
|
||||
const slot: any = this.slots[slotIndex];
|
||||
canAcceptItem(slotIndex: number, item: BaseItem=) {
|
||||
const slot = this.slots[slotIndex];
|
||||
return !slot.filter || slot.filter === item.getItemType();
|
||||
}
|
||||
/**
|
||||
* 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({
|
||||
item,
|
||||
slotIndex,
|
||||
@ -75,10 +75,10 @@ export class ItemAcceptorComponent extends Component {
|
||||
// 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.
|
||||
// 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
|
||||
for (let slotIndex: any = 0; slotIndex < this.slots.length; ++slotIndex) {
|
||||
const slot: any = this.slots[slotIndex];
|
||||
for (let slotIndex = 0; slotIndex < this.slots.length; ++slotIndex) {
|
||||
const slot = this.slots[slotIndex];
|
||||
// Make sure the acceptor slot is on the right position
|
||||
if (!slot.pos.equals(targetLocalTile)) {
|
||||
continue;
|
||||
|
@ -17,10 +17,10 @@ export type ItemEjectorSlot = {
|
||||
};
|
||||
|
||||
export class ItemEjectorComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "ItemEjector";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
// The cachedDestSlot, cachedTargetEntity fields are not serialized.
|
||||
return {
|
||||
slots: types.fixedSizeArray(types.structured({
|
||||
@ -35,8 +35,8 @@ export class ItemEjectorComponent extends Component {
|
||||
super();
|
||||
this.setSlots(slots);
|
||||
}
|
||||
clear(): any {
|
||||
for (const slot: any of this.slots) {
|
||||
clear() {
|
||||
for (const slot of this.slots) {
|
||||
slot.item = null;
|
||||
slot.lastItem = null;
|
||||
slot.progress = 0;
|
||||
@ -45,10 +45,10 @@ export class ItemEjectorComponent extends Component {
|
||||
setSlots(slots: Array<{
|
||||
pos: Vector;
|
||||
direction: enumDirection;
|
||||
}>): any {
|
||||
}>) {
|
||||
this.slots = [];
|
||||
for (let i: any = 0; i < slots.length; ++i) {
|
||||
const slot: any = slots[i];
|
||||
for (let i = 0; i < slots.length; ++i) {
|
||||
const slot = slots[i];
|
||||
this.slots.push({
|
||||
pos: slot.pos,
|
||||
direction: slot.direction,
|
||||
@ -65,14 +65,14 @@ export class ItemEjectorComponent extends Component {
|
||||
* {}
|
||||
*/
|
||||
getSlotTargetLocalTile(slot: ItemEjectorSlot): Vector {
|
||||
const directionVector: any = enumDirectionToVector[slot.direction];
|
||||
const directionVector = enumDirectionToVector[slot.direction];
|
||||
return slot.pos.add(directionVector);
|
||||
}
|
||||
/**
|
||||
* Returns whether any slot ejects to the given local tile
|
||||
*/
|
||||
anySlotEjectsToLocalTile(tile: Vector): any {
|
||||
for (let i: any = 0; i < this.slots.length; ++i) {
|
||||
anySlotEjectsToLocalTile(tile: Vector) {
|
||||
for (let i = 0; i < this.slots.length; ++i) {
|
||||
if (this.getSlotTargetLocalTile(this.slots[i]).equals(tile)) {
|
||||
return true;
|
||||
}
|
||||
@ -92,7 +92,7 @@ export class ItemEjectorComponent extends Component {
|
||||
* {}
|
||||
*/
|
||||
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)) {
|
||||
return i;
|
||||
}
|
||||
@ -117,8 +117,8 @@ export class ItemEjectorComponent extends Component {
|
||||
* {}
|
||||
*/
|
||||
takeSlotItem(slotIndex: number): BaseItem | null {
|
||||
const slot: any = this.slots[slotIndex];
|
||||
const item: any = slot.item;
|
||||
const slot = this.slots[slotIndex];
|
||||
const item = slot.item;
|
||||
slot.item = null;
|
||||
slot.progress = 0.0;
|
||||
return item;
|
||||
|
@ -2,7 +2,7 @@ import { types } from "../../savegame/serialization";
|
||||
import { BaseItem } from "../base_item";
|
||||
import { Component } from "../component";
|
||||
/** @enum {string} */
|
||||
export const enumItemProcessorTypes: any = {
|
||||
export const enumItemProcessorTypes = {
|
||||
balancer: "balancer",
|
||||
cutter: "cutter",
|
||||
cutterQuad: "cutterQuad",
|
||||
@ -21,7 +21,7 @@ export const enumItemProcessorTypes: any = {
|
||||
goal: "goal",
|
||||
};
|
||||
/** @enum {string} */
|
||||
export const enumItemProcessorRequirements: any = {
|
||||
export const enumItemProcessorRequirements = {
|
||||
painterQuad: "painterQuad",
|
||||
};
|
||||
export type EjectorItemToEject = {
|
||||
@ -36,10 +36,10 @@ export type EjectorCharge = {
|
||||
|
||||
|
||||
export class ItemProcessorComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "ItemProcessor";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
nextOutputSlot: types.uint,
|
||||
};
|
||||
@ -53,7 +53,7 @@ export class ItemProcessorComponent extends Component {
|
||||
super();
|
||||
this.clear();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
// 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
|
||||
// sure the outputs always match
|
||||
@ -78,7 +78,7 @@ export class ItemProcessorComponent extends Component {
|
||||
/**
|
||||
* Tries to take the item
|
||||
*/
|
||||
tryTakeItem(item: BaseItem, sourceSlot: number): any {
|
||||
tryTakeItem(item: BaseItem, sourceSlot: number) {
|
||||
if (this.type === enumItemProcessorTypes.hub ||
|
||||
this.type === enumItemProcessorTypes.trash ||
|
||||
this.type === enumItemProcessorTypes.goal) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Component } from "../component";
|
||||
export class ItemProducerComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "ItemProducer";
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Component } from "../component";
|
||||
import { types } from "../../savegame/serialization";
|
||||
export class LeverComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Lever";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
toggled: types.bool,
|
||||
};
|
||||
@ -12,7 +12,7 @@ export class LeverComponent extends Component {
|
||||
/**
|
||||
* Copy the current state to another component
|
||||
*/
|
||||
copyAdditionalStateTo(otherComponent: LeverComponent): any {
|
||||
copyAdditionalStateTo(otherComponent: LeverComponent) {
|
||||
otherComponent.toggled = this.toggled;
|
||||
}
|
||||
public toggled = toggled;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Component } from "../component";
|
||||
/** @enum {string} */
|
||||
export const enumLogicGateType: any = {
|
||||
export const enumLogicGateType = {
|
||||
and: "and",
|
||||
not: "not",
|
||||
xor: "xor",
|
||||
@ -15,7 +15,7 @@ export const enumLogicGateType: any = {
|
||||
painter: "painter",
|
||||
};
|
||||
export class LogicGateComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "LogicGate";
|
||||
}
|
||||
public type = type;
|
||||
|
@ -3,12 +3,12 @@ import { BaseItem } from "../base_item";
|
||||
import { Component } from "../component";
|
||||
import { Entity } from "../entity";
|
||||
import { typeItemSingleton } from "../item_resolver";
|
||||
const chainBufferSize: any = 6;
|
||||
const chainBufferSize = 6;
|
||||
export class MinerComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Miner";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
// cachedMinedItem is not serialized.
|
||||
return {
|
||||
lastMiningTime: types.ufloat,
|
||||
@ -24,14 +24,14 @@ export class MinerComponent extends Component {
|
||||
super();
|
||||
this.clear();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
/**
|
||||
* Stores items from other miners which were chained to this
|
||||
* miner.
|
||||
*/
|
||||
this.itemChainBuffer = [];
|
||||
}
|
||||
tryAcceptChainedItem(item: BaseItem): any {
|
||||
tryAcceptChainedItem(item: BaseItem) {
|
||||
if (this.itemChainBuffer.length > chainBufferSize) {
|
||||
// Well, this one is full
|
||||
return false;
|
||||
|
@ -7,10 +7,10 @@ import { types } from "../../savegame/serialization";
|
||||
import { getBuildingDataFromCode } from "../building_codes";
|
||||
import { Component } from "../component";
|
||||
export class StaticMapEntityComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "StaticMapEntity";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
origin: types.tileVector,
|
||||
rotation: types.float,
|
||||
@ -71,7 +71,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
/**
|
||||
* Copy the current state to another component
|
||||
*/
|
||||
copyAdditionalStateTo(otherComponent: Component): any {
|
||||
copyAdditionalStateTo(otherComponent: Component) {
|
||||
return new StaticMapEntityComponent({
|
||||
origin: this.origin.copy(),
|
||||
rotation: this.rotation,
|
||||
@ -93,7 +93,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
* {}
|
||||
*/
|
||||
getTileSpaceBounds(): Rectangle {
|
||||
const size: any = this.getTileSize();
|
||||
const size = this.getTileSize();
|
||||
switch (this.rotation) {
|
||||
case 0:
|
||||
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 {
|
||||
const result: any = localTile.rotateFastMultipleOf90(this.rotation);
|
||||
const result = localTile.rotateFastMultipleOf90(this.rotation);
|
||||
result.x += this.origin.x;
|
||||
result.y += this.origin.y;
|
||||
return result;
|
||||
@ -148,19 +148,19 @@ export class StaticMapEntityComponent extends Component {
|
||||
/**
|
||||
* Transforms from world space to local space
|
||||
*/
|
||||
worldToLocalTile(worldTile: Vector): any {
|
||||
const localUnrotated: any = worldTile.sub(this.origin);
|
||||
worldToLocalTile(worldTile: Vector) {
|
||||
const localUnrotated = worldTile.sub(this.origin);
|
||||
return this.unapplyRotationToVector(localUnrotated);
|
||||
}
|
||||
/**
|
||||
* Returns whether the entity should be drawn for the given parameters
|
||||
*/
|
||||
shouldBeDrawn(parameters: DrawParameters): any {
|
||||
let x: any = 0;
|
||||
let y: any = 0;
|
||||
let w: any = 0;
|
||||
let h: any = 0;
|
||||
const size: any = this.getTileSize();
|
||||
shouldBeDrawn(parameters: DrawParameters) {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let w = 0;
|
||||
let h = 0;
|
||||
const size = this.getTileSize();
|
||||
switch (this.rotation) {
|
||||
case 0: {
|
||||
x = this.origin.x;
|
||||
@ -198,13 +198,13 @@ export class StaticMapEntityComponent extends Component {
|
||||
/**
|
||||
* 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) {
|
||||
return;
|
||||
}
|
||||
const size: any = this.getTileSize();
|
||||
let worldX: any = this.origin.x * globalConfig.tileSize;
|
||||
let worldY: any = this.origin.y * globalConfig.tileSize;
|
||||
const size = this.getTileSize();
|
||||
let worldX = this.origin.x * globalConfig.tileSize;
|
||||
let worldY = this.origin.y * globalConfig.tileSize;
|
||||
if (overridePosition) {
|
||||
worldX = overridePosition.x * 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);
|
||||
}
|
||||
else {
|
||||
const rotationCenterX: any = worldX + globalConfig.halfTileSize;
|
||||
const rotationCenterY: any = worldY + globalConfig.halfTileSize;
|
||||
const rotationCenterX = worldX + globalConfig.halfTileSize;
|
||||
const rotationCenterY = worldY + globalConfig.halfTileSize;
|
||||
parameters.context.translate(rotationCenterX, rotationCenterY);
|
||||
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
|
||||
|
@ -8,10 +8,10 @@ export const MODS_ADDITIONAL_STORAGE_ITEM_RESOLVER: {
|
||||
[x: string]: (item: BaseItem) => Boolean;
|
||||
} = {};
|
||||
export class StorageComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Storage";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
storedCount: types.uint,
|
||||
storedItem: types.nullable(typeItemSingleton),
|
||||
@ -28,14 +28,14 @@ export class StorageComponent extends Component {
|
||||
/**
|
||||
* Returns whether this storage can accept the item
|
||||
*/
|
||||
canAcceptItem(item: BaseItem): any {
|
||||
canAcceptItem(item: BaseItem) {
|
||||
if (this.storedCount >= this.maximumStorage) {
|
||||
return false;
|
||||
}
|
||||
if (!this.storedItem || this.storedCount === 0) {
|
||||
return true;
|
||||
}
|
||||
const itemType: any = item.getItemType();
|
||||
const itemType = item.getItemType();
|
||||
if (itemType !== this.storedItem.getItemType()) {
|
||||
// Check type matches
|
||||
return false;
|
||||
@ -60,7 +60,7 @@ export class StorageComponent extends Component {
|
||||
getIsFull(): boolean {
|
||||
return this.storedCount >= this.maximumStorage;
|
||||
}
|
||||
takeItem(item: BaseItem): any {
|
||||
takeItem(item: BaseItem) {
|
||||
this.storedItem = item;
|
||||
this.storedCount++;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { Component } from "../component";
|
||||
import { Entity } from "../entity";
|
||||
import { typeItemSingleton } from "../item_resolver";
|
||||
/** @enum {string} */
|
||||
export const enumUndergroundBeltMode: any = {
|
||||
export const enumUndergroundBeltMode = {
|
||||
sender: "sender",
|
||||
receiver: "receiver",
|
||||
};
|
||||
@ -15,10 +15,10 @@ export type LinkedUndergroundBelt = {
|
||||
};
|
||||
|
||||
export class UndergroundBeltComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "UndergroundBelt";
|
||||
}
|
||||
static getSchema(): any {
|
||||
static getSchema() {
|
||||
return {
|
||||
pendingItems: types.array(types.pair(typeItemSingleton, types.float)),
|
||||
};
|
||||
@ -31,7 +31,7 @@ export class UndergroundBeltComponent extends Component {
|
||||
super();
|
||||
this.clear();
|
||||
}
|
||||
clear(): any {
|
||||
clear() {
|
||||
this.consumptionAnimations = [];
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
tryAcceptExternalItem(item: BaseItem, beltSpeed: number): any {
|
||||
tryAcceptExternalItem(item: BaseItem, beltSpeed: number) {
|
||||
if (this.mode !== enumUndergroundBeltMode.sender) {
|
||||
// Only senders accept external items
|
||||
return false;
|
||||
@ -59,13 +59,13 @@ export class UndergroundBeltComponent extends Component {
|
||||
/**
|
||||
* 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) {
|
||||
// Only receivers can accept tunneled items
|
||||
return false;
|
||||
}
|
||||
// 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) {
|
||||
// Simulate a real belt which gets full at some point
|
||||
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.
|
||||
// So instead of adding 1 we add 0.5 only.
|
||||
// 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]);
|
||||
return true;
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { Component } from "../component";
|
||||
/** @enum {string} */
|
||||
export const enumWireType: any = {
|
||||
export const enumWireType = {
|
||||
forward: "forward",
|
||||
turn: "turn",
|
||||
split: "split",
|
||||
cross: "cross",
|
||||
};
|
||||
/** @enum {string} */
|
||||
export const enumWireVariant: any = {
|
||||
export const enumWireVariant = {
|
||||
first: "first",
|
||||
second: "second",
|
||||
};
|
||||
export class WireComponent extends Component {
|
||||
static getId(): any {
|
||||
static getId() {
|
||||
return "Wire";
|
||||
}
|
||||
public type = type;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user