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;*/
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -2183,6 +2185,10 @@ export struct EntityManager
|
|||
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)
|
||||
{
|
||||
foreach (listener; new_info.add_listeners)
|
||||
|
|
@ -2190,7 +2196,7 @@ export struct EntityManager
|
|||
if (!info.systems[listener])
|
||||
{
|
||||
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])
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -2291,12 +2295,14 @@ export struct EntityManager
|
|||
//EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
|
||||
|
||||
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;
|
||||
|
||||
Entity* new_entity = cast(Entity*) start;
|
||||
new_entity.id = entity.id;
|
||||
id_manager.update(*new_entity); //new_entity.updateID();
|
||||
id_manager.update(*new_entity);
|
||||
|
||||
uint j = 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)
|
||||
{
|
||||
foreach (listener; new_info.add_listeners)
|
||||
|
|
@ -2349,7 +2359,7 @@ export struct EntityManager
|
|||
if (!info.systems[listener])
|
||||
{
|
||||
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])
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -2487,14 +2496,12 @@ export struct EntityManager
|
|||
}
|
||||
}
|
||||
|
||||
if (new_index == 1)
|
||||
threads[threadID].blockToUpdate.add(new_block);
|
||||
if (new_index == 1 && info.update_block == block)
|
||||
threads[threadID].infosToUpdate.add(info);
|
||||
|
||||
Entity* new_entity = cast(Entity*) start;
|
||||
//add_mutex.lock_nothrow();
|
||||
new_entity.id = id_manager.getNewID();
|
||||
//add_mutex.unlock_nothrow();
|
||||
id_manager.update(*new_entity); //new_entity.updateID();
|
||||
id_manager.update(*new_entity);
|
||||
|
||||
return new_entity;
|
||||
}
|
||||
|
|
@ -2538,12 +2545,10 @@ export struct EntityManager
|
|||
}
|
||||
|
||||
if (index == 1)
|
||||
threads[threadID].blockToUpdate.add(block);
|
||||
threads[threadID].infosToUpdate.add(block);
|
||||
|
||||
Entity* entity = cast(Entity*) start;
|
||||
//add_mutex.lock_nothrow();
|
||||
entity.id = id_manager.getNewID();
|
||||
//add_mutex.unlock_nothrow();
|
||||
id_manager.update(*entity); //entity.updateID();
|
||||
|
||||
return entity;*/
|
||||
|
|
@ -2589,7 +2594,7 @@ export struct EntityManager
|
|||
if (comp.component_id < info.deltas.length)
|
||||
{
|
||||
ushort delta = info.deltas[comp.component_id];
|
||||
if (delta != ushort.max)
|
||||
if (delta != 0)
|
||||
{
|
||||
uint size = components[comp.component_id].size;
|
||||
if (size != 0)
|
||||
|
|
@ -2607,14 +2612,12 @@ export struct EntityManager
|
|||
}
|
||||
}
|
||||
|
||||
if (index == 1)
|
||||
threads[threadID].blockToUpdate.add(block);
|
||||
if (index == 1 && info.update_block == block)
|
||||
threads[threadID].infosToUpdate.add(info);
|
||||
|
||||
Entity* entity = cast(Entity*) start;
|
||||
//add_mutex.lock_nothrow();
|
||||
entity.id = id_manager.getNewID();
|
||||
//add_mutex.unlock_nothrow();
|
||||
id_manager.update(*entity); //entity.updateID();
|
||||
id_manager.update(*entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
|
@ -2633,6 +2636,7 @@ export struct EntityManager
|
|||
block.id = 0;
|
||||
info.first_block = block;
|
||||
info.last_block = block;
|
||||
info.update_block = block;
|
||||
}
|
||||
else if (block.entities_count >= info.max_entities)
|
||||
{
|
||||
|
|
@ -2643,6 +2647,12 @@ export struct EntityManager
|
|||
new_block.id = cast(ushort)(block.id + 1);
|
||||
block = new_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;
|
||||
}
|
||||
|
|
@ -2668,8 +2678,9 @@ export struct EntityManager
|
|||
block.id = 0;
|
||||
info.first_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;
|
||||
|
||||
|
|
@ -2687,6 +2698,12 @@ export struct EntityManager
|
|||
new_block.id = cast(ushort)(block.id + 1);
|
||||
block = new_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;
|
||||
}
|
||||
|
|
@ -2730,8 +2747,10 @@ export struct EntityManager
|
|||
{
|
||||
EntityInfo* info = block.type_info;
|
||||
|
||||
if (info.last_block.added_count)
|
||||
updateBlock(info.last_block);
|
||||
updateEntityInfoBlocks(info);
|
||||
|
||||
assert(info.last_block.added_count == 0);
|
||||
assert(info.last_block.entities_count > 0);
|
||||
|
||||
info.last_block.entities_count--;
|
||||
|
||||
|
|
@ -2764,12 +2783,13 @@ export struct EntityManager
|
|||
block = info.last_block;
|
||||
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;
|
||||
if (block.entities_count == 0)
|
||||
{
|
||||
assert(info.update_block is block);
|
||||
info.last_block = block.prev_block;
|
||||
if (info.first_block is block)
|
||||
{
|
||||
|
|
@ -2778,7 +2798,9 @@ export struct EntityManager
|
|||
if (block.prev_block)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
ListenerCallData data;
|
||||
|
|
@ -2873,8 +2895,8 @@ export struct EntityManager
|
|||
}
|
||||
}
|
||||
|
||||
private void callRemoveEntityListener(System* system, EntityInfo* info,
|
||||
EntitiesBlock* block, int begin, int end) @nogc nothrow
|
||||
private static void callRemoveEntityListener(System* system,
|
||||
EntityInfo* info, EntitiesBlock* block, int begin, int end) @nogc nothrow
|
||||
{
|
||||
ListenerCallData data;
|
||||
data.system = system;
|
||||
|
|
@ -2921,9 +2943,34 @@ export struct EntityManager
|
|||
(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
|
||||
{
|
||||
if(block.added_count == 0)return;
|
||||
//if(block.added_count == 0)return;
|
||||
assert(block.added_count != 0);
|
||||
EntityInfo* info = block.type_info;
|
||||
ushort entities_count = block.entities_count;
|
||||
block.entities_count += block.added_count;
|
||||
|
|
@ -2942,17 +2989,15 @@ export struct EntityManager
|
|||
private bool updateBlocks()
|
||||
{
|
||||
bool has_work = false;
|
||||
//foreach (ref ThreadData thread; threads)thread.swapToUpdate();
|
||||
foreach (ref ThreadData thread; threads)
|
||||
{
|
||||
//thread.swapToUpdate();
|
||||
if (thread.blockToUpdatePrev.length)
|
||||
if (thread.infosToUpdatePrev.length)
|
||||
has_work = true;
|
||||
foreach (block; thread.blockToUpdatePrev)
|
||||
foreach (info; thread.infosToUpdatePrev)
|
||||
{
|
||||
updateBlock(block);
|
||||
updateEntityInfoBlocks(info);
|
||||
}
|
||||
thread.blockToUpdatePrev.clear();
|
||||
thread.infosToUpdatePrev.clear();
|
||||
}
|
||||
return has_work;
|
||||
}
|
||||
|
|
@ -3055,6 +3100,9 @@ export struct EntityManager
|
|||
swapData();
|
||||
|
||||
has_work = false;
|
||||
// has_work |= updateBlocks();
|
||||
// has_work |= changeEntities();
|
||||
// has_work |= removeEntities();
|
||||
has_work |= updateEvents();
|
||||
|
||||
//id_manager.optimize();
|
||||
|
|
@ -3477,7 +3525,7 @@ export struct EntityManager
|
|||
EntityInfo*[] comp_rem_info;
|
||||
|
||||
///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)
|
||||
ushort size;
|
||||
///max number of entities in block
|
||||
|
|
@ -3496,6 +3544,8 @@ export struct EntityManager
|
|||
EntitiesBlock* first_block;
|
||||
///pointer to 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];
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -3657,9 +3707,9 @@ export struct EntityManager
|
|||
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:
|
||||
|
|
@ -3671,7 +3721,7 @@ export struct EntityManager
|
|||
|
||||
Vector!EntityID[2] entities_to_remove;
|
||||
SimpleVector[2] change_entities_list;
|
||||
Vector!(EntitiesBlock*)[2] blocks_to_update;
|
||||
Vector!(EntityInfo*)[2] infos_to_update;
|
||||
|
||||
ubyte data_index = 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue