1
1
using System ;
2
+ using System . Collections ;
2
3
using System . Collections . Generic ;
3
4
4
5
namespace SimpleECS
5
6
{
6
- class EntityRegistry
7
+ class EntityRegistry : IReadOnlyCollection < Entity >
7
8
{
8
9
public struct EntityLocation
9
10
{
@@ -20,19 +21,29 @@ public EntityLocation(ArchetypeContainer archetypeContainer, int index)
20
21
private const int InitialCapacity = 512 ;
21
22
EntityLocation [ ] Locations = new EntityLocation [ InitialCapacity ] ;
22
23
int [ ] Versions = new int [ InitialCapacity ] ;
23
- Queue < int > freeIDs = new Queue < int > ( ) ;
24
- int count = 0 ;
24
+ HashSet < int > freeIDs = new HashSet < int > ( ) ;
25
+ int nextId = 0 ;
26
+
27
+ public int Count => nextId - freeIDs . Count ;
25
28
26
29
public int GetVersion ( int entity ) => Versions [ entity ] ;
27
30
28
31
public Entity RegisterEntity ( ArchetypeContainer container , int index )
29
32
{
30
- if ( count == Locations . Length )
33
+ if ( nextId == Locations . Length )
31
34
Array . Resize ( ref Locations , Locations . Length * 2 ) ;
32
- if ( ! freeIDs . TryDequeue ( out int id ) )
35
+ int id ;
36
+ if ( freeIDs . Count > 0 )
33
37
{
34
- id = count ;
35
- count ++ ;
38
+ // faster implementation of First()
39
+ foreach ( var _id in freeIDs ) { id = _id ; goto done ; }
40
+ throw new Exception ( ) ;
41
+ done : ;
42
+ }
43
+ else
44
+ {
45
+ id = nextId ;
46
+ nextId ++ ;
36
47
}
37
48
Locations [ id ] = new EntityLocation ( container , index ) ;
38
49
return new Entity ( id , Versions [ id ] ) ;
@@ -44,7 +55,7 @@ public void UnregisterEntity(Entity entity, out EntityLocation lastLocation)
44
55
lastLocation = Locations [ entity . Id ] ;
45
56
Locations [ entity . Id ] = default ;
46
57
Versions [ entity . Id ] ++ ;
47
- freeIDs . Enqueue ( entity . Id ) ;
58
+ freeIDs . Add ( entity . Id ) ;
48
59
}
49
60
public void MoveEntity ( int entity , ArchetypeContainer newContainer , int newIndex )
50
61
{
@@ -63,5 +74,38 @@ public bool TryGetLocation(Entity entity, out EntityLocation location)
63
74
return true ;
64
75
}
65
76
}
77
+
78
+ public IEnumerator < Entity > GetEnumerator ( ) => new EntityEnumerator ( this ) ;
79
+ IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
80
+ struct EntityEnumerator : IEnumerator < Entity >
81
+ {
82
+ int currentId ;
83
+ EntityRegistry registry ;
84
+ public Entity Current => new Entity ( currentId , registry . GetVersion ( currentId ) ) ;
85
+
86
+ object ? IEnumerator . Current => this . Current ;
87
+
88
+ public EntityEnumerator ( EntityRegistry registry )
89
+ {
90
+ this . currentId = - 1 ;
91
+ this . registry = registry ;
92
+ }
93
+
94
+ public void Dispose ( ) { }
95
+
96
+ public bool MoveNext ( )
97
+ {
98
+ do
99
+ {
100
+ currentId ++ ;
101
+ if ( registry . nextId == currentId )
102
+ return false ;
103
+ }
104
+ while ( registry . freeIDs . Contains ( currentId ) ) ;
105
+ return true ;
106
+ }
107
+
108
+ public void Reset ( ) => currentId = - 1 ;
109
+ }
66
110
}
67
111
}
0 commit comments