module: remove archetypeByID, improve "entity does not exist" error cases

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-05-24 13:42:29 -07:00
parent f4f89af8b9
commit aa0ec4ba5e

View file

@ -271,10 +271,14 @@ pub fn Database(comptime modules: anytype) type {
} }
/// Removes an entity. /// Removes an entity.
///
/// Panics if the entity does not exist.
pub fn remove(entities: *Self, entity: EntityID) !void { pub fn remove(entities: *Self, entity: EntityID) !void {
if (entities.active_queries.items.len > 0) return entities.removeDeferred(entity); if (entities.active_queries.items.len > 0) return entities.removeDeferred(entity);
var archetype = entities.archetypeByID(entity); const ptr = entities.entities.get(entity) orelse std.debug.panic("cannot remove entity {}: entity does not exist", .{
const ptr = entities.entities.get(entity).?; entity,
});
const archetype = &entities.archetypes.items[ptr.archetype_index];
// A swap removal will be performed, update the entity stored in the last row of the // A swap removal will be performed, update the entity stored in the last row of the
// archetype table to point to the row the entity we are removing is currently located. // archetype table to point to the row the entity we are removing is currently located.
@ -309,12 +313,6 @@ pub fn Database(comptime modules: anytype) type {
return entities.componentNameString(@tagName(module_name) ++ "." ++ @tagName(component_name)); return entities.componentNameString(@tagName(module_name) ++ "." ++ @tagName(component_name));
} }
/// Returns the archetype storage for the given entity.
pub inline fn archetypeByID(entities: *Self, entity: EntityID) *Archetype {
const ptr = entities.entities.get(entity).?;
return &entities.archetypes.items[ptr.archetype_index];
}
/// Sets the named component to the specified value for the given entity, /// Sets the named component to the specified value for the given entity,
/// moving the entity from it's current archetype table to the new archetype /// moving the entity from it's current archetype table to the new archetype
/// table if required. /// table if required.
@ -373,6 +371,8 @@ pub fn Database(comptime modules: anytype) type {
/// moving the entity from it's current archetype table to the new archetype /// moving the entity from it's current archetype table to the new archetype
/// table if required. /// table if required.
/// ///
/// Panics if the entity does not exist.
///
/// For tags, set component.len = 0 and alignment = 1 /// For tags, set component.len = 0 and alignment = 1
pub fn setComponentDynamic( pub fn setComponentDynamic(
entities: *Self, entities: *Self,
@ -390,7 +390,11 @@ pub fn Database(comptime modules: anytype) type {
type_id, type_id,
); );
const prev_archetype_idx = entities.entities.get(entity).?.archetype_index; const prev_ptr = entities.entities.get(entity) orelse std.debug.panic("cannot set component {s}: entity={} does not exist", .{
entities.component_names.string(name_id),
entity,
});
const prev_archetype_idx = prev_ptr.archetype_index;
var prev_archetype = &entities.archetypes.items[prev_archetype_idx]; var prev_archetype = &entities.archetypes.items[prev_archetype_idx];
var archetype: ?*Archetype = if (prev_archetype.hasComponent(name_id)) prev_archetype else null; var archetype: ?*Archetype = if (prev_archetype.hasComponent(name_id)) prev_archetype else null;
var archetype_idx: ?u32 = if (archetype != null) prev_archetype_idx else null; var archetype_idx: ?u32 = if (archetype != null) prev_archetype_idx else null;
@ -483,6 +487,8 @@ pub fn Database(comptime modules: anytype) type {
/// Gets the named component of the given type. /// Gets the named component of the given type.
/// Returns null if the component does not exist on the entity. /// Returns null if the component does not exist on the entity.
///
/// Panics if the entity does not exist.
pub fn getComponent( pub fn getComponent(
entities: *Self, entities: *Self,
entity: EntityID, entity: EntityID,
@ -502,8 +508,11 @@ pub fn Database(comptime modules: anytype) type {
const name_str = @tagName(namespace_name) ++ "." ++ @tagName(component_name); const name_str = @tagName(namespace_name) ++ "." ++ @tagName(component_name);
const name_id = entities.component_names.index(name_str) orelse return null; const name_id = entities.component_names.index(name_str) orelse return null;
var archetype = entities.archetypeByID(entity); const ptr = entities.entities.get(entity) orelse std.debug.panic("cannot get component {s}: entity={} does not exist", .{
const ptr = entities.entities.get(entity).?; entities.component_names.string(name_id),
entity,
});
const archetype = &entities.archetypes.items[ptr.archetype_index];
return archetype.get(ptr.row_index, name_id, Component); return archetype.get(ptr.row_index, name_id, Component);
} }
@ -511,6 +520,8 @@ pub fn Database(comptime modules: anytype) type {
/// Gets the named component of the given type. /// Gets the named component of the given type.
/// Returns null if the component does not exist on the entity. /// Returns null if the component does not exist on the entity.
/// ///
/// Panics if the entity does not exist.
///
/// For tags, set size = 0 and alignment = 1 /// For tags, set size = 0 and alignment = 1
pub fn getComponentDynamic( pub fn getComponentDynamic(
entities: *Self, entities: *Self,
@ -520,8 +531,11 @@ pub fn Database(comptime modules: anytype) type {
alignment: u16, alignment: u16,
type_id: u32, type_id: u32,
) ?[]u8 { ) ?[]u8 {
var archetype = entities.archetypeByID(entity); const ptr = entities.entities.get(entity) orelse std.debug.panic("cannot get component {s}: entity={} does not exist", .{
const ptr = entities.entities.get(entity).?; entities.component_names.string(name_id),
entity,
});
const archetype = &entities.archetypes.items[ptr.archetype_index];
return archetype.getDynamic(ptr.row_index, name_id, size, alignment, type_id); return archetype.getDynamic(ptr.row_index, name_id, size, alignment, type_id);
} }
@ -546,13 +560,20 @@ pub fn Database(comptime modules: anytype) type {
} }
/// Removes the named component from the entity, or noop if it doesn't have such a component. /// Removes the named component from the entity, or noop if it doesn't have such a component.
///
/// Panics if the entity does not exist.
pub fn removeComponentDynamic( pub fn removeComponentDynamic(
entities: *Self, entities: *Self,
entity: EntityID, entity: EntityID,
name_id: StringTable.Index, name_id: StringTable.Index,
) !void { ) !void {
if (entities.active_queries.items.len > 0) return entities.removeComponentDeferred(entity, name_id); if (entities.active_queries.items.len > 0) return entities.removeComponentDeferred(entity, name_id);
const prev_archetype_idx = entities.entities.get(entity).?.archetype_index;
const prev_ptr = entities.entities.get(entity) orelse std.debug.panic("cannot remove component {s}: entity={} does not exist", .{
entities.component_names.string(name_id),
entity,
});
const prev_archetype_idx = prev_ptr.archetype_index;
var prev_archetype = &entities.archetypes.items[prev_archetype_idx]; var prev_archetype = &entities.archetypes.items[prev_archetype_idx];
var archetype: ?*Archetype = if (prev_archetype.hasComponent(name_id)) prev_archetype else return; var archetype: ?*Archetype = if (prev_archetype.hasComponent(name_id)) prev_archetype else return;
var archetype_idx: u32 = if (archetype != null) prev_archetype_idx else 0; var archetype_idx: u32 = if (archetype != null) prev_archetype_idx else 0;
@ -1014,7 +1035,8 @@ test "example" {
try testing.expectEqual(@as(usize, 0), archetypes[5].len); try testing.expectEqual(@as(usize, 0), archetypes[5].len);
// Resolve archetype by entity ID and print column names // Resolve archetype by entity ID and print column names
const columns = world.archetypeByID(player2).columns; const archetype = &world.archetypes.items[world.entities.get(player2).?.archetype_index];
const columns = archetype.columns;
try testing.expectEqual(@as(usize, 2), columns.len); try testing.expectEqual(@as(usize, 2), columns.len);
try testing.expectEqualStrings("entities.id", world.component_names.string(columns[0].name)); try testing.expectEqualStrings("entities.id", world.component_names.string(columns[0].name));
try testing.expectEqualStrings("game.rotation", world.component_names.string(columns[1].name)); try testing.expectEqualStrings("game.rotation", world.component_names.string(columns[1].name));