diff --git a/packages/ecs/src/world.js b/packages/ecs/src/world.js index 58e23f23..0a39d840 100644 --- a/packages/ecs/src/world.js +++ b/packages/ecs/src/world.js @@ -366,15 +366,38 @@ export class World { return this.getResourceByTypeId(typeid(resourceType)) } + /** + * @template T + * @param {Constructor} resourceType + * @returns {T | undefined} + */ + getOptionalResource(resourceType) { + return this.getOptionalResourceByTypeId(typeid(resourceType)) + } + /** * @template T * @param {TypeId} id * @returns {T} */ getResourceByTypeId(id) { + const resource = this.getOptionalResourceByTypeId(id) + + assert(resource, `The resource or resource alias \`${id}\` is non existent.`) + + // SAFETY: The typeid should match the type, caller's responsibility + return /** @type {T}*/(resource) + } + + /** + * @template T + * @param {TypeId} id + * @returns {T | undefined} + */ + getOptionalResourceByTypeId(id) { const resource = this.resources.get(id) - if (resource) { + if (resource !== undefined) { // SAFETY: The typeid should match the type, caller's responsibility return /** @type {T}*/(resource) @@ -382,11 +405,11 @@ export class World { const aliasedid = this.resourceAliases.get(id) - assert(aliasedid, `The resource or resource alias \`${id}\` is non existent.`) + if (aliasedid === undefined) return undefined const aliasedResource = this.resources.get(aliasedid) - assert(aliasedResource, `The resource alias \`${id}\` points to a non-existent resource \`${aliasedid}\`.`) + if (aliasedResource === undefined) return undefined // SAFETY: The aliased typeid should match the type, caller's responsibility return /** @type {T}*/(aliasedResource) diff --git a/packages/ecs/tests/world.test.js b/packages/ecs/tests/world.test.js index 8777b8d8..1da09efc 100644 --- a/packages/ecs/tests/world.test.js +++ b/packages/ecs/tests/world.test.js @@ -1,5 +1,5 @@ import { test, describe } from "vitest"; -import { deepStrictEqual, throws } from "node:assert"; +import { deepStrictEqual, strictEqual, throws } from "node:assert"; import { World } from "../src"; import { typeid } from "@wimaengine/type"; import { EntityHandle } from "../src/entities"; @@ -109,6 +109,30 @@ describe("Testing `World`", () => { deepStrictEqual(resource, new TestResource()) }) + test('Get optional correct resource on world.', () => { + const world = new World() + world.setResource(new TestResource()) + const resource = world.getOptionalResource(TestResource) + + deepStrictEqual(resource, new TestResource()) + }) + + test('Optional resource lookup on world returns aliased resources.', () => { + const world = new World() + world.setResource(new TestResource()) + world.setResourceAlias(typeid(TestResource), TestAlias) + const resource = world.getOptionalResource(TestAlias) + + deepStrictEqual(resource, new TestResource()) + }) + + test('Optional resource lookup on world returns undefined when missing.', () => { + const world = new World() + + strictEqual(world.getOptionalResource(TestResource), undefined) + strictEqual(world.getOptionalResource(TestAlias), undefined) + }) + test('World has resource.', () => { const world = new World() world.setResource(new TestResource())