Bugfix update
-fixed critical bug with adding entities -fixed small bug with adding entity with replacement components which entity hasn't -added multiple asserts to faster bug detection in future
This commit is contained in:
parent
3719cdaee0
commit
7a0ddf7494
1 changed files with 93 additions and 43 deletions
|
|
@ -2154,6 +2154,8 @@ export struct EntityManager
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
||||||
|
updateEntityInfoBlocks(new_info);
|
||||||
|
assert(new_block.added_count == 0);
|
||||||
|
|
||||||
void* start = new_block.dataBegin() + new_block.entities_count * EntityID.sizeof;
|
void* start = new_block.dataBegin() + new_block.entities_count * EntityID.sizeof;
|
||||||
|
|
||||||
|
|
@ -2183,6 +2185,10 @@ export struct EntityManager
|
||||||
cast(void*) block + info.deltas[comp] + ind * comp_size, comp_size);
|
cast(void*) block + info.deltas[comp] + ind * comp_size, comp_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_block.entities_count++;
|
||||||
|
if (new_block != new_info.update_block)
|
||||||
|
new_info.update_block = new_block;
|
||||||
|
|
||||||
if (new_info.add_listeners)
|
if (new_info.add_listeners)
|
||||||
{
|
{
|
||||||
foreach (listener; new_info.add_listeners)
|
foreach (listener; new_info.add_listeners)
|
||||||
|
|
@ -2190,7 +2196,7 @@ export struct EntityManager
|
||||||
if (!info.systems[listener])
|
if (!info.systems[listener])
|
||||||
{
|
{
|
||||||
callAddEntityListener(&systems[listener], new_info, new_block,
|
callAddEntityListener(&systems[listener], new_info, new_block,
|
||||||
new_block.entities_count, new_block.entities_count + 1);
|
new_block.entities_count - 1, new_block.entities_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2202,13 +2208,11 @@ export struct EntityManager
|
||||||
if (info.systems[listener])
|
if (info.systems[listener])
|
||||||
{
|
{
|
||||||
callChangeEntityListener(&systems[listener], new_info, new_block,
|
callChangeEntityListener(&systems[listener], new_info, new_block,
|
||||||
new_block.entities_count, new_block.entities_count + 1, del_ids);
|
new_block.entities_count - 1, new_block.entities_count, del_ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_block.entities_count++;
|
|
||||||
|
|
||||||
removeEntityNoID(entity, block);
|
removeEntityNoID(entity, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2291,12 +2295,14 @@ export struct EntityManager
|
||||||
//EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
|
//EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
|
||||||
|
|
||||||
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
||||||
|
updateEntityInfoBlocks(new_info);
|
||||||
|
assert(new_block.added_count == 0);
|
||||||
|
|
||||||
void* start = new_block.dataBegin() + new_block.entities_count * EntityID.sizeof;
|
void* start = new_block.dataBegin() + new_block.entities_count * EntityID.sizeof;
|
||||||
|
|
||||||
Entity* new_entity = cast(Entity*) start;
|
Entity* new_entity = cast(Entity*) start;
|
||||||
new_entity.id = entity.id;
|
new_entity.id = entity.id;
|
||||||
id_manager.update(*new_entity); //new_entity.updateID();
|
id_manager.update(*new_entity);
|
||||||
|
|
||||||
uint j = 0;
|
uint j = 0;
|
||||||
uint k = 0;
|
uint k = 0;
|
||||||
|
|
@ -2342,6 +2348,10 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_block.entities_count++;
|
||||||
|
if (new_block != new_info.update_block)
|
||||||
|
new_info.update_block = new_block;
|
||||||
|
|
||||||
if (new_info.add_listeners)
|
if (new_info.add_listeners)
|
||||||
{
|
{
|
||||||
foreach (listener; new_info.add_listeners)
|
foreach (listener; new_info.add_listeners)
|
||||||
|
|
@ -2349,7 +2359,7 @@ export struct EntityManager
|
||||||
if (!info.systems[listener])
|
if (!info.systems[listener])
|
||||||
{
|
{
|
||||||
callAddEntityListener(&systems[listener], new_info, new_block,
|
callAddEntityListener(&systems[listener], new_info, new_block,
|
||||||
new_block.entities_count, new_block.entities_count + 1);
|
new_block.entities_count - 1, new_block.entities_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2361,12 +2371,11 @@ export struct EntityManager
|
||||||
if (info.systems[listener])
|
if (info.systems[listener])
|
||||||
{
|
{
|
||||||
callChangeEntityListener(&systems[listener], new_info, new_block,
|
callChangeEntityListener(&systems[listener], new_info, new_block,
|
||||||
new_block.entities_count, new_block.entities_count + 1, new_ids);
|
new_block.entities_count - 1, new_block.entities_count, new_ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_block.entities_count++;
|
|
||||||
removeEntityNoID(entity, block);
|
removeEntityNoID(entity, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2487,14 +2496,12 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_index == 1)
|
if (new_index == 1 && info.update_block == block)
|
||||||
threads[threadID].blockToUpdate.add(new_block);
|
threads[threadID].infosToUpdate.add(info);
|
||||||
|
|
||||||
Entity* new_entity = cast(Entity*) start;
|
Entity* new_entity = cast(Entity*) start;
|
||||||
//add_mutex.lock_nothrow();
|
|
||||||
new_entity.id = id_manager.getNewID();
|
new_entity.id = id_manager.getNewID();
|
||||||
//add_mutex.unlock_nothrow();
|
id_manager.update(*new_entity);
|
||||||
id_manager.update(*new_entity); //new_entity.updateID();
|
|
||||||
|
|
||||||
return new_entity;
|
return new_entity;
|
||||||
}
|
}
|
||||||
|
|
@ -2538,12 +2545,10 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 1)
|
if (index == 1)
|
||||||
threads[threadID].blockToUpdate.add(block);
|
threads[threadID].infosToUpdate.add(block);
|
||||||
|
|
||||||
Entity* entity = cast(Entity*) start;
|
Entity* entity = cast(Entity*) start;
|
||||||
//add_mutex.lock_nothrow();
|
|
||||||
entity.id = id_manager.getNewID();
|
entity.id = id_manager.getNewID();
|
||||||
//add_mutex.unlock_nothrow();
|
|
||||||
id_manager.update(*entity); //entity.updateID();
|
id_manager.update(*entity); //entity.updateID();
|
||||||
|
|
||||||
return entity;*/
|
return entity;*/
|
||||||
|
|
@ -2589,7 +2594,7 @@ export struct EntityManager
|
||||||
if (comp.component_id < info.deltas.length)
|
if (comp.component_id < info.deltas.length)
|
||||||
{
|
{
|
||||||
ushort delta = info.deltas[comp.component_id];
|
ushort delta = info.deltas[comp.component_id];
|
||||||
if (delta != ushort.max)
|
if (delta != 0)
|
||||||
{
|
{
|
||||||
uint size = components[comp.component_id].size;
|
uint size = components[comp.component_id].size;
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
|
|
@ -2607,14 +2612,12 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 1)
|
if (index == 1 && info.update_block == block)
|
||||||
threads[threadID].blockToUpdate.add(block);
|
threads[threadID].infosToUpdate.add(info);
|
||||||
|
|
||||||
Entity* entity = cast(Entity*) start;
|
Entity* entity = cast(Entity*) start;
|
||||||
//add_mutex.lock_nothrow();
|
|
||||||
entity.id = id_manager.getNewID();
|
entity.id = id_manager.getNewID();
|
||||||
//add_mutex.unlock_nothrow();
|
id_manager.update(*entity);
|
||||||
id_manager.update(*entity); //entity.updateID();
|
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
@ -2633,6 +2636,7 @@ export struct EntityManager
|
||||||
block.id = 0;
|
block.id = 0;
|
||||||
info.first_block = block;
|
info.first_block = block;
|
||||||
info.last_block = block;
|
info.last_block = block;
|
||||||
|
info.update_block = block;
|
||||||
}
|
}
|
||||||
else if (block.entities_count >= info.max_entities)
|
else if (block.entities_count >= info.max_entities)
|
||||||
{
|
{
|
||||||
|
|
@ -2643,6 +2647,12 @@ export struct EntityManager
|
||||||
new_block.id = cast(ushort)(block.id + 1);
|
new_block.id = cast(ushort)(block.id + 1);
|
||||||
block = new_block;
|
block = new_block;
|
||||||
info.last_block = block;
|
info.last_block = block;
|
||||||
|
///make sure that update_block point to unfilled block
|
||||||
|
if (info.update_block.entities_count == info.max_entities)
|
||||||
|
{
|
||||||
|
assert(!info.update_block.added_count);
|
||||||
|
info.update_block = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
@ -2668,8 +2678,9 @@ export struct EntityManager
|
||||||
block.id = 0;
|
block.id = 0;
|
||||||
info.first_block = block;
|
info.first_block = block;
|
||||||
info.last_block = block;
|
info.last_block = block;
|
||||||
|
info.update_block = block;
|
||||||
}
|
}
|
||||||
else if (block.entities_count + block.added_count > info.max_entities)
|
else if (block.entities_count + block.added_count >= info.max_entities)
|
||||||
{
|
{
|
||||||
EntitiesBlock* last_block = info.last_block;
|
EntitiesBlock* last_block = info.last_block;
|
||||||
|
|
||||||
|
|
@ -2687,6 +2698,12 @@ export struct EntityManager
|
||||||
new_block.id = cast(ushort)(block.id + 1);
|
new_block.id = cast(ushort)(block.id + 1);
|
||||||
block = new_block;
|
block = new_block;
|
||||||
info.last_block = block;
|
info.last_block = block;
|
||||||
|
///make sure that update_block point to unfilled block
|
||||||
|
if (info.update_block.entities_count == info.max_entities)
|
||||||
|
{
|
||||||
|
assert(!info.update_block.added_count);
|
||||||
|
info.update_block = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
@ -2730,8 +2747,10 @@ export struct EntityManager
|
||||||
{
|
{
|
||||||
EntityInfo* info = block.type_info;
|
EntityInfo* info = block.type_info;
|
||||||
|
|
||||||
if (info.last_block.added_count)
|
updateEntityInfoBlocks(info);
|
||||||
updateBlock(info.last_block);
|
|
||||||
|
assert(info.last_block.added_count == 0);
|
||||||
|
assert(info.last_block.entities_count > 0);
|
||||||
|
|
||||||
info.last_block.entities_count--;
|
info.last_block.entities_count--;
|
||||||
|
|
||||||
|
|
@ -2764,12 +2783,13 @@ export struct EntityManager
|
||||||
block = info.last_block;
|
block = info.last_block;
|
||||||
entity.id = *cast(EntityID*)(block.dataBegin() + block.entities_count * EntityID.sizeof);
|
entity.id = *cast(EntityID*)(block.dataBegin() + block.entities_count * EntityID.sizeof);
|
||||||
|
|
||||||
id_manager.update(*entity); //entity.updateID();
|
id_manager.update(*entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
block = info.last_block;
|
block = info.last_block;
|
||||||
if (block.entities_count == 0)
|
if (block.entities_count == 0)
|
||||||
{
|
{
|
||||||
|
assert(info.update_block is block);
|
||||||
info.last_block = block.prev_block;
|
info.last_block = block.prev_block;
|
||||||
if (info.first_block is block)
|
if (info.first_block is block)
|
||||||
{
|
{
|
||||||
|
|
@ -2778,7 +2798,9 @@ export struct EntityManager
|
||||||
if (block.prev_block)
|
if (block.prev_block)
|
||||||
{
|
{
|
||||||
block.prev_block.next_block = null;
|
block.prev_block.next_block = null;
|
||||||
block.prev_block.added_count = 0;
|
info.update_block = block.prev_block;
|
||||||
|
assert(block.prev_block.added_count == 0);
|
||||||
|
//block.prev_block.added_count.atomicStore(cast(ushort)0);
|
||||||
}
|
}
|
||||||
allocator.freeBlock(block);
|
allocator.freeBlock(block);
|
||||||
}
|
}
|
||||||
|
|
@ -2852,7 +2874,7 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callAddEntityListener(System* system, EntityInfo* info,
|
private static void callAddEntityListener(System* system, EntityInfo* info,
|
||||||
EntitiesBlock* block, int begin, int end) @nogc nothrow
|
EntitiesBlock* block, int begin, int end) @nogc nothrow
|
||||||
{
|
{
|
||||||
ListenerCallData data;
|
ListenerCallData data;
|
||||||
|
|
@ -2873,8 +2895,8 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callRemoveEntityListener(System* system, EntityInfo* info,
|
private static void callRemoveEntityListener(System* system,
|
||||||
EntitiesBlock* block, int begin, int end) @nogc nothrow
|
EntityInfo* info, EntitiesBlock* block, int begin, int end) @nogc nothrow
|
||||||
{
|
{
|
||||||
ListenerCallData data;
|
ListenerCallData data;
|
||||||
data.system = system;
|
data.system = system;
|
||||||
|
|
@ -2921,9 +2943,34 @@ export struct EntityManager
|
||||||
(cast(void function(ref ListenerCallData) nothrow @nogc) system.m_change_entity)(data);
|
(cast(void function(ref ListenerCallData) nothrow @nogc) system.m_change_entity)(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateEntityInfoBlocks(EntityInfo* info) nothrow @nogc
|
||||||
|
{
|
||||||
|
while (info.last_block.added_count)
|
||||||
|
{
|
||||||
|
EntitiesBlock* block = info.update_block;
|
||||||
|
assert(block !is null);
|
||||||
|
if (block.entities_count == info.max_entities)
|
||||||
|
{
|
||||||
|
assert(!block.added_count);
|
||||||
|
block = block.next_block;
|
||||||
|
}
|
||||||
|
assert(!block.prev_block || !block.prev_block.added_count);
|
||||||
|
info.update_block = info.last_block;
|
||||||
|
|
||||||
|
while (block)
|
||||||
|
{
|
||||||
|
assert(block.added_count.atomicLoad() > 0);
|
||||||
|
updateBlock(block);
|
||||||
|
block = block.next_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(info.last_block is info.update_block);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateBlock(EntitiesBlock* block) @nogc nothrow
|
private void updateBlock(EntitiesBlock* block) @nogc nothrow
|
||||||
{
|
{
|
||||||
if(block.added_count == 0)return;
|
//if(block.added_count == 0)return;
|
||||||
|
assert(block.added_count != 0);
|
||||||
EntityInfo* info = block.type_info;
|
EntityInfo* info = block.type_info;
|
||||||
ushort entities_count = block.entities_count;
|
ushort entities_count = block.entities_count;
|
||||||
block.entities_count += block.added_count;
|
block.entities_count += block.added_count;
|
||||||
|
|
@ -2942,17 +2989,15 @@ export struct EntityManager
|
||||||
private bool updateBlocks()
|
private bool updateBlocks()
|
||||||
{
|
{
|
||||||
bool has_work = false;
|
bool has_work = false;
|
||||||
//foreach (ref ThreadData thread; threads)thread.swapToUpdate();
|
|
||||||
foreach (ref ThreadData thread; threads)
|
foreach (ref ThreadData thread; threads)
|
||||||
{
|
{
|
||||||
//thread.swapToUpdate();
|
if (thread.infosToUpdatePrev.length)
|
||||||
if (thread.blockToUpdatePrev.length)
|
|
||||||
has_work = true;
|
has_work = true;
|
||||||
foreach (block; thread.blockToUpdatePrev)
|
foreach (info; thread.infosToUpdatePrev)
|
||||||
{
|
{
|
||||||
updateBlock(block);
|
updateEntityInfoBlocks(info);
|
||||||
}
|
}
|
||||||
thread.blockToUpdatePrev.clear();
|
thread.infosToUpdatePrev.clear();
|
||||||
}
|
}
|
||||||
return has_work;
|
return has_work;
|
||||||
}
|
}
|
||||||
|
|
@ -3055,6 +3100,9 @@ export struct EntityManager
|
||||||
swapData();
|
swapData();
|
||||||
|
|
||||||
has_work = false;
|
has_work = false;
|
||||||
|
// has_work |= updateBlocks();
|
||||||
|
// has_work |= changeEntities();
|
||||||
|
// has_work |= removeEntities();
|
||||||
has_work |= updateEvents();
|
has_work |= updateEvents();
|
||||||
|
|
||||||
//id_manager.optimize();
|
//id_manager.optimize();
|
||||||
|
|
@ -3477,7 +3525,7 @@ export struct EntityManager
|
||||||
EntityInfo*[] comp_rem_info;
|
EntityInfo*[] comp_rem_info;
|
||||||
|
|
||||||
///alignment of whole entity
|
///alignment of whole entity
|
||||||
ushort alignment; //unused in linear-layout
|
ushort alignment; //unused in linear-layout TODO: to remove
|
||||||
///size of entity (with alignment respect)
|
///size of entity (with alignment respect)
|
||||||
ushort size;
|
ushort size;
|
||||||
///max number of entities in block
|
///max number of entities in block
|
||||||
|
|
@ -3496,6 +3544,8 @@ export struct EntityManager
|
||||||
EntitiesBlock* first_block;
|
EntitiesBlock* first_block;
|
||||||
///pointer to last block
|
///pointer to last block
|
||||||
EntitiesBlock* last_block;
|
EntitiesBlock* last_block;
|
||||||
|
///pointer to last updated block
|
||||||
|
EntitiesBlock* update_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
|
|
@ -3642,9 +3692,9 @@ export struct EntityManager
|
||||||
return change_entities_list[data_index];
|
return change_entities_list[data_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
ref Vector!(EntitiesBlock*) blockToUpdate() @nogc nothrow return
|
ref Vector!(EntityInfo*) infosToUpdate() @nogc nothrow return
|
||||||
{
|
{
|
||||||
return blocks_to_update[data_index];
|
return infos_to_update[data_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
ref Vector!EntityID entitiesToRemovePrev() @nogc nothrow return
|
ref Vector!EntityID entitiesToRemovePrev() @nogc nothrow return
|
||||||
|
|
@ -3657,9 +3707,9 @@ export struct EntityManager
|
||||||
return change_entities_list[1 - data_index];
|
return change_entities_list[1 - data_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
ref Vector!(EntitiesBlock*) blockToUpdatePrev() @nogc nothrow return
|
ref Vector!(EntityInfo*) infosToUpdatePrev() @nogc nothrow return
|
||||||
{
|
{
|
||||||
return blocks_to_update[1 - data_index];
|
return infos_to_update[1 - data_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -3671,7 +3721,7 @@ export struct EntityManager
|
||||||
|
|
||||||
Vector!EntityID[2] entities_to_remove;
|
Vector!EntityID[2] entities_to_remove;
|
||||||
SimpleVector[2] change_entities_list;
|
SimpleVector[2] change_entities_list;
|
||||||
Vector!(EntitiesBlock*)[2] blocks_to_update;
|
Vector!(EntityInfo*)[2] infos_to_update;
|
||||||
|
|
||||||
ubyte data_index = 0;
|
ubyte data_index = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue