From c6378e15385f568417cf53a8d72900f4de2fe558 Mon Sep 17 00:00:00 2001 From: Yiin Date: Sun, 11 Feb 2024 06:37:09 +0200 Subject: [PATCH] feat(shared): Cleanup Vector2 & Vector3 apis (#170) * shared: fix Vector2 & Vector3 api * shared: cleanup unused vector code * Update versions --- shared/js/classes/vector.js | 317 ++++++++++++++++++++---------------- types/client/index.d.ts | 22 +-- types/client/package.json | 2 +- types/server/index.d.ts | 42 ++--- types/server/package.json | 2 +- types/shared/index.d.ts | 18 +- 6 files changed, 224 insertions(+), 179 deletions(-) diff --git a/shared/js/classes/vector.js b/shared/js/classes/vector.js index ebe40c9dc..557274c62 100644 --- a/shared/js/classes/vector.js +++ b/shared/js/classes/vector.js @@ -1,183 +1,129 @@ // clang-format off -// WIP -class VectorCache { - #size = 0; - #cache = new Map(); - #ctor = null; - - constructor(size, ctor) { - this.#size = size; - this.#ctor = ctor; - } - - insert(values) { - const map = this.#cache; - for (let i = 0; i < this.#size; i++) { - if (!map.has(values[i])) map.set(values[i], new Map()); - map = map.get(values[i]); - if (i === this.#size - 1) map.set(values[i], new this.#ctor(...values)); - } - } - get(values) { - const map = this.#cache; - for (let i = 0; i < this.#size; i++) { - if (!map.has(values[i])) return null; - map = map.get(values[i]); - if (i === this.#size - 1) return map.get(values[i]); - } - } -} - -class Vector { - #size = 0; - values = []; - - constructor(size, values) { - this.#size = size; - this.values = values; +export class Vector3 { + constructor(...args) { + [this.x, this.y, this.z] = this.#getArgValues(...args); Object.freeze(this); } add(...args) { - let values = this.#getArgValues(...args); - return new this.constructor(...this.values.map((value, i) => value + values[i])); + const [x, y, z] = this.#getArgValues(...args); + return new Vector3(this.x + x, this.y + y, this.z + z); } + sub(...args) { - let values = this.#getArgValues(...args); - return new this.constructor(...this.values.map((value, i) => value - values[i])); + const [x, y, z] = this.#getArgValues(...args); + return new Vector3(this.x - x, this.y - y, this.z - z); } + mul(...args) { - let values = this.#getArgValues(...args); - return new this.constructor(...this.values.map((value, i) => value * values[i])); + const [x, y, z] = this.#getArgValues(...args); + return new Vector3(this.x * x, this.y * y, this.z * z); } + div(...args) { - let values = this.#getArgValues(...args); - return new this.constructor(...this.values.map((value, i) => value / values[i])); + const [x, y, z] = this.#getArgValues(...args); + if (x === 0 || y === 0 || z === 0) { + throw new Error("Division by zero"); + } + return new Vector3(this.x / x, this.y / y, this.z / z); } dot(...args) { - let values = this.#getArgValues(...args); - let sum = 0; - for (let i = 0; i < this.#size; i++) sum += this.values[i] * values[i]; - return sum; + const [x, y, z] = this.#getArgValues(...args); + return this.x * x + this.y * y + this.z * z; } - toArray() { - return Array.from(this.values); - } - - toFixed(precision = 4) { - let fixedValues = []; - for (let i = 0; i < this.#size; i++) fixedValues.push(parseFloat(this.values[i].toFixed(precision))); - return new this.constructor(...fixedValues); + cross(...args) { + const [x, y, z] = this.#getArgValues(...args); + return new Vector3(this.y * z - this.z * y, this.z * x - this.x * z, this.x * y - this.y * x); } get lengthSquared() { - let sum = 0; - for (let i = 0; i < this.#size; i++) sum += this.values[i] * this.values[i]; - return sum; + return this.x * this.x + this.y * this.y + this.z * this.z; } get length() { return Math.sqrt(this.lengthSquared); } - get negative() { - return new this.constructor(...this.values.map((value) => -value)); + get normalized() { + const length = this.length; + if (length === 0) { + return Vector3.zero; + } + return new Vector3(this.x / length, this.y / length, this.z / length); } get inverse() { - return new this.constructor(...this.values.map((value) => 1 / value)); + return new Vector3(this.x ? 1 / this.x : 0, this.y ? 1 / this.y : 0, this.z ? 1 / this.z : 0); } - get normalized() { - return this.div(this.length); + get negative() { + return new Vector3(-this.x, -this.y, -this.z); } - distanceTo(...args) { - return Math.sqrt(this.distanceToSquared(...args)); + angleTo(...args) { + const [x, y, z] = this.#getArgValues(...args); + const mag1 = this.length; + const mag2 = Math.sqrt(x * x + y * y + z * z); + const dot = this.dot(x, y, z); + return Math.acos(dot / (mag1 * mag2)); } - distanceToSquared(...args) { - let values = this.#getArgValues(...args); - let sum = 0; - for (let i = 0; i < this.#size; i++) sum += (this.values[i] - values[i]) * (this.values[i] - values[i]); - return sum; + angleToDegrees(...args) { + return this.angleTo(...args) * (180 / Math.PI); } - angleTo(...args) { - let values = this.#getArgValues(...args); - let dot = this.dot(...values); - let length = this.length * Math.sqrt(values.map((value) => value * value).reduce((a, b) => a + b)); - return Math.acos(dot / length); + distanceTo(...args) { + const [x, y, z] = this.#getArgValues(...args); + const dx = this.x - x; + const dy = this.y - y; + const dz = this.z - z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); } - angleToDegrees(...args) { - return this.angleTo(...args) * (180 / Math.PI); + distanceToSquared(...args) { + const [x, y, z] = this.#getArgValues(...args); + const dx = this.x - x; + const dy = this.y - y; + const dz = this.z - z; + return dx * dx + dy * dy + dz * dz; + } + + toFixed(precision = 4) { + return new Vector3(parseFloat(this.x.toFixed(precision)), parseFloat(this.y.toFixed(precision)), parseFloat(this.z.toFixed(precision))); } toDegrees() { - return new this.constructor(...this.values.map((value) => value * (180 / Math.PI))); + return new Vector3(this.x * (180 / Math.PI), this.y * (180 / Math.PI), this.z * (180 / Math.PI)); } toRadians() { - return new this.constructor(...this.values.map((value) => value * (Math.PI / 180))); + return new Vector3(this.x * (Math.PI / 180), this.y * (Math.PI / 180), this.z * (Math.PI / 180)); } isInRange(range, ...args) { - let values = this.#getArgValues(...args); - for (let i = 0; i < this.#size; i++) { - if (this.values[i] < values[i] - range || this.values[i] > values[i] + range) return false; - } - return true; + const [x, y, z] = this.#getArgValues(...args); + return Math.abs(this.x - x) <= range && Math.abs(this.y - y) <= range && Math.abs(this.z - z) <= range; } - lerp(ratio, ...args) { - let values = this.#getArgValues(...args); - return new this.constructor(...this.values.map((value, i) => value + (values[i] - value) * ratio)); + lerp(alpha, ...args) { + const [x, y, z] = this.#getArgValues(...args); + return new Vector3(this.x + (x - this.x) * alpha, this.y + (y - this.y) * alpha, this.z + (z - this.z) * alpha); } #getArgValues(...args) { let values = []; - if (args.length === this.#size) values = args; + if (args.length === 3) values = args; else if (args.length === 1) { const arg = args[0]; - if (arg instanceof Vector) values = arg.values; + if (arg instanceof Vector3) values = [arg.x, arg.y, arg.z]; else if (Array.isArray(arg)) values = arg; else if (typeof arg === "object") values = Object.values(arg); - else for (let i = 0; i < this.#size; i++) values.push(arg); + else values = [arg, arg, arg]; } else throw new Error("Invalid arguments"); - return values; - } -} - -export class Vector3 extends Vector { - constructor(...args) { - let values; - if (args.length === 3) values = [valueToNumber(args[0]), valueToNumber(args[1]), valueToNumber(args[2])]; - else if (args.length === 1) { - const arg = args[0]; - if (Array.isArray(arg)) values = [valueToNumber(arg[0]), valueToNumber(arg[1]), valueToNumber(arg[2])]; - else if (typeof arg === "object") values = [valueToNumber(arg.x), valueToNumber(arg.y), valueToNumber(arg.z)]; - else values = [valueToNumber(arg), valueToNumber(arg), valueToNumber(arg)]; - } else throw new Error("Invalid arguments"); - super(3, values); - } - - get x() { - return this.values[0]; - } - get y() { - return this.values[1]; - } - get z() { - return this.values[2]; - } - - cross(...args) { - const vec = new Vector3(...args); - return new this.constructor(this.y * vec.z - this.z * vec.y, this.z * vec.x - this.x * vec.z, this.x * vec.y - this.y * vec.x); + return values.map(valueToNumber); } static fromArray(arr) { @@ -189,10 +135,10 @@ export class Vector3 extends Vector { static zero = new Vector3(0, 0, 0); static one = new Vector3(1, 1, 1); - static back = new Vector3(0, -1, 0); static up = new Vector3(0, 0, 1); static down = new Vector3(0, 0, -1); static forward = new Vector3(0, 1, 0); + static back = new Vector3(0, -1, 0); static left = new Vector3(-1, 0, 0); static right = new Vector3(1, 0, 0); static negativeInfinity = new Vector3(-Infinity, -Infinity, -Infinity); @@ -200,24 +146,123 @@ export class Vector3 extends Vector { } cppBindings.registerExport(cppBindings.BindingExport.VECTOR3_CLASS, Vector3); -export class Vector2 extends Vector { +export class Vector2 { constructor(...args) { - let values; - if (args.length === 2) values = [valueToNumber(args[0]), valueToNumber(args[1])]; - else if (args.length === 1) { - const arg = args[0]; - if (Array.isArray(arg)) values = [valueToNumber(arg[0]), valueToNumber(arg[1])]; - else if (typeof arg === "object") values = [valueToNumber(arg.x), valueToNumber(arg.y)]; - else values = [valueToNumber(arg), valueToNumber(arg)]; - } else throw new Error("Invalid arguments"); - super(2, values); + [this.x, this.y] = this.#getArgValues(...args); + Object.freeze(this); + } + + add(...args) { + const [x, y] = this.#getArgValues(...args); + return new Vector2(this.x + x, this.y + y); + } + + sub(...args) { + const [x, y] = this.#getArgValues(...args); + return new Vector2(this.x - x, this.y - y); + } + + mul(...args) { + const [x, y] = this.#getArgValues(...args); + return new Vector2(this.x * x, this.y * y); + } + + div(...args) { + const [x, y] = this.#getArgValues(...args); + if (x === 0 || y === 0) { + throw new Error("Division by zero"); + } + return new Vector2(this.x / x, this.y / y); + } + + dot(...args) { + const [x, y] = this.#getArgValues(...args); + return this.x * x + this.y * y; + } + + get lengthSquared() { + return this.x * this.x + this.y * this.y; + } + + get length() { + return Math.sqrt(this.lengthSquared); + } + + get normalized() { + const length = this.length; + if (length === 0) { + return Vector2.zero; + } + return new Vector2(this.x / length, this.y / length); + } + + get inverse() { + return new Vector2(this.x ? 1 / this.x : 0, this.y ? 1 / this.y : 0); + } + + get negative() { + return new Vector2(-this.x, -this.y); + } + + angleTo(...args) { + const [x, y] = this.#getArgValues(...args); + const mag1 = this.length; + const mag2 = Math.sqrt(x * x + y * y); + const dot = this.dot(x, y); + return Math.acos(dot / (mag1 * mag2)); + } + + angleToDegrees(...args) { + return (this.angleTo(...args) * 180) / Math.PI; + } + + distanceTo(...args) { + const [x, y] = this.#getArgValues(...args); + const dx = this.x - x; + const dy = this.y - y; + return Math.sqrt(dx * dx + dy * dy); + } + + distanceToSquared(...args) { + const [x, y] = this.#getArgValues(...args); + const dx = this.x - x; + const dy = this.y - y; + return dx * dx + dy * dy; + } + + toFixed(precision = 4) { + return new Vector2(parseFloat(this.x.toFixed(precision)), parseFloat(this.y.toFixed(precision))); + } + + toRadians() { + return new Vector2((this.x * Math.PI) / 180, (this.y * Math.PI) / 180); + } + + toDegrees() { + return new Vector2((this.x * 180) / Math.PI, (this.y * 180) / Math.PI); } - get x() { - return this.values[0]; + isInRange(range, ...args) { + const [x, y] = this.#getArgValues(...args); + return Math.abs(this.x - x) <= range && Math.abs(this.y - y) <= range; + } + + lerp(alpha, ...args) { + const [x, y] = this.#getArgValues(...args); + return new Vector2(this.x + alpha * (x - this.x), this.y + alpha * (y - this.y)); } - get y() { - return this.values[1]; + + #getArgValues(...args) { + let values = []; + if (args.length === 2) values = args; + else if (args.length === 1) { + const arg = args[0]; + if (arg instanceof Vector2) values = [arg.x, arg.y]; + else if (Array.isArray(arg)) values = arg; + else if (typeof arg === "object") values = Object.values(arg); + else values = [arg, arg]; + } else throw new Error("Invalid arguments"); + return values.map(valueToNumber); } static fromArray(arr) { diff --git a/types/client/index.d.ts b/types/client/index.d.ts index 757e7375c..a6343b4b0 100644 --- a/types/client/index.d.ts +++ b/types/client/index.d.ts @@ -13,7 +13,7 @@ declare module "@altv/client" { export const clientConfig: Readonly>; export const clientPath: string; - export const localMeta: Readonly; + export const localMeta: Readonly>; export function isMenuOpen(): boolean; export function isConsoleOpen(): boolean; @@ -234,7 +234,7 @@ declare module "@altv/client" { static getByID(type: altShared.Enums.BaseObjectType, id: number): BaseObject | null; static getByRemoteID(type: altShared.Enums.BaseObjectType, id: number): BaseObject | null; - readonly meta: BaseObjectMeta & { [key: string]: unknown }; + readonly meta: BaseObjectMeta & Record; } export type PointBlipCreateOptions = { pos: altShared.IVector3; entity?: never } | { entity: Entity; pos?: never }; @@ -256,7 +256,7 @@ declare module "@altv/client" { readonly isAttached: boolean; readonly attachedTo?: Entity; - readonly meta: BlipMeta & { [key: string]: unknown }; + readonly meta: BlipMeta & Record; blipType: altShared.Enums.BlipType; scale: altShared.Vector2; @@ -316,7 +316,7 @@ declare module "@altv/client" { readonly isGlobal: boolean; readonly streamingDistance: number; - readonly meta: MarkerMeta & { [key: string]: unknown }; + readonly meta: MarkerMeta & Record; color: altShared.RGBA; visible: boolean; @@ -412,7 +412,7 @@ declare module "@altv/client" { readonly netOwner?: Player; readonly visible: boolean; readonly isStreamedIn: boolean; - readonly streamSyncedMeta: Readonly; + readonly streamSyncedMeta: Readonly>; frozen: boolean; rot: altShared.Vector3; @@ -617,8 +617,8 @@ declare module "@altv/client" { readonly armour: number; readonly currentWeapon: number; - readonly meta: PedMeta & { [key: string]: unknown }; - readonly streamSyncedMeta: Readonly; + readonly meta: PedMeta & Record; + readonly streamSyncedMeta: Readonly>; static readonly all: ReadonlyArray; static readonly streamedIn: ReadonlyArray; @@ -775,7 +775,7 @@ declare module "@altv/client" { getWeaponTintIndex(weaponHash: number | string): number | undefined; hasWeaponComponent(weaponHash: number | string, componentHash: number | string): boolean; - readonly streamSyncedMeta: Readonly; + readonly streamSyncedMeta: Readonly>; static readonly local: LocalPlayer; static readonly all: ReadonlyArray; @@ -1003,7 +1003,7 @@ declare module "@altv/client" { readonly steeringAngle: number; readonly rearWheelVariation: number; - readonly streamSyncedMeta: Readonly; + readonly streamSyncedMeta: Readonly>; readonly speed: number; readonly gear: number; @@ -1119,8 +1119,8 @@ declare module "@altv/client" { visible: boolean; - readonly meta: VirtualEntityMeta & { [key: string]: unknown }; - readonly streamSyncedMeta: Readonly; + readonly meta: VirtualEntityMeta & Record; + readonly streamSyncedMeta: Readonly>; static readonly all: ReadonlyArray; static readonly streamedIn: ReadonlyArray; diff --git a/types/client/package.json b/types/client/package.json index 1d58f548a..d66eae63a 100644 --- a/types/client/package.json +++ b/types/client/package.json @@ -1,6 +1,6 @@ { "name": "@altv/client", - "version": "0.0.26", + "version": "0.0.27", "description": "This package contains the type definitions for the alt:V JS module v2 client types", "types": "index.d.ts", "files": [ diff --git a/types/server/index.d.ts b/types/server/index.d.ts index 7ce0556d1..5936b3327 100644 --- a/types/server/index.d.ts +++ b/types/server/index.d.ts @@ -8,7 +8,7 @@ declare module "@altv/server" { import * as altShared from "@altv/shared"; export const rootDir: string; - export const syncedMeta: altShared.GlobalSyncedMeta & { [key: string]: unknown }; + export const syncedMeta: altShared.GlobalSyncedMeta & Record; export const serverConfig: Readonly>; export function setServerPassword(password: string): void; @@ -23,7 +23,7 @@ declare module "@altv/server" { export function setVoiceExternal(host: string, port: number): void; export class BaseObject extends altShared.BaseObject { - meta: BaseObjectMeta & { [key: string]: unknown }; + meta: BaseObjectMeta & Record; static getByID(type: altShared.Enums.BaseObjectType, id: number): BaseObject | null; } @@ -93,7 +93,7 @@ declare module "@altv/server" { addTarget(target: Player): void; removeTarget(target: Player): void; - meta: BlipMeta & { [key: string]: unknown }; + meta: BlipMeta & Record; public onCreate?(opts: BlipCreateOptions): void; public onDestroy?(): void; @@ -122,7 +122,7 @@ declare module "@altv/server" { readonly target?: Player; readonly streamingDistance: number; - meta: MarkerMeta & { [key: string]: unknown }; + meta: MarkerMeta & Record; color: altShared.RGBA; visible: boolean; @@ -214,7 +214,7 @@ declare module "@altv/server" { isEntityIdIn(id: number): boolean; isPointIn(point: altShared.Vector3): boolean; - meta: ColShapeMeta & { [key: string]: unknown }; + meta: ColShapeMeta & Record; static readonly all: ReadonlyArray; @@ -256,8 +256,8 @@ declare module "@altv/server" { isEntityIdIn(id: number): boolean; isPointIn(point: altShared.Vector3): boolean; - meta: CheckpointMeta & { [key: string]: unknown }; - streamSyncedMeta: altShared.CheckpointStreamSyncedMeta & { [key: string]: unknown }; + meta: CheckpointMeta & Record; + streamSyncedMeta: altShared.CheckpointStreamSyncedMeta & Record; public onCreate?(opts: CheckpointCreateOptions): void; public onDestroy?(): void; @@ -284,8 +284,8 @@ declare module "@altv/server" { streamingDistance: number; readonly timestamp: number; - meta: EntityMeta & { [key: string]: unknown }; - streamSyncedMeta: altShared.EntityStreamSyncedMeta & { [key: string]: unknown }; + meta: EntityMeta & Record; + streamSyncedMeta: altShared.EntityStreamSyncedMeta & Record; setNetOwner(player: Player, disableMigration: boolean): void; resetNetOwner(disableMigration: boolean): void; @@ -326,8 +326,8 @@ declare module "@altv/server" { activatePhysics(): void; placeOnGroundProperly(): void; - meta: ObjectMeta & { [key: string]: unknown }; - streamSyncedMeta: altShared.ObjectStreamSyncedMeta & { [key: string]: unknown }; + meta: ObjectMeta & Record; + streamSyncedMeta: altShared.ObjectStreamSyncedMeta & Record; public onCreate?(opts: ObjectCreateOptions): void; public onDestroy?(): void; @@ -354,8 +354,8 @@ declare module "@altv/server" { armour: number; currentWeapon: number; - meta: PedMeta & { [key: string]: unknown }; - streamSyncedMeta: altShared.PedStreamSyncedMeta & { [key: string]: unknown }; + meta: PedMeta & Record; + streamSyncedMeta: altShared.PedStreamSyncedMeta & Record; public onCreate?(opts: PedCreateOptions): void; public onDestroy?(): void; @@ -531,9 +531,9 @@ declare module "@altv/server" { sendRPC(rpcName: E, ...args: Parameters): Promise>; sendRPC(rpcName: Exclude, ...args: unknown[]): Promise; - meta: PlayerMeta & { [key: string]: unknown }; - localMeta: PlayerLocalMeta & { [key: string]: unknown }; - streamSyncedMeta: altShared.PlayerStreamSyncedMeta & { [key: string]: unknown }; + meta: PlayerMeta & Record; + localMeta: PlayerLocalMeta & Record; + streamSyncedMeta: altShared.PlayerStreamSyncedMeta & Record; static readonly all: ReadonlyArray; static getByID(id: number): Player | null; @@ -719,8 +719,8 @@ declare module "@altv/server" { setWeaponCapacity(index: number, state: number): void; setBadge(textureDictionary: string | number, texture: string | number, pos: VehicleBadgePosition, pos2?: VehicleBadgePosition, pos3?: VehicleBadgePosition, pos4?: VehicleBadgePosition): void; - meta: VehicleMeta & { [key: string]: unknown }; - streamSyncedMeta: altShared.VehicleStreamSyncedMeta & { [key: string]: unknown }; + meta: VehicleMeta & Record; + streamSyncedMeta: altShared.VehicleStreamSyncedMeta & Record; public onCreate?(opts: VehicleCreateOptions): void; public onDestroy?(): void; @@ -770,8 +770,8 @@ declare module "@altv/server" { visible: boolean; - meta: VirtualEntityMeta & { [key: string]: unknown }; - streamSyncedMeta: altShared.VirtualEntityStreamSyncedMeta & { [key: string]: unknown }; + meta: VirtualEntityMeta & Record; + streamSyncedMeta: altShared.VirtualEntityStreamSyncedMeta & Record; public onCreate?(opts: VirtualEntityCreateOptions): void; public onDestroy?(): void; @@ -795,7 +795,7 @@ declare module "@altv/server" { readonly players: ReadonlyArray; readonly playerCount: number; - meta: VoiceChannelMeta & { [key: string]: unknown }; + meta: VoiceChannelMeta & Record; hasPlayer(player: Player): boolean; addPlayer(player: Player): void; diff --git a/types/server/package.json b/types/server/package.json index 49494ca71..6ce066afa 100644 --- a/types/server/package.json +++ b/types/server/package.json @@ -1,6 +1,6 @@ { "name": "@altv/server", - "version": "0.0.29", + "version": "0.0.30", "description": "This package contains the type definitions for the alt:V JS module v2 server types", "types": "index.d.ts", "files": [ diff --git a/types/shared/index.d.ts b/types/shared/index.d.ts index 9358170a5..b7d4b1e68 100644 --- a/types/shared/index.d.ts +++ b/types/shared/index.d.ts @@ -13,8 +13,8 @@ declare module "@altv/shared" { export const sdkVersion: string; export const branch: string; - export const meta: GlobalMeta & { [key: string]: unknown }; - export const syncedMeta: GlobalSyncedMeta & { [key: string]: unknown }; + export const meta: GlobalMeta & Record; + export const syncedMeta: GlobalSyncedMeta & Record; export function log(...args: unknown[]): void; export function logDebug(...args: unknown[]): void; @@ -104,13 +104,13 @@ declare module "@altv/shared" { type ColShapeCreateOptions = { colShapeType: Enums.ColShapeType; } & ( - | ({ colShapeType: Enums.ColShapeType.SPHERE } & ColShapeSphereCreateOptions) - | ({ colShapeType: Enums.ColShapeType.CYLINDER } & ColShapeCylinderCreateOptions) - | ({ colShapeType: Enums.ColShapeType.CIRCLE } & ColShapeCircleCreateOptions) - | ({ colShapeType: Enums.ColShapeType.CUBOID } & ColShapeCuboidCreateOptions) - | ({ colShapeType: Enums.ColShapeType.RECT } & ColShapeRectangleCreateOptions) - | ({ colShapeType: Enums.ColShapeType.POLYGON } & ColShapePolygonCreateOptions) - ); + | ({ colShapeType: Enums.ColShapeType.SPHERE } & ColShapeSphereCreateOptions) + | ({ colShapeType: Enums.ColShapeType.CYLINDER } & ColShapeCylinderCreateOptions) + | ({ colShapeType: Enums.ColShapeType.CIRCLE } & ColShapeCircleCreateOptions) + | ({ colShapeType: Enums.ColShapeType.CUBOID } & ColShapeCuboidCreateOptions) + | ({ colShapeType: Enums.ColShapeType.RECT } & ColShapeRectangleCreateOptions) + | ({ colShapeType: Enums.ColShapeType.POLYGON } & ColShapePolygonCreateOptions) + ); export abstract class Resource { readonly type: string;