-IDManager reserve EntityID(0) as empty

-fixed bug with events called on destroyed entities (crash)
-don't call event on system for unsupported entity
-added "entity_id" property to EntitiesData
This commit is contained in:
Mergul 2020-03-06 10:12:52 +01:00
parent 87e9a31d7f
commit 5399b584dd
3 changed files with 44 additions and 10 deletions

View file

@ -136,7 +136,9 @@ begin:
*/ */
export bool isExist(EntityID id) nothrow @nogc export bool isExist(EntityID id) nothrow @nogc
{ {
if(id.id >= m_ids_array.length)return false;
Data* data = &m_ids_array[id.id]; Data* data = &m_ids_array[id.id];
if(data.entity is null)return false;
return data.counter == id.counter; return data.counter == id.counter;
} }
@ -151,6 +153,9 @@ begin:
add_mutex = Mallocator.make!Mutex(); add_mutex = Mallocator.make!Mutex();
add_mutex.initialize(); add_mutex.initialize();
getNewID();
optimize();
} }
void deinitialize() @trusted @nogc nothrow void deinitialize() @trusted @nogc nothrow
@ -243,23 +248,31 @@ private:
unittest unittest
{ {
IDManager manager; IDManager manager;
manager.initialize();
EntityID id1 = manager.getNewID(); EntityID id1 = manager.getNewID();
EntityID id2 = manager.getNewID(); EntityID id2 = manager.getNewID();
EntityID id3 = manager.getNewID(); EntityID id3 = manager.getNewID();
assert(id1 == EntityID(0, 1)); assert(id1 == EntityID(1, 0));
assert(id2 == EntityID(1, 1)); assert(id2 == EntityID(2, 0));
assert(id3 == EntityID(2, 1)); assert(id3 == EntityID(3, 0));
manager.optimize();
manager.releaseID(id2); manager.releaseID(id2);
manager.releaseID(id1); manager.releaseID(id1);
id2 = manager.getNewID(); id2 = manager.getNewID();
id1 = manager.getNewID(); id1 = manager.getNewID();
assert(id1 == EntityID(1, 2)); Entity e;
assert(id2 == EntityID(0, 2)); e.id = id3;
assert(id3 == EntityID(2, 1)); manager.update(e);
assert(id1 == EntityID(2, 1));
assert(id2 == EntityID(1, 1));
assert(id3 == EntityID(3, 0));
assert(manager.isExist(id3)); assert(manager.isExist(id3));
assert(!manager.isExist(EntityID(0, 1))); assert(!manager.isExist(EntityID(1, 0)));
assert(!manager.isExist(EntityID(0, 0)));
manager.deinitialize();
} }

View file

@ -542,7 +542,7 @@ export struct EntityManager
foreach (member; __traits(allMembers, Sys.EntitiesData)) foreach (member; __traits(allMembers, Sys.EntitiesData))
{ {
alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member)); alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member));
if (member == "length" || is(MemberType == Entity[]) if (member == "length" || member == "thread_id" || is(MemberType == Entity[])
|| is(MemberType == const(Entity)[])) || is(MemberType == const(Entity)[]))
{ {
if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[])) if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
@ -648,6 +648,13 @@ export struct EntityManager
static assert(MemberType.sizeof > 1, static assert(MemberType.sizeof > 1,
"EntitiesData 'length' member can't be byte or ubyte."); "EntitiesData 'length' member can't be byte or ubyte.");
} }
else static if(member == "thread_id")
{
static assert(isIntegral!(MemberType),
"EntitiesData 'thread_id' member must be integral type.");
static assert(MemberType.sizeof > 1,
"EntitiesData 'thread_id' member can't be byte or ubyte.");
}
else static if (!(isArray!(MemberType))) else static if (!(isArray!(MemberType)))
static assert(0, "EntitiesData members should be arrays of elements!"); static assert(0, "EntitiesData members should be arrays of elements!");
} }
@ -703,6 +710,11 @@ export struct EntityManager
{ {
input_data.length = cast(typeof(input_data.length))(entities_count - offset); input_data.length = cast(typeof(input_data.length))(entities_count - offset);
} }
static if (hasMember!(Sys.EntitiesData, "thread_id"))
{
input_data.thread_id = cast(typeof(input_data.thread_id))threadID();
}
static foreach (iii, comp_info; components_info.req) static foreach (iii, comp_info; components_info.req)
{ {
@ -2378,9 +2390,9 @@ export struct EntityManager
{ {
EventCallData call_data; EventCallData call_data;
void* event_pointer = cast(void*) block + event.data_offset; void* event_pointer = cast(void*) block + event.data_offset;
call_data.event = event_pointer;
foreach (j; 0 .. block.count) foreach (j; 0 .. block.count)
{ {
call_data.event = event_pointer;
EntityID entity_id = *cast(EntityID*) event_pointer; EntityID entity_id = *cast(EntityID*) event_pointer;
Entity* entity = id_manager.getEntityPointer(entity_id); Entity* entity = id_manager.getEntityPointer(entity_id);
if (entity) if (entity)
@ -2390,6 +2402,7 @@ export struct EntityManager
foreach (caller; events[i].callers) foreach (caller; events[i].callers)
{ {
if(call_data.block.type_info.systems[caller.system.m_id] == false)continue;
call_data.system_pointer = caller.system.m_system_pointer; call_data.system_pointer = caller.system.m_system_pointer;
(cast(void function( (cast(void function(
ref EventCallData) nothrow @nogc) caller.callback)( ref EventCallData) nothrow @nogc) caller.callback)(
@ -2412,9 +2425,9 @@ export struct EntityManager
{ {
id_manager.optimize(); id_manager.optimize();
updateBlocks(); updateBlocks();
removeEntities();
changeEntities(); changeEntities();
updateEvents(); updateEvents();
removeEntities();
event_manager.clearEvents(); event_manager.clearEvents();
} }

View file

@ -515,6 +515,14 @@ struct ExternalUpdateCallTest
} }
} }
version(unittest)
{
void main()
{
}
}
else:
extern(C) int main() extern(C) int main()
{ {