From 6a92d4e3c6ab742d5260c31a99bbfabb7dab4931 Mon Sep 17 00:00:00 2001 From: Ukendio Date: Fri, 25 Apr 2025 22:36:07 +0200 Subject: [PATCH] Add ecs_assert and fix entity range handling --- jecs.luau | 40 +++++++++++++++++++++++----------------- test/tests.luau | 10 +++++++++- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/jecs.luau b/jecs.luau index 8978ea1..c48c6c5 100644 --- a/jecs.luau +++ b/jecs.luau @@ -128,6 +128,12 @@ local ECS_INTERNAL_ERROR = [[ https://github.com/Ukendio/jecs/issues/new?template=BUG-REPORT.md ]] +local function ecs_assert(condition, msg: string?) + if not condition then + error(msg) + end +end + local ecs_metadata: Map> = {} local ecs_max_component_id = 0 local ecs_max_tag_id = EcsRest @@ -287,6 +293,8 @@ local function ecs_get_alive(world, entity) return current end +local ECS_INTERNAL_ERROR_INCOMPATIBLE_ENTITY = "Entity is outside range" + local function entity_index_new_id(entity_index: ecs_entity_index_t): i53 local dense_array = entity_index.dense_array local alive_count = entity_index.alive_count @@ -302,9 +310,8 @@ local function entity_index_new_id(entity_index: ecs_entity_index_t): i53 local id = max_id + 1 local range_end = entity_index.range_end - if range_end then - assert(id < range_end) - end + ecs_assert(range_end == nil or id < range_end, ECS_INTERNAL_ERROR_INCOMPATIBLE_ENTITY) + entity_index.max_id = id alive_count += 1 entity_index.alive_count = alive_count @@ -596,10 +603,10 @@ local function id_record_ensure(world: ecs_world_t, id: number): ecs_id_record_t local is_pair = ECS_IS_PAIR(id) if is_pair then relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id)) :: i53 - assert(relation and entity_index_is_alive( + ecs_assert(relation and entity_index_is_alive( entity_index, relation), ECS_INTERNAL_ERROR) target = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id)) :: i53 - assert(target and entity_index_is_alive( + ecs_assert(target and entity_index_is_alive( entity_index, target), ECS_INTERNAL_ERROR) end @@ -734,9 +741,6 @@ end local function world_range(world: ecs_world_t, range_begin: number, range_end: number?) local entity_index = world.entity_index - if range_end then - range_end += 1 - end entity_index.range_begin = range_begin entity_index.range_end = range_end @@ -753,8 +757,8 @@ local function world_range(world: ecs_world_t, range_begin: number, range_end: n sparse_array[range_begin] = { dense = 0 } :: ecs_record_t end - entity_index.max_id = range_begin - entity_index.alive_count = range_begin + entity_index.max_id = range_begin - 1 + entity_index.alive_count = range_begin - 1 end local function world_entity(world: ecs_world_t, entity: i53?): i53 @@ -762,9 +766,12 @@ local function world_entity(world: ecs_world_t, entity: i53?): i53 if entity then local index = ECS_ID(entity) local range_begin = entity_index.range_begin - if range_begin then - assert(index > range_begin) - end + local range_end = entity_index.range_end + ecs_assert(range_begin == nil or index >= range_begin, + ECS_INTERNAL_ERROR_INCOMPATIBLE_ENTITY) + ecs_assert(range_end == nil or index <= range_end, + ECS_INTERNAL_ERROR_INCOMPATIBLE_ENTITY) + local max_id = entity_index.max_id local sparse_array = entity_index.sparse_array local dense_array = entity_index.dense_array @@ -805,10 +812,6 @@ local function world_entity(world: ecs_world_t, entity: i53?): i53 dense_array[dense] = e_swap return any else - local range_end = entity_index.range_end - if range_end then - assert(index < range_end) - end for i = max_id + 1, index do sparse_array[i] = { dense = i } :: ecs_record_t dense_array[i] = i @@ -2572,6 +2575,9 @@ export type World = { observable: any, + --- Enforce a check on entities to be created within desired range + range: (self: World, range_begin: number, range_end: number?) -> (), + --- Creates a new entity entity: (self: World, id: Entity?) -> Entity, --- Creates a new entity located in the first 256 ids. diff --git a/test/tests.luau b/test/tests.luau index af2f700..b9cdfce 100644 --- a/test/tests.luau +++ b/test/tests.luau @@ -633,11 +633,13 @@ TEST("world:each()", function() end end) -TEST("world:entity()", function() +TEST("world:range()", function() do CASE "range" local world = jecs.world() world = lifetime_tracker_add(world, {}) world:range(1000, 2000) + local e = world:entity() + CHECK(e == 1000) world:entity(1590) CHECK_EXPECT_ERR(function() @@ -650,7 +652,13 @@ TEST("world:entity()", function() CHECK(not world:contains(591)) CHECK(not world:contains(5000)) CHECK(not world:contains(988)) + + local e = world:entity(2000) + CHECK(e == 2000) end +end) + +TEST("world:entity()", function() do CASE "desired id" local world = jecs.world() local id = world:entity()