Skip to content

Commit 23ad2e7

Browse files
committed
Initial commit
0 parents  commit 23ad2e7

10 files changed

+294
-0
lines changed

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.sln
2+
.vs
3+
.vscode
4+
.idea
5+
.DS_Store
6+
bin
7+
obj
8+
Library
9+
Temp

Bitron.Ecs.csproj

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>netstandard2.0</TargetFramework>
4+
<DefineConstants>NET_STANDARD_2_0</DefineConstants>
5+
</PropertyGroup>
6+
</Project>

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Aaron Winter
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# BitEcs
2+

src/Commands.cs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
namespace Bitron.Ecs
2+
{
3+
public sealed class Commands
4+
{
5+
private World _world;
6+
7+
public EntityCommands Spawn()
8+
{
9+
return Entity(_world.Spawn());
10+
}
11+
12+
public EntityCommands Entity(Entity entity)
13+
{
14+
return new EntityCommands(this, entity);
15+
}
16+
17+
public void AddComponent<Component>(Entity entity) where Component: struct
18+
{
19+
var storage = _world.GetStorage<Component>();
20+
storage.Add(entity);
21+
}
22+
23+
public void AddComponent<Component>(Entity entity, Component component) where Component: struct
24+
{
25+
var storage = _world.GetStorage<Component>();
26+
storage.Add(entity) = component;
27+
}
28+
29+
public void RemoveComponent<Component>(Entity entity) where Component: struct
30+
{
31+
var storage = _world.GetStorage<Component>();
32+
storage.Remove(entity);
33+
}
34+
}
35+
36+
public sealed class EntityCommands
37+
{
38+
private Commands _commands;
39+
private Entity _entity;
40+
41+
internal EntityCommands(Commands commands, Entity entity)
42+
{
43+
_commands = commands;
44+
_entity = entity;
45+
}
46+
47+
public EntityCommands Add<Component>() where Component: struct
48+
{
49+
50+
_commands.AddComponent<Component>(_entity);
51+
return this;
52+
}
53+
54+
public EntityCommands Add<Component>(Component component) where Component: struct
55+
{
56+
_commands.AddComponent<Component>(_entity, component);
57+
return this;
58+
}
59+
60+
public EntityCommands Remove<Component>() where Component: struct
61+
{
62+
_commands.RemoveComponent<Component>(_entity);
63+
return this;
64+
}
65+
66+
public Entity Id()
67+
{
68+
return _entity;
69+
}
70+
}
71+
}

src/Entity.cs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Bitron.Ecs
2+
{
3+
public struct Entity
4+
{
5+
public int Id;
6+
public int Gen;
7+
}
8+
}

src/Storage.cs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
3+
namespace Bitron.Ecs
4+
{
5+
public interface IStorage { }
6+
7+
public sealed class Storage<Component> : IStorage where Component : struct
8+
{
9+
private int[] _indicies;
10+
private Component[] _components;
11+
private int _componentCount;
12+
13+
public ref Component Add(Entity entity)
14+
{
15+
int index = _componentCount++;
16+
17+
if (_componentCount == _components.Length)
18+
{
19+
Array.Resize(ref _components, _componentCount << 1);
20+
}
21+
22+
_indicies[entity.Id] = index;
23+
return ref _components[index];
24+
}
25+
26+
public void Remove(Entity entity)
27+
{
28+
ref var index = ref _indicies[entity.Id];
29+
30+
if (index > 0)
31+
{
32+
_components[index] = default;
33+
index = 0;
34+
}
35+
}
36+
37+
public bool Has(Entity entity)
38+
{
39+
return _indicies[entity.Id] > 0;
40+
}
41+
}
42+
}

src/System.cs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Collections.Generic;
2+
3+
namespace Bitron.Ecs
4+
{
5+
public sealed class EcsSystemGroup
6+
{
7+
private List<ISystem> _systems = new List<ISystem>();
8+
9+
public EcsSystemGroup Add(ISystem system)
10+
{
11+
_systems.Add(system);
12+
return this;
13+
}
14+
15+
// public EcsSystemGroup OneFrame<Component>() where Component : struct
16+
// {
17+
// return Add(new RemoveAllComponentsOfType<Component>());
18+
// }
19+
20+
public void Run(Commands commands)
21+
{
22+
for(var i = 0; i < _systems.Count; i++)
23+
{
24+
_systems[i].Run(commands);
25+
}
26+
}
27+
}
28+
29+
public interface ISystem
30+
{
31+
void Run(Commands commands);
32+
}
33+
34+
// public class RemoveAllComponentsOfType<Component> : ISystem where Component : struct
35+
// {
36+
// public void Run(World world)
37+
// {
38+
// var query = world.Query<Component>().End();
39+
// var pool = world.GetPool<Component>();
40+
41+
// foreach (var entity in query)
42+
// {
43+
// pool.Remove(entity);
44+
// }
45+
// }
46+
// }
47+
}

src/World.cs

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
3+
namespace Bitron.Ecs
4+
{
5+
public sealed class World
6+
{
7+
private EntityMeta[] _entityMetas;
8+
private int _entityCount;
9+
10+
private int _despawnedEntityCount;
11+
private int[] _despawnedEntities;
12+
13+
private IStorage[] _pools;
14+
private int _poolCount;
15+
16+
public Entity Spawn()
17+
{
18+
int id;
19+
int gen;
20+
21+
if (_despawnedEntityCount > 0)
22+
{
23+
id = _despawnedEntities[--_despawnedEntityCount];
24+
gen = -(_entityMetas[id]).Gen;
25+
}
26+
else
27+
{
28+
id = _entityCount++;
29+
gen = 1;
30+
}
31+
32+
_entityMetas[id].Gen = gen;
33+
34+
return new Entity() { Id = id, Gen = gen };
35+
}
36+
37+
public void Despawn(Entity entity)
38+
{
39+
if (_entityMetas[entity.Id].Gen < 0)
40+
{
41+
return;
42+
}
43+
44+
if (_despawnedEntityCount == _despawnedEntities.Length)
45+
{
46+
Array.Resize(ref _despawnedEntities, _despawnedEntityCount << 1);
47+
}
48+
49+
ref var meta = ref _entityMetas[entity.Id];
50+
meta.Gen = -(meta.Gen + 1);
51+
52+
_despawnedEntities[_despawnedEntityCount++] = entity.Id;
53+
}
54+
55+
public Storage<Component> GetStorage<Component>() where Component : struct
56+
{
57+
var typeId = ComponentType<Component>.Id;
58+
59+
if (typeId == _poolCount)
60+
{
61+
Array.Resize(ref _pools, _poolCount << 1);
62+
_pools[typeId] = new Storage<Component>();
63+
_poolCount++;
64+
}
65+
66+
return _pools[typeId] as Storage<Component>;
67+
}
68+
}
69+
70+
internal struct EntityMeta
71+
{
72+
public int Gen;
73+
}
74+
75+
internal class ComponentType
76+
{
77+
protected static int counter = 0;
78+
}
79+
80+
internal class ComponentType<T> : ComponentType
81+
{
82+
public static readonly int Id;
83+
84+
static ComponentType() => Id = counter++;
85+
}
86+
}

0 commit comments

Comments
 (0)