This commit is contained in:
mmcomando 2018-09-07 10:48:03 +02:00
parent f851e3c2ec
commit a984824ec5
5 changed files with 311 additions and 2 deletions

241
source/ecs/ecs.d Normal file
View file

@ -0,0 +1,241 @@
module ecs.ecs;
import std.stdio;
alias SytemFuncType = void function(ref SystemCallData data, void* componentsStart);
struct HasComponentsStore {
ulong[4] bits; //256 components
bool has(HasComponentsStore components) {
return true;
}
bool notIn(HasComponentsStore components) {
return true;
}
int length() {
assert(0);
}
}
// Informacje o kompnencie
struct ComponentInfo {
int size;
int aligment;
SerializeJSON funsSerJ;
SerializeBiN funcSerB;
}
struct System {
HasComponentsStore requiredComponents;
HasComponentsStore absenComponents;
HasComponentsStore maybeComponents;
bool enabled;
int priority;
SytemFuncType func;
}
// Informacje o systemie dla konkretnego entitiesa
struct SystemCallData {
System* system;
int[] componentsDt;
}
// Informacje o entitiesie danego typu
struct EntityTypeData {
HasComponentsStore components;
int[] deltas;
int totalSize;
int totalAligment = 8;
SystemCallData[] systems;
}
struct EntitiesBlock {
EntityTypeData* typeData;
Entity* freeEntitySlot;
EntitiesBlock* nextBlock;
}
struct EntityID {
ulong id = ulong.max;
static immutable notUsedValue = EntityID(ulong.max);
}
// Dane konkretnego Entitiesa
struct Entity {
EntityID entityID = EntityID.notUsedValue;
union {
string name;
Entity* nextFreeSlot;
}
//string eventOnDestroy;
uint group;
EntityID entityID;
//ubyte[XX] thereIsComponentsMemory;
}
struct Template {
HasComponentsStore hasComp;
Entity* entity;
}
struct Manager {
EntityAllocator entityArrayAllcoator;
ComponentInfo[] components;
System[] systems;
HashMap!(HasComponentsStore, EntitiesBlock*) entitiesDatas;
HashMapTwoWays!(string, Entity*) nameMap;
HashMapTwoWays!(EntityID, Entity*) idMap;
EntitiesBlock* getEntitiesBlock(HasComponentsStore hasComponents) {
EntitiesBlock* block = entitiesDatas.get(hasComponents, null);
if (block is null) {
// If such component combination was never present, add it
block = addNewBlock(hasComponents, block);
return block;
}
// Iterate over list of components until free slot is found or lists ends
do {
if (block.freeEntitySlot !is null) {
return block;
}
if (block.nextBlock is null) {
block = addNewBlock(hasComponents);
return block;
}
block = block.nextBlock;
}
while (block.nextBlock !is null);
}
EntitiesBlock* addNewBlock(HasComponentsStore hasComponents, EntitiesBlock* firstBlock) {
// Get last block so order of blocks is preserved, and first blocks are filled first
EntitiesBlock* lastBlock = firstBlock;
if (lastBlock !is null) {
while (lastBlock.nextBlock !is null) {
lastBlock = lastBlock.nextBlock;
}
}
assert(lastBlock is null || lastBlock.nextBlock is null);
ubyte[] memory = new ubyte[](4096);
EntitiesBlock* block = cast(EntitiesBlock*) memory.ptr;
if (lastBlock is null) {
EntityTypeData* entityTypeData = newEntityTypeData(hasComponents);
block.typeData = entityTypeData;
block.nextBlock = null;
entitiesDatas.add(hasComponents, block);
} else {
lastBlock.nextBlock = block;
block.typeData = lastBlock.typeData;
block.nextBlock = null;
}
}
void alignNum(ref int num, int aligment) {
int reminder = num % aligment;
if (reminder != 0) {
num += aligment - reminder;
}
}
EntityTypeData* newEntityTypeData(HasComponentsStore hasComponents) {
EntityTypeData* typeData = new EntityTypeData();
typeData.components = hasComponents;
ComponentInfo[] components = getComponentsInfo(hasComponents);
typeData.deltas.length = hasComponents.length;
foreach (i, comp; components) {
typeData.deltas[i] = typeData.totalSize;
typeData.totalAligment.max(comp.aligment);
typeData.totalSize += comp.size;
alignNum(typeData.totalSize, comp.aligment);
}
alignNum(typeData.totalSize, typeData.totalAligment);
foreach (sys; systems) {
if (!typeData.hasComp.has(sys.requiredComponents)
|| !typeData.hasComp.notIn(sys.absenComponents)) {
continue;
}
entTypeData.systems ~= sys
}
return typeData;
}
void addEntity(Template* templ) {
EntitiesBlock* block = getEntitiesBlock(templ.hasComp);
Entity* newEntity = block.freeEntitySlot;
block.freeEntitySlot = newEntity.nextFreeSlot;
// from to size
memcpy(temp.entity, newEntity, block.typeData.totalSize);
}
void addSystem(Func)(int priority) {
HasComponentsStore requiredComponents;
HasComponentsStore absenComponents;
HasComponentsStore maybeComponents;
void systemCaller(ref SystemCallData data, void * componentsStart) {
Func(cast(FUnc.par1Type)(componentsStart + data.componentsDt[0]),
cast(FUnc.par1Type)(componentsStart + data.componentsDt[1])...);
}
System* system = new System(&systemCaller, entTypeData);
systems~=system;
foreach (ref entTypeData; entitiesDatas) {
if (!entTypeData.hasComp.has(requiredComponents)
|| !entTypeData.hasComp.notIn(absenComponents)) {
continue;
}
entTypeData.systems ~= system;
}
}
}
void someSystem(CompA a, CompB b, CompC* c) {
}
void main() {
writeln("Edit source/app.d to start your project.");
}
class System{
void start(){
}
void end(){
}
void update(ref ObjRend a){
}
void useEvent(EventData evvv, ref ObjRend a){
}
}

View file

@ -0,0 +1,51 @@
module ecs.entity_allocator;
enum bucketSize = 4096;
enum bucketsInAllocation = 128;
struct Bucket
{
union
{
ubyte[bucketSize] memory;
Bucket* next;
}
}
struct BucketArray
{
Bucket[bucketsInAllocation] buckets;
}
struct EntityAllocator
{
BucketArray[] arrays;
Bucket* lastEmptyBucket;
void initBucketArray(ref BucketArray bArr)
{
}
void allocateBucketArray()
{
auto bucketArray = new BucketArray();
assert(bucketArray.buckets[0].ptr % bucketSize == 0) arrays ~= bucketArray;
Bucket* lasBucket = initBucketArray(bucketArray);
lastEmptyBucket = lasBucket;
}
ubyte[] getMemory()
{
if (lastEmptyBucket is null)
{
allocateBucket();
}
auto bucketTmp = lastEmptyBucket;
lastEmptyBucket = bucketTmp.next;
return bucketTmp.memory[];
}
}