{"version":3,"sources":["../src/mask.ts","../src/component.ts"],"sourcesContent":["import { Component } from './component';\n\nexport class Mask {\n    private _mask: Uint32Array;\n    private _enabled = false;\n\n    constructor(size = Component.maxId) {\n        // Uint32Array holds 32 bits for every unit of size, so we need the no. of components\n        // divided by 32 to mask all components\n        this._mask = new Uint32Array(Math.ceil(size / 32));\n    }\n\n    enable(): void {\n        this._enabled = true;\n    }\n\n    get enabled(): boolean {\n        return this._enabled;\n    }\n\n    get mask(): Uint32Array {\n        return this._mask;\n    }\n\n    get empty(): boolean {\n        return this._mask.every((m) => m === 0);\n    }\n\n    /**\n     * Checks another mask to see it is fulfilled by the flags in this mask\n     * @param otherMask Uint32Array to be compared with this mask\n     * @returns True if the provided mask is satisfied by this mask\n     */\n    public fulfills = (otherMask: Mask): boolean => {\n        if (otherMask.mask.length !== this._mask.length) {\n            throw new Error('Comparing masks of different sizes not allowed.');\n        }\n        return this._mask.every((m, index) =>\n            this.checkMask(m, otherMask.mask[index])\n        );\n    };\n\n    /**\n     * Checks another mask to see it contains all flags in this mask\n     * @param otherMask Uint32Array to be compared with this mask\n     * @returns True if the provided mask is satisfied by this mask\n     */\n    public fulfilledBy = (otherMask: Mask): boolean => {\n        if (otherMask.mask.length !== this._mask.length) {\n            throw new Error('Comparing masks of different sizes not allowed.');\n        }\n        return this._mask.every((m, index) =>\n            this.checkMask(otherMask.mask[index], m)\n        );\n    };\n\n    /**\n     * @param checkingMask The mask that needs to be met to fulfill the condition\n     * @param requiredMask The other mask that needs to match up with the first mask\n     * @returns Whether the masks match or not\n     */\n    private checkMask = (\n        checkingMask: number,\n        requiredMask: number\n    ): boolean => {\n        return (\n            (checkingMask & requiredMask) >>> 0 === requiredMask ||\n            checkingMask === requiredMask // second condition checking if they're both 0\n        );\n    };\n\n    /**\n     * Flips all bits in the mask to 1\n     */\n    flipAllToOne = () => {\n        this._mask.fill(~0 >>> 0);\n    };\n\n    /**\n     * Flip on a flag in this mask\n     * @param bitPosition The bit flag to flip, typically a componentId.\n     */\n    flipOn = (bitPosition: number) => {\n        this._mask[Math.floor(bitPosition / 32)] |=\n            (1 << bitPosition % 32) >>> 0;\n    };\n\n    /**\n     * Flip off a flag on this mask\n     * @param bitPosition The bit flag to flip, typically a componentId.\n     */\n    flipOff = (bitPosition: number) => {\n        this._mask[Math.floor(bitPosition / 32)] &= ~(\n            (1 << bitPosition % 32) >>>\n            0\n        );\n    };\n\n    toString(): string {\n        const decToBin = (dec: number) => {\n            return (dec >>> 0).toString(2);\n        };\n        let string = '|';\n        for (const mask of this.mask) {\n            const stringMask = decToBin(mask);\n            string += stringMask.padEnd(32, '0');\n            string += '|';\n        }\n        return string;\n    }\n\n    get maskString() {\n        return this.toString();\n    }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Entity } from './entity';\nimport { pendingFields, pendingInitializers } from './decorators';\n\nexport type ComponentId = number;\nexport type ComponentName = string;\nexport type ComponentField = {\n    fieldName: string;\n    defaultValue?: unknown;\n};\n\n/**\n * Component that can be attached to entities.\n */\nexport abstract class Component {\n    /**\n     * Bitflag id assigned to a component class at registration time.\n     * Keyed by the class reference itself, not by class name, so the ECS\n     * survives identifier mangling by minifiers and obfuscators.\n     */\n    static ComponentIdMap: Map<ComponentConstructor, ComponentId> = new Map();\n\n    static ComponentFieldMap: Map<\n        ComponentConstructor,\n        Map<string, ComponentField>\n    > = new Map();\n\n    static ComponentFieldInitializeMap: Map<\n        ComponentConstructor,\n        Map<string, Array<string>>\n    > = new Map();\n\n    static maxId = 0;\n\n    declare componentId: ComponentId;\n\n    private declare entity: Entity;\n\n    setValues(values: Record<string, any>): void {\n        const ctor = this.constructor as ComponentConstructor;\n        const fields = Component.ComponentFieldMap.get(ctor);\n        const initializers = Component.ComponentFieldInitializeMap.get(ctor);\n\n        if (!fields) {\n            return;\n        }\n\n        fields.forEach(({ fieldName }) => {\n            if (typeof values[fieldName] === 'undefined') {\n                throw new Error(\n                    `Value not provided for ${fieldName} on component ${this.constructor.name}.`\n                );\n            } else {\n                (this as any)[fieldName] = values[fieldName];\n\n                if (initializers && initializers.has(fieldName)) {\n                    initializers.get(fieldName)?.forEach((otherField) => {\n                        (this as any)[otherField] = values[fieldName];\n                    });\n                }\n            }\n        });\n    }\n    setEntity(entity: Entity): void {\n        this.entity = entity;\n    }\n\n    getEntity(): Entity {\n        if (!this.entity) {\n            throw new Error(\n                \"Component tried to fetch it's entity, but none was found\"\n            );\n        }\n        return this.entity;\n    }\n\n    onComponentRemoved() {\n        // no-op\n    }\n\n    toString(): string {\n        return `${this.constructor.name}`;\n    }\n}\n\ntype NonFunctionPropertyNames<T> = {\n    // eslint-disable-next-line @typescript-eslint/ban-types\n    [K in keyof T]: T[K] extends Function ? never : K;\n}[keyof T];\n\nexport type ComponentArgs<C> = {\n    [Property in Exclude<\n        NonFunctionPropertyNames<C>,\n        keyof Component\n    >]: C[Property];\n};\nexport type ComponentConstructor = { new (...args: any[]): Component };\n\nexport const registerComponentWithSpecificId = <T extends ComponentConstructor>(\n    constructor: T,\n    id: number\n) => {\n    registerComponent(constructor, id);\n};\n\nexport function RegisterComponent<T extends ComponentConstructor>(\n    value: T,\n    _context: ClassDecoratorContext\n): void {\n    Component.maxId++;\n    const newComponentId = Component.maxId;\n    registerComponent(value, newComponentId);\n\n    const fields = pendingFields.splice(0);\n    const fieldMap = Component.ComponentFieldMap.get(value);\n    if (fieldMap) {\n        for (const f of fields) {\n            fieldMap.set(f.fieldName, f);\n        }\n    }\n\n    const initializers = pendingInitializers.splice(0);\n    if (initializers.length > 0) {\n        let initMap = Component.ComponentFieldInitializeMap.get(value);\n        if (!initMap) {\n            initMap = new Map();\n            Component.ComponentFieldInitializeMap.set(value, initMap);\n        }\n        for (const init of initializers) {\n            if (!initMap.has(init.initFrom)) {\n                initMap.set(init.initFrom, []);\n            }\n            initMap.get(init.initFrom)?.push(init.field);\n        }\n    }\n}\n\nconst registerComponent = (\n    constructor: ComponentConstructor,\n    newComponentId: number\n) => {\n    constructor.prototype.componentId = newComponentId;\n    Component.ComponentIdMap.set(constructor, newComponentId);\n\n    if (!Component.ComponentFieldMap.has(constructor)) {\n        Component.ComponentFieldMap.set(constructor, new Map());\n    }\n};\n"],"mappings":"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","names":[]}