OnChange should invoke after data has been set
Some checks are pending
analysis / Run Luau Analyze (push) Waiting to run
deploy-docs / build (push) Waiting to run
deploy-docs / Deploy (push) Blocked by required conditions
publish-npm / publish (push) Waiting to run
unit-testing / Run Luau Tests (push) Waiting to run

This commit is contained in:
Ukendio 2025-03-30 22:49:11 +02:00
parent 7bcd6bd220
commit 41ebde415f
3 changed files with 18 additions and 13 deletions

View file

@ -18,7 +18,7 @@ The format is based on [Keep a Changelog][kac], and this project adheres to
- Specifically happened when you had at least two pairs of different relations with multiple targets each - Specifically happened when you had at least two pairs of different relations with multiple targets each
- `[hooks]`: - `[hooks]`:
- Replaced `OnSet` with `OnChange` - Replaced `OnSet` with `OnChange`
- The former was used to detect emplace/move actions. Now the behaviour for `OnChange` is that it will run only when the value is about to be changed allowing you to retrieve the old value when needed - The former was used to detect emplace/move actions. Now the behaviour for `OnChange` is that it will run only when the value has changed
- Changed `OnAdd` to specifically run after the data has been set for non-zero-sized components. Also returns the value that the component was set to - Changed `OnAdd` to specifically run after the data has been set for non-zero-sized components. Also returns the value that the component was set to
- This should allow a more lenient window for modifying data - This should allow a more lenient window for modifying data
- Changed `OnRemove` to lazily lookup which archetype the entity will move to - Changed `OnRemove` to lazily lookup which archetype the entity will move to

View file

@ -124,12 +124,9 @@ local EcsOnArchetypeCreate = HI_COMPONENT_ID + 12
local EcsOnArchetypeDelete = HI_COMPONENT_ID + 13 local EcsOnArchetypeDelete = HI_COMPONENT_ID + 13
local EcsRest = HI_COMPONENT_ID + 14 local EcsRest = HI_COMPONENT_ID + 14
local ECS_ID_DELETE = 0b0000_0001 local ECS_ID_DELETE = 0b01
local ECS_ID_IS_TAG = 0b0000_0010 local ECS_ID_IS_TAG = 0b10
local ECS_ID_HAS_ON_ADD = 0b0000_0100 local ECS_ID_MASK = 0b00
local ECS_ID_HAS_ON_SET = 0b0000_1000
local ECS_ID_HAS_ON_REMOVE = 0b0001_0000
local ECS_ID_MASK = 0b0000_0000
local ECS_ENTITY_MASK = bit32.lshift(1, 24) local ECS_ENTITY_MASK = bit32.lshift(1, 24)
local ECS_GENERATION_MASK = bit32.lshift(1, 16) local ECS_GENERATION_MASK = bit32.lshift(1, 16)
@ -930,6 +927,10 @@ local function world_set(world: ecs_world_t, entity: i53, id: i53, data: unknown
local idr_hooks = idr.hooks local idr_hooks = idr.hooks
if from == to then if from == to then
local tr = to.records[id]
local column = from.columns[tr]
column[record.row] = data
-- If the archetypes are the same it can avoid moving the entity -- If the archetypes are the same it can avoid moving the entity
-- and just set the data directly. -- and just set the data directly.
local on_change = idr_hooks.on_change local on_change = idr_hooks.on_change
@ -937,9 +938,6 @@ local function world_set(world: ecs_world_t, entity: i53, id: i53, data: unknown
on_change(entity, data) on_change(entity, data)
end end
local tr = to.records[id]
local column = from.columns[tr]
column[record.row] = data
return return
end end
@ -962,8 +960,6 @@ local function world_set(world: ecs_world_t, entity: i53, id: i53, data: unknown
if on_add then if on_add then
on_add(entity, data) on_add(entity, data)
end end
end end
local function world_component(world: World): i53 local function world_component(world: World): i53

View file

@ -1665,11 +1665,20 @@ TEST("Hooks", function()
local Number = world:component() local Number = world:component()
local e1 = world:entity() local e1 = world:entity()
local call = 0
world:set(Number, jecs.OnChange, function(entity, data) world:set(Number, jecs.OnChange, function(entity, data)
CHECK(e1 == entity) CHECK(e1 == entity)
CHECK(world:get(entity, Number) == nil) if call == 1 then
CHECK(false)
elseif call == 2 then
CHECK(world:get(entity, Number) == data)
end
CHECK(data == 1) CHECK(data == 1)
end) end)
call = 1
world:set(e1, Number, 1)
call = 2
world:set(e1, Number, 1) world:set(e1, Number, 1)
end end