From 76b28a88b1ff224018d035576fb04d880a0e82a8 Mon Sep 17 00:00:00 2001 From: Skillbert Date: Fri, 17 Mar 2023 02:59:59 +0100 Subject: [PATCH] stricter typescript rules --- src/3d/modelnodes.ts | 12 ++--- src/3d/textures.ts | 22 +++++---- src/cache/downloader.ts | 9 ++-- src/cache/index.ts | 2 +- src/cache/rawfiles.ts | 1 - src/cache/sqlitewasm.ts | 2 - src/constants.ts | 6 +-- src/scripts/cachediff.ts | 1 - src/utils.ts | 101 +++++++-------------------------------- tsconfig.json | 15 ++++-- 10 files changed, 54 insertions(+), 117 deletions(-) diff --git a/src/3d/modelnodes.ts b/src/3d/modelnodes.ts index bb07832..7a9a31f 100644 --- a/src/3d/modelnodes.ts +++ b/src/3d/modelnodes.ts @@ -2,7 +2,7 @@ import { parse } from "../opdecoder"; import { appearanceUrl, avatarStringToBytes, avatarToModel } from "./avatar"; import * as THREE from "three"; import { ThreejsSceneCache, mergeModelDatas, ob3ModelToThree, mergeNaiveBoneids, constModelsIds } from '../3d/modeltothree'; -import { ModelModifications, constrainedMap, TypedEmitter } from '../utils'; +import { ModelModifications, constrainedMap, TypedEmitter, CallbackPromise } from '../utils'; import { boundMethod } from 'autobind-decorator'; import { resolveMorphedObject, modifyMesh, MapRect, ParsemapOpts, parseMapsquare, mapsquareModels, mapsquareToThreeSingle, ChunkData, TileGrid, mapsquareSkybox, generateLocationMeshgroups, PlacedMesh } from '../3d/mapsquare'; import { AnimationClip, AnimationMixer, Group, Material, Mesh, MeshBasicMaterial, Object3D, Skeleton, SkeletonHelper, SkinnedMesh, Texture, Vector2 } from "three"; @@ -156,11 +156,11 @@ export async function materialToModel(sceneCache: ThreejsSceneCache, modelid: nu export class RSModel extends TypedEmitter<{ loaded: undefined, animchanged: number }> implements ThreeJsSceneElementSource { model: Promise<{ modeldata: ModelData, mesh: Object3D, nullAnim: AnimationClip }>; loaded: { modeldata: ModelData, mesh: Object3D, nullAnim: AnimationClip, matUvAnims: { tex: Texture, v: Vector2 }[] } | null = null; - cache: ThreejsSceneCache; + cache!: ThreejsSceneCache; rootnode = new THREE.Group(); - nullAnimLoaded: (clip: AnimationClip) => void; + nullAnimPromise = { clip: null as AnimationClip | null, prom: new CallbackPromise() }; anims: Record }> = { - "-1": { clip: null, prom: new Promise(d => this.nullAnimLoaded = d) } + "-1": this.nullAnimPromise }; mountedanim: AnimationClip | null = null; mixer = new AnimationMixer(this.rootnode); @@ -232,8 +232,8 @@ export class RSModel extends TypedEmitter<{ loaded: undefined, animchanged: numb } }); let nullAnim = new AnimationClip(undefined, undefined, []); - this.nullAnimLoaded(nullAnim); - this.anims[-1].clip = nullAnim; + this.nullAnimPromise.clip = nullAnim; + this.nullAnimPromise.prom.done(nullAnim); this.rootnode.add(mesh); this.loaded = { mesh, modeldata, nullAnim, matUvAnims }; diff --git a/src/3d/textures.ts b/src/3d/textures.ts index 522f946..088c654 100644 --- a/src/3d/textures.ts +++ b/src/3d/textures.ts @@ -22,6 +22,7 @@ export class ParsedTexture { if (texture instanceof ImageData) { this.filesize = texture.data.byteLength; this.type = "imagedata"; + this.mipmaps = 1; this.cachedImageDatas = [Promise.resolve(texture)]; } else { this.filesize = texture.byteLength; @@ -36,34 +37,35 @@ export class ParsedTexture { let offset = 0; //peek first bytes of first image file - let foundtype = false; - for (let extraoffset = 0; extraoffset <= 1; extraoffset++) { + let extraoffset = 0 + while (true) { let byte0 = texture.readUInt8(extraoffset + offset + 1 + 4 + 0); let byte1 = texture.readUInt8(extraoffset + offset + 1 + 4 + 1); if (byte0 == 0 && byte1 == 0) { //has no header magic, but starts by writing the width in uint32 BE, any widths under 65k have 0x0000xxxx this.type = "bmpmips"; + break; } else if (byte0 == 0x44 && byte1 == 0x44) { //0x44445320 "DDS " this.type = "dds"; + break; } else if (byte0 == 0x89 && byte1 == 0x50) { //0x89504e47 ".PNG" this.type = "png"; + break; } else if (byte0 == 0xab && byte1 == 0x4b) { //0xab4b5458 "«KTX" this.type = "ktx"; - } else { + break; + } else if (extraoffset++ <= 1) { continue; } - foundtype = true; - if (extraoffset == 1) { - let numtexs = texture.readUint8(offset++); - //TODO figure this out further - } - break; - } if (!foundtype) { throw new Error(`failed to detect texture`); } + if (extraoffset == 1) { + let numtexs = texture.readUint8(offset++); + //TODO figure this out further + } this.mipmaps = texture.readUInt8(offset++); if (this.type == "bmpmips") { diff --git a/src/cache/downloader.ts b/src/cache/downloader.ts index a243232..8f3d088 100644 --- a/src/cache/downloader.ts +++ b/src/cache/downloader.ts @@ -4,7 +4,7 @@ import * as net from "net"; import fetch from "node-fetch"; import { crc32 } from "../libs/crc32util"; import { FileParser } from "../opdecoder"; -import { delay } from "../utils"; +import { CallbackPromise, delay } from "../utils"; import { cacheMajors } from "../constants"; const maxblocksize = 102400; @@ -96,7 +96,7 @@ function trackDataUsage(len: number) { class DownloadSocket { pending: PendingFile[] = []; - ready: Promise; + ready = new CallbackPromise(); socket: net.Socket; config: ParsedClientconfig; @@ -148,8 +148,8 @@ class DownloadSocket { } async run() { - this.ready = this.connect(); - await this.ready; + await this.connect(); + this.ready.done(); while (true) { let bytesread = 0; try { var chunk = await this.getChunk(1 + 4); } @@ -235,7 +235,6 @@ export class CacheDownloader extends DirectCacheFileSource { configPromise: Promise; socket: DownloadSocket | null = null; socketPromise: Promise | null = null; - pending: PendingFile[]; constructor() { super(true); diff --git a/src/cache/index.ts b/src/cache/index.ts index 1eef828..b0a8e6f 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -328,7 +328,7 @@ export abstract class CacheFileSource { export abstract class DirectCacheFileSource extends CacheFileSource { indexMap = new Map>(); requiresCrc: boolean; - xteakeys: XteaTable | null; + xteakeys: XteaTable | null = null; constructor(needscrc: boolean) { super(); diff --git a/src/cache/rawfiles.ts b/src/cache/rawfiles.ts index 4b021ed..87f578d 100644 --- a/src/cache/rawfiles.ts +++ b/src/cache/rawfiles.ts @@ -5,7 +5,6 @@ import { CacheFileSource, CacheIndex, CacheIndexFile, SubFile } from "./index"; export class RawFileLoader extends CacheFileSource { cachedir: string; - writable: boolean; virtualMajor: number; index: CacheIndex[]; files = new Map(); diff --git a/src/cache/sqlitewasm.ts b/src/cache/sqlitewasm.ts index 78b838b..4dc94f5 100644 --- a/src/cache/sqlitewasm.ts +++ b/src/cache/sqlitewasm.ts @@ -4,8 +4,6 @@ import type { WorkerPackets } from "./sqlitewasmworker"; export class WasmGameCacheLoader extends cache.CacheFileSource { - cachedir: string; - writable: boolean; indices = new Map>(); dbfiles: Record = {}; worker: Worker; diff --git a/src/constants.ts b/src/constants.ts index a14003f..e1fbd5a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -41,7 +41,7 @@ export const cacheMajors = { achievements: 57, index: 255 -} +} as const; //represents the largest build number that this application is aware off //is used as default value when a cache is considered "current" @@ -53,7 +53,7 @@ export const cacheMapFiles = { squares: 3, squaresWater: 4, square_nxt: 5 -} +} as const; export const cacheConfigPages = { mapunderlays: 1, @@ -69,7 +69,7 @@ export const cacheConfigPages = { npcs_old: 9, items_old: 10, spotanim_old: 13 -} +} as const; export const lastLegacyBuildnr = 377; //unclear if there ended up beign overlap with (public) rs2 since this was 12 years after rs2 release diff --git a/src/scripts/cachediff.ts b/src/scripts/cachediff.ts index 9e12abd..83fa6d0 100644 --- a/src/scripts/cachediff.ts +++ b/src/scripts/cachediff.ts @@ -91,7 +91,6 @@ export class FileEdit { minor: number; subfile: number; action: FileAction; - source: CacheFileSource; before: Buffer | Loadable | null; after: Buffer | Loadable | null; constructor(action: FileAction, type: CacheEditType, major: number, minor: number, subfile: number, before: Buffer | Loadable | null, after: Buffer | Loadable | null) { diff --git a/src/utils.ts b/src/utils.ts index 157eb84..67d85d7 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -368,90 +368,6 @@ export function packedHSL2HSL(hsl: number) { return [h, s, l]; } -/*function packedHSL2RGBAArray(hsl) -{ - var packedRGBA = packedHSL2RGBA(hsl); - var rgba = []; - rgba.push((packedRGBA ) & 0xFF); - rgba.push((packedRGBA >> 8) & 0xFF); - rgba.push((packedRGBA >> 16) & 0xFF); - rgba.push((packedRGBA >> 24) & 0xFF); - return rgba; -}*/ - -// https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_model_view_projection#Perspective_matrix -export function getProjectionMatrix(fieldOfViewInRadians: number, aspectRatio: number, near: number, far: number) { - var f = 1.0 / Math.tan(fieldOfViewInRadians / 2); - var rangeInv = 1 / (near - far); - - return [ - f / aspectRatio, 0, 0, 0, - 0, f, 0, 0, - 0, 0, (near + far) * rangeInv, -1, - 0, 0, near * far * rangeInv * 2, 0 - ]; -} - -export namespace Matrix4x4Utils { - export function mul(a: number[], b: number[]) { - var c: number[] = []; - for (var y = 0; y < 4; ++y) { - for (var x = 0; x < 4; ++x) { - var sum = 0; - for (var n = 0; n < 4; ++n) { - sum += a[n + y * 4] * b[x + n * 4]; - } - c.push(sum); - } - } - return c; - } - - export function identity() { - return [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ]; - } - - export function translation(x: number, y: number, z: number) { - return [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - x, y, z, 1.0 - ]; - } - - export function rotation(axis: "x" | "y" | "z", angle: number) { - var a = 0, b = 0; - if (axis == "x") { - a = 1; - b = 2; - } - else if (axis == "y") { - a = 0; - b = 2; - } - else if (axis == "z") { - a = 0; - b = 1; - } - else - //TODO throw here? - return; // Incorrect axis parameter, ya basic! - - var matrix = this.identity(); - matrix[a + a * 4] = Math.cos(angle); - matrix[b + b * 4] = Math.cos(angle); - matrix[b + a * 4] = -Math.sin(angle); - matrix[a + b * 4] = Math.sin(angle); - return matrix; - } -} - export class TypedEmitter> { protected listeners: { [key in keyof T]?: Set<(v: T[key]) => void> } = {}; on(event: K, listener: (v: T[K]) => void) { @@ -474,4 +390,19 @@ export class TypedEmitter> { let listeners = this.listeners[event] ?? (this.listeners[event] = new Set()); listeners.forEach(cb => cb(value)); } -} \ No newline at end of file +} + +export class CallbackPromise extends Promise { + done!: (v: T) => void; + err!: (e: Error) => void; + constructor(exe = (done: (v: T) => void, err: (e: Error) => void) => { }) { + //tmp vars since i can't access this during the super callback + let tmpdone: (v: T) => void; + let tmperr: (e: Error) => void; + super((done, err) => { tmpdone = done; tmperr = err; return exe(done, err); }); + this.done = tmpdone!; + this.err = tmperr!; + } +} + +globalThis.promhack = CallbackPromise; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 1994640..73294e2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,10 @@ "compilerOptions": { "moduleResolution": "node", "module": "ESNext", - "lib": [ "ESNext","DOM"], + "lib": [ + "ESNext", + "DOM" + ], "target": "ES2020", "sourceMap": false, "alwaysStrict": true, @@ -14,8 +17,14 @@ "rootDir": "./src", "esModuleInterop": true, "experimentalDecorators": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictPropertyInitialization":true }, - "exclude": [ "node_modules", "./generated"], + "exclude": [ + "node_modules", + "./generated" + ], "compileOnSave": false } \ No newline at end of file