From 71569bba6042cdb97b217e569932120fb1fc6f66 Mon Sep 17 00:00:00 2001 From: Conz Date: Sat, 10 Aug 2024 20:30:58 -0500 Subject: [PATCH] component Hooks (#98) Co-authored-by: Marcus --- src/init.luau | 68 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/src/init.luau b/src/init.luau index d8d3720..e82d00c 100644 --- a/src/init.luau +++ b/src/init.luau @@ -465,6 +465,61 @@ local function archetype_traverse_add(world: World, id: i53, from: Archetype): A return add end +local world_get: (world: World, entityId: i53, a: i53, b: i53?, c: i53?, d: i53?, e: i53?) -> (...any) + do + -- Keeping the function as small as possible to enable inlining + local records + local columns + local row + + local function fetch(id): any + local tr = records[id] + + if not tr then + return nil + end + + return columns[tr.column][row] + end + + function world_get(world: World, entity: i53, a: i53, b: i53?, c: i53?, d: i53?, e: i53?): ...any + local record = world.entityIndex.sparse[entity] + if not record then + return nil + end + + local archetype = record.archetype + if not archetype then + return nil + end + + records = archetype.records + columns = archetype.columns + row = record.row + + local va = fetch(a) + + if not b then + return va + elseif not c then + return va, fetch(b) + elseif not d then + return va, fetch(b), fetch(c) + elseif not e then + return va, fetch(b), fetch(c), fetch(d) + else + error("args exceeded") + end + end + end + +local function invoke_hook(world: World, hook_id: number, id: i53, entity: i53, data: any?) + local hook = world_get(world, id, hook_id) + if hook then + hook(entity, data) + end +end + local function world_add(world: World, entity: i53, id: i53) local entityIndex = world.entityIndex local record = entityIndex.sparse[entity] @@ -480,6 +535,8 @@ local function world_add(world: World, entity: i53, id: i53) new_entity(entity, record, to) end end + + invoke_hook(world, EcsOnAdd, id, entity) end -- Symmetric like `World.add` but idempotent @@ -493,7 +550,7 @@ local function world_set(world: World, entity: i53, id: i53, data: unknown) -- and just set the data directly. local tr = to.records[id] from.columns[tr.column][record.row] = data - -- Should fire an OnSet event here. + invoke_hook(world, EcsOnSet, id, entity, data) return end @@ -509,6 +566,8 @@ local function world_set(world: World, entity: i53, id: i53, data: unknown) local tr = to.records[id] to.columns[tr.column][record.row] = data + + invoke_hook(world, EcsOnAdd, id, entity, data) end local function world_component(world: World): i53 @@ -544,6 +603,8 @@ local function archetype_traverse_remove(world: World, id: i53, from: Archetype) end local function world_remove(world: World, entity: i53, id: i53) + invoke_hook(world, EcsOnRemove, id, entity) + local entity_index = world.entityIndex local record = entity_index.sparse[entity] local from = record.archetype @@ -641,7 +702,6 @@ local function world_clear(world: World, entity: i53) entity_move(world.entityIndex, entity, record, ROOT_ARCHETYPE) end - type CompatibleArchetype = { archetype: Archetype, indices: { number } } local noop: Item = function() @@ -1172,9 +1232,6 @@ function World.new() dense = {} :: { [i24]: i53 }, sparse = {} :: { [i53]: Record }, } :: EntityIndex, - hooks = { - [EcsOnAdd] = {}, - }, nextArchetypeId = 0, nextComponentId = 0, nextEntityId = 0, @@ -1247,6 +1304,7 @@ export type World = { & ((World, Entity, Entity, Entity, Entity, Entity, Entity, Entity, Entity) -> Query) } + return { World = World ,