initial snapshot system
							parent
							
								
									f045335881
								
							
						
					
					
						commit
						8061590195
					
				|  | @ -87,5 +87,28 @@ namespace MoonTools.ECS | |||
| 		{ | ||||
| 			Lookup<TComponent>().Remove(entityID); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Clear() | ||||
| 		{ | ||||
| 			for (var i = 0; i < ComponentTypeIndices.Count; i += 1) | ||||
| 			{ | ||||
| 				if (storages[i] != null) | ||||
| 				{ | ||||
| 					storages[i].Clear(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// used to fill snapshot depot with correct storages | ||||
| 		public void FillMissingStorages(ComponentDepot other) | ||||
| 		{ | ||||
| 			for (var i = 0; i < ComponentTypeIndices.Count; i += 1) | ||||
| 			{ | ||||
| 				if (storages[i] == null && other.storages[i] != null) | ||||
| 				{ | ||||
| 					storages[i] = other.storages[i].CreateStorage(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -8,12 +8,12 @@ namespace MoonTools.ECS | |||
| 	{ | ||||
| 		internal abstract void Set(int entityID, object component); | ||||
| 		public abstract bool Remove(int entityID); | ||||
| 		public abstract ComponentStorageState CreateState(); | ||||
| 		public abstract void Save(ComponentStorageState state); | ||||
| 		public abstract void Load(ComponentStorageState state); | ||||
| 		public abstract void Clear(); | ||||
| 
 | ||||
| 		// used for debugging and template instantiation | ||||
| 		internal abstract object UntypedGet(int entityID); | ||||
| 		// used to create correctly typed storage on snapshot | ||||
| 		public abstract ComponentStorage CreateStorage(); | ||||
| 	} | ||||
| 
 | ||||
| 	internal class ComponentStorage<TComponent> : ComponentStorage where TComponent : unmanaged | ||||
|  | @ -101,7 +101,7 @@ namespace MoonTools.ECS | |||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		public void Clear() | ||||
| 		public override void Clear() | ||||
| 		{ | ||||
| 			nextID = 0; | ||||
| 			entityIDToStorageIndex.Clear(); | ||||
|  | @ -123,43 +123,9 @@ namespace MoonTools.ECS | |||
| 			return new Entity(entityIDs[0]); | ||||
| 		} | ||||
| 
 | ||||
| 		public override ComponentStorageState CreateState() | ||||
| 		public override ComponentStorage<TComponent> CreateStorage() | ||||
| 		{ | ||||
| 			return ComponentStorageState.Create<TComponent>(nextID); | ||||
| 		} | ||||
| 
 | ||||
| 		public override void Save(ComponentStorageState state) | ||||
| 		{ | ||||
| 			ReadOnlySpan<byte> entityIDBytes = MemoryMarshal.Cast<int, byte>(new ReadOnlySpan<int>(entityIDs, 0, nextID)); | ||||
| 
 | ||||
| 			if (entityIDBytes.Length > state.EntityIDs.Length) | ||||
| 			{ | ||||
| 				Array.Resize(ref state.EntityIDs, entityIDBytes.Length); | ||||
| 			} | ||||
| 			entityIDBytes.CopyTo(state.EntityIDs); | ||||
| 
 | ||||
| 			ReadOnlySpan<byte> componentBytes = MemoryMarshal.Cast<TComponent, byte>(AllComponents()); | ||||
| 			if (componentBytes.Length > state.Components.Length) | ||||
| 			{ | ||||
| 				Array.Resize(ref state.Components, componentBytes.Length); | ||||
| 			} | ||||
| 			componentBytes.CopyTo(state.Components); | ||||
| 
 | ||||
| 			state.Count = nextID; | ||||
| 		} | ||||
| 
 | ||||
| 		public override void Load(ComponentStorageState state) | ||||
| 		{ | ||||
| 			state.EntityIDs.CopyTo(MemoryMarshal.Cast<int, byte>(entityIDs)); | ||||
| 			state.Components.CopyTo(MemoryMarshal.Cast<TComponent, byte>(components)); | ||||
| 
 | ||||
| 			entityIDToStorageIndex.Clear(); | ||||
| 			for (var i = 0; i < state.Count; i += 1) | ||||
| 			{ | ||||
| 				entityIDToStorageIndex[entityIDs[i]] = i; | ||||
| 			} | ||||
| 
 | ||||
| 			nextID = state.Count; | ||||
| 			return new ComponentStorage<TComponent>(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -52,11 +52,6 @@ namespace MoonTools.ECS | |||
| 			return ComponentDepot.GetSingletonEntity<TComponent>(); | ||||
| 		} | ||||
| 
 | ||||
| 		protected bool Exists(in Entity entity) | ||||
| 		{ | ||||
| 			return EntityStorage.Exists(entity); | ||||
| 		} | ||||
| 
 | ||||
| 		protected IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : unmanaged | ||||
| 		{ | ||||
| 			return RelationDepot.Relations<TRelationKind>(); | ||||
|  |  | |||
|  | @ -7,11 +7,14 @@ namespace MoonTools.ECS | |||
| 		private int nextID = 0; | ||||
| 		// FIXME: why is this duplicated? | ||||
| 		private readonly Stack<int> availableIDs = new Stack<int>(); | ||||
| 		// FIXME: this is only needed in debug mode | ||||
| 		private readonly HashSet<int> availableIDHash = new HashSet<int>(); | ||||
| 
 | ||||
| 		private Dictionary<int, HashSet<int>> EntityToComponentTypeIndices = new Dictionary<int, HashSet<int>>(); | ||||
| 		private Dictionary<int, HashSet<int>> EntityToRelationTypeIndices = new Dictionary<int, HashSet<int>>(); | ||||
| 
 | ||||
| 		public int Count => nextID - availableIDs.Count; | ||||
| 
 | ||||
| 		public Entity Create() | ||||
| 		{ | ||||
| 			var entity = new Entity(NextID()); | ||||
|  | @ -70,6 +73,21 @@ namespace MoonTools.ECS | |||
| 			return EntityToRelationTypeIndices[entityID]; | ||||
| 		} | ||||
| 
 | ||||
| 		public void Clear() | ||||
| 		{ | ||||
| 			nextID = 0; | ||||
| 			foreach (var componentSet in EntityToComponentTypeIndices.Values) | ||||
| 			{ | ||||
| 				componentSet.Clear(); | ||||
| 			} | ||||
| 			foreach (var relationSet in EntityToRelationTypeIndices.Values) | ||||
| 			{ | ||||
| 				relationSet.Clear(); | ||||
| 			} | ||||
| 			availableIDs.Clear(); | ||||
| 			availableIDHash.Clear(); | ||||
| 		} | ||||
| 
 | ||||
| 		private int NextID() | ||||
| 		{ | ||||
| 			if (availableIDs.Count > 0) | ||||
|  |  | |||
|  | @ -84,32 +84,5 @@ namespace MoonTools.ECS | |||
| 		{ | ||||
| 			Count = 0; | ||||
| 		} | ||||
| 
 | ||||
| 		public void Save(IndexableSetState<T> state) | ||||
| 		{ | ||||
| 			ReadOnlySpan<byte> arrayBytes = MemoryMarshal.Cast<T, byte>(array); | ||||
| 
 | ||||
| 			if (arrayBytes.Length > state.Array.Length) | ||||
| 			{ | ||||
| 				Array.Resize(ref state.Array, arrayBytes.Length); | ||||
| 			} | ||||
| 
 | ||||
| 			arrayBytes.CopyTo(state.Array); | ||||
| 
 | ||||
| 			state.Count = Count; | ||||
| 		} | ||||
| 
 | ||||
| 		public void Load(IndexableSetState<T> state) | ||||
| 		{ | ||||
| 			state.Array.CopyTo(MemoryMarshal.Cast<T, byte>(array)); | ||||
| 
 | ||||
| 			indices.Clear(); | ||||
| 			for (var i = 0; i < state.Count; i += 1) | ||||
| 			{ | ||||
| 				indices[array[i]] = i; | ||||
| 			} | ||||
| 
 | ||||
| 			Count = state.Count; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -6,9 +6,6 @@ namespace MoonTools.ECS | |||
| { | ||||
| 	internal abstract class RelationStorage | ||||
| 	{ | ||||
| 		public abstract RelationStorageState CreateState(); | ||||
| 		public abstract void Save(RelationStorageState state); | ||||
| 		public abstract void Load(RelationStorageState state); | ||||
| 		public abstract void UnrelateAll(int entityID); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -228,60 +225,5 @@ namespace MoonTools.ECS | |||
| 			hashSet.Clear(); | ||||
| 			listPool.Push(hashSet); | ||||
| 		} | ||||
| 
 | ||||
| 		public override RelationStorageState CreateState() | ||||
| 		{ | ||||
| 			return RelationStorageState.Create<TRelation>(count); | ||||
| 		} | ||||
| 
 | ||||
| 		public override void Save(RelationStorageState state) | ||||
| 		{ | ||||
| 			ReadOnlySpan<byte> relationBytes = MemoryMarshal.Cast<Relation, byte>(relations); | ||||
| 
 | ||||
| 			if (relationBytes.Length > state.Relations.Length) | ||||
| 			{ | ||||
| 				Array.Resize(ref state.Relations, relationBytes.Length); | ||||
| 			} | ||||
| 			relationBytes.CopyTo(state.Relations); | ||||
| 
 | ||||
| 			ReadOnlySpan<byte> relationDataBytes = MemoryMarshal.Cast<TRelation, byte>(relationDatas); | ||||
| 
 | ||||
| 			if (relationDataBytes.Length > state.RelationDatas.Length) | ||||
| 			{ | ||||
| 				Array.Resize(ref state.RelationDatas, relationDataBytes.Length); | ||||
| 			} | ||||
| 			relationDataBytes.CopyTo(state.RelationDatas); | ||||
| 
 | ||||
| 			state.Count = count; | ||||
| 		} | ||||
| 
 | ||||
| 		public override void Load(RelationStorageState state) | ||||
| 		{ | ||||
| 			state.Relations.CopyTo(MemoryMarshal.Cast<Relation, byte>(relations)); | ||||
| 			state.RelationDatas.CopyTo(MemoryMarshal.Cast<TRelation, byte>(relationDatas)); | ||||
| 
 | ||||
| 			indices.Clear(); | ||||
| 			outRelations.Clear(); | ||||
| 			inRelations.Clear(); | ||||
| 			for (var i = 0; i < state.Count; i += 1) | ||||
| 			{ | ||||
| 				var relation = relations[i]; | ||||
| 				indices[relation] = i; | ||||
| 
 | ||||
| 				if (!outRelations.ContainsKey(relation.A.ID)) | ||||
| 				{ | ||||
| 					outRelations[relation.A.ID] = AcquireHashSetFromPool(); | ||||
| 				} | ||||
| 				outRelations[relation.A.ID].Add(relation.B.ID); | ||||
| 
 | ||||
| 				if (!inRelations.ContainsKey(relation.B.ID)) | ||||
| 				{ | ||||
| 					inRelations[relation.B.ID] = AcquireHashSetFromPool(); | ||||
| 				} | ||||
| 				inRelations[relation.B.ID].Add(relation.A.ID); | ||||
| 			} | ||||
| 
 | ||||
| 			count = state.Count; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,66 @@ | |||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	public class Snapshot | ||||
| 	{ | ||||
| 		private World World; | ||||
| 		private Filter? Filter; | ||||
| 
 | ||||
| 		private EntityStorage SnapshotEntityStorage; | ||||
| 		private ComponentDepot SnapshotComponentDepot; | ||||
| 
 | ||||
| 		internal Snapshot(World world) | ||||
| 		{ | ||||
| 			World = world; | ||||
| 			SnapshotEntityStorage = new EntityStorage(); | ||||
| 			SnapshotComponentDepot = new ComponentDepot(World.ComponentTypeIndices); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Take(Filter filter) | ||||
| 		{ | ||||
| 			Clear(); | ||||
| 			Filter = filter; | ||||
| 			SnapshotComponentDepot.FillMissingStorages(World.ComponentDepot); | ||||
| 
 | ||||
| 			foreach (var worldEntity in filter.Entities) | ||||
| 			{ | ||||
| 				var snapshotEntity = SnapshotEntityStorage.Create(); | ||||
| 				foreach (var componentTypeIndex in World.EntityStorage.ComponentTypeIndices(worldEntity.ID)) | ||||
| 				{ | ||||
| 					SnapshotEntityStorage.SetComponent(snapshotEntity.ID, componentTypeIndex); | ||||
| 					SnapshotComponentDepot.Set(snapshotEntity.ID, componentTypeIndex, World.ComponentDepot.UntypedGet(worldEntity.ID, componentTypeIndex)); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public void Restore() | ||||
| 		{ | ||||
| 			if (Filter == null) | ||||
| 			{ | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			foreach (var entity in Filter.Entities) | ||||
| 			{ | ||||
| 				World.Destroy(entity); | ||||
| 			} | ||||
| 
 | ||||
| 			for (var i = 0; i < SnapshotEntityStorage.Count; i += 1) | ||||
| 			{ | ||||
| 				var entity = World.CreateEntity(); | ||||
| 
 | ||||
| 				foreach (var componentTypeIndex in SnapshotEntityStorage.ComponentTypeIndices(i)) | ||||
| 				{ | ||||
| 					World.EntityStorage.SetComponent(entity.ID, componentTypeIndex); | ||||
| 					World.FilterStorage.Check(entity.ID, componentTypeIndex); | ||||
| 					World.ComponentDepot.Set(entity.ID, componentTypeIndex, SnapshotComponentDepot.UntypedGet(i, componentTypeIndex)); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void Clear() | ||||
| 		{ | ||||
| 			SnapshotEntityStorage.Clear(); | ||||
| 			SnapshotComponentDepot.Clear(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,11 +0,0 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	internal class ComponentDepotState | ||||
| 	{ | ||||
| 		public Dictionary<Type, ComponentStorageState> StorageStates = new Dictionary<Type, ComponentStorageState>(); | ||||
| 		public Dictionary<FilterSignature, IndexableSetState<int>> FilterStates = new Dictionary<FilterSignature, IndexableSetState<int>>(); | ||||
| 	} | ||||
| } | ||||
|  | @ -1,27 +0,0 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
|     internal class ComponentStorageState | ||||
|     { | ||||
| 		public int Count; | ||||
| 		public byte[] EntityIDs; | ||||
| 		public byte[] Components; | ||||
| 
 | ||||
|         public unsafe static ComponentStorageState Create<TComponent>(int count) where TComponent : unmanaged | ||||
|         { | ||||
| 			return new ComponentStorageState( | ||||
|                 count, | ||||
|                 count * sizeof(int), | ||||
|                 count * sizeof(TComponent) | ||||
|             ); | ||||
| 		} | ||||
| 
 | ||||
|         private ComponentStorageState(int count, int entityIDSize, int componentSize) | ||||
|         { | ||||
| 			Count = count; | ||||
| 			EntityIDs = new byte[entityIDSize]; | ||||
| 			Components = new byte[componentSize]; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,13 +0,0 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
|     internal class EntityStorageState | ||||
|     { | ||||
| 		public int NextID; | ||||
| 		public List<int> availableIDs = new List<int>(); | ||||
| 
 | ||||
| 		public Dictionary<int, HashSet<int>> EntityToComponentTypeIndices = new Dictionary<int, HashSet<int>>(); | ||||
| 		public Dictionary<int, HashSet<int>> EntityToRelationTypeIndices = new Dictionary<int, HashSet<int>>(); | ||||
| 	} | ||||
| } | ||||
|  | @ -1,16 +0,0 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
|     internal class IndexableSetState<T> where T : unmanaged | ||||
|     { | ||||
| 		public int Count; | ||||
| 		public byte[] Array; | ||||
| 
 | ||||
|         public unsafe IndexableSetState(int count) | ||||
|         { | ||||
| 			Count = count; | ||||
| 			Array = new byte[sizeof(T) * count]; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,10 +0,0 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
|     internal class RelationDepotState | ||||
|     { | ||||
| 		public Dictionary<Type, RelationStorageState> StorageStates = new Dictionary<Type, RelationStorageState>(); | ||||
| 	} | ||||
| } | ||||
|  | @ -1,27 +0,0 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	internal class RelationStorageState | ||||
| 	{ | ||||
| 		public int Count; | ||||
| 		public byte[] Relations; | ||||
| 		public byte[] RelationDatas; | ||||
| 
 | ||||
| 		public unsafe static RelationStorageState Create<TRelation>(int count) where TRelation : unmanaged | ||||
| 		{ | ||||
| 			return new RelationStorageState( | ||||
| 				count, | ||||
| 				count * sizeof(Relation), | ||||
| 				count * sizeof(TRelation) | ||||
| 			); | ||||
| 		} | ||||
| 
 | ||||
| 		private RelationStorageState(int count, int relationSize, int relationDataSize) | ||||
| 		{ | ||||
| 			Count = count; | ||||
| 			Relations = new byte[relationSize]; | ||||
| 			RelationDatas = new byte[relationDataSize]; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,16 +0,0 @@ | |||
| namespace MoonTools.ECS | ||||
| { | ||||
|     public class WorldState | ||||
|     { | ||||
| 		internal readonly ComponentDepotState ComponentDepotState; | ||||
| 		internal readonly EntityStorageState EntityStorageState; | ||||
| 		internal readonly RelationDepotState RelationDepotState; | ||||
| 
 | ||||
| 		public WorldState() | ||||
|         { | ||||
| 			ComponentDepotState = new ComponentDepotState(); | ||||
| 			EntityStorageState = new EntityStorageState(); | ||||
| 			RelationDepotState = new RelationDepotState(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -11,27 +11,9 @@ namespace MoonTools.ECS | |||
| 
 | ||||
| 		public abstract void Update(TimeSpan delta); | ||||
| 
 | ||||
| 		protected Entity CreateEntity() | ||||
| 		{ | ||||
| 			return EntityStorage.Create(); | ||||
| 		} | ||||
| 		protected Entity CreateEntity() => World.CreateEntity(); | ||||
| 
 | ||||
| 		protected void Set<TComponent>(in Entity entity, in TComponent component) where TComponent : unmanaged | ||||
| 		{ | ||||
| #if DEBUG | ||||
| 			// check for use after destroy | ||||
| 			if (!Exists(entity)) | ||||
| 			{ | ||||
| 				throw new ArgumentException("This entity is not valid!"); | ||||
| 			} | ||||
| #endif | ||||
| 			if (EntityStorage.SetComponent(entity.ID, ComponentTypeIndices.GetIndex<TComponent>())) | ||||
| 			{ | ||||
| 				FilterStorage.Check<TComponent>(entity.ID); | ||||
| 			} | ||||
| 
 | ||||
| 			ComponentDepot.Set<TComponent>(entity.ID, component); | ||||
| 		} | ||||
| 		protected void Set<TComponent>(in Entity entity, in TComponent component) where TComponent : unmanaged => World.Set<TComponent>(entity, component); | ||||
| 
 | ||||
| 		protected void Remove<TComponent>(in Entity entity) where TComponent : unmanaged | ||||
| 		{ | ||||
|  | @ -42,27 +24,9 @@ namespace MoonTools.ECS | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		protected void Set<TComponent>(in Template template, in TComponent component) where TComponent : unmanaged | ||||
| 		{ | ||||
| 			var componentTypeIndex = ComponentTypeIndices.GetIndex<TComponent>(); | ||||
| 			TemplateStorage.SetComponent(template.ID, componentTypeIndex); | ||||
| 			TemplateComponentDepot.Set(template.ID, component); | ||||
| 			ComponentDepot.Register<TComponent>(componentTypeIndex); | ||||
| 		} | ||||
| 		protected void Set<TComponent>(in Template template, in TComponent component) where TComponent : unmanaged => World.Set<TComponent>(template, component); | ||||
| 
 | ||||
| 		protected Entity Instantiate(in Template template) | ||||
| 		{ | ||||
| 			var entity = EntityStorage.Create(); | ||||
| 
 | ||||
| 			foreach (var componentTypeIndex in TemplateStorage.ComponentTypeIndices(template.ID)) | ||||
| 			{ | ||||
| 				EntityStorage.SetComponent(entity.ID, componentTypeIndex); | ||||
| 				FilterStorage.Check(entity.ID, componentTypeIndex); | ||||
| 				ComponentDepot.Set(entity.ID, componentTypeIndex, TemplateComponentDepot.UntypedGet(template.ID, componentTypeIndex)); | ||||
| 			} | ||||
| 
 | ||||
| 			return entity; | ||||
| 		} | ||||
| 		protected Entity Instantiate(in Template template) => World.Instantiate(template); | ||||
| 
 | ||||
| 		protected ReadOnlySpan<TMessage> ReadMessages<TMessage>() where TMessage : unmanaged | ||||
| 		{ | ||||
|  | @ -128,20 +92,6 @@ namespace MoonTools.ECS | |||
| 			EntityStorage.RemoveRelation(entity.ID, RelationTypeIndices.GetIndex<TRelationKind>()); | ||||
| 		} | ||||
| 
 | ||||
| 		protected void Destroy(in Entity entity) | ||||
| 		{ | ||||
| 			foreach (var componentTypeIndex in EntityStorage.ComponentTypeIndices(entity.ID)) | ||||
| 			{ | ||||
| 				ComponentDepot.Remove(entity.ID, componentTypeIndex); | ||||
| 				FilterStorage.RemoveEntity(entity.ID, componentTypeIndex); | ||||
| 			} | ||||
| 
 | ||||
| 			foreach (var relationTypeIndex in EntityStorage.RelationTypeIndices(entity.ID)) | ||||
| 			{ | ||||
| 				RelationDepot.UnrelateAll(entity.ID, relationTypeIndex); | ||||
| 			} | ||||
| 
 | ||||
| 			EntityStorage.Destroy(entity); | ||||
| 		} | ||||
| 		protected void Destroy(in Entity entity) => World.Destroy(entity); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ namespace MoonTools.ECS | |||
| 	{ | ||||
| 		Dictionary<Type, int> TypeToIndex = new Dictionary<Type, int>(); | ||||
| 		int nextID = 0; | ||||
| 		public int Count => TypeToIndex.Count; | ||||
| 
 | ||||
| 		public int GetIndex<T>() where T : unmanaged | ||||
| 		{ | ||||
|  | @ -24,6 +25,7 @@ namespace MoonTools.ECS | |||
| 			return TypeToIndex[type]; | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| #if DEBUG | ||||
| 		public IEnumerable<Type> Types => TypeToIndex.Keys; | ||||
| #endif | ||||
|  |  | |||
							
								
								
									
										39
									
								
								src/World.cs
								
								
								
								
							
							
						
						
									
										39
									
								
								src/World.cs
								
								
								
								
							|  | @ -1,4 +1,6 @@ | |||
| namespace MoonTools.ECS | ||||
| using System; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	public class World | ||||
| 	{ | ||||
|  | @ -9,11 +11,11 @@ | |||
| 		internal readonly MessageDepot MessageDepot = new MessageDepot(); | ||||
| 		internal readonly RelationDepot RelationDepot; | ||||
| 		internal readonly FilterStorage FilterStorage; | ||||
| 		public FilterBuilder FilterBuilder => new FilterBuilder(FilterStorage, ComponentTypeIndices); | ||||
| 
 | ||||
| 		internal readonly TemplateStorage TemplateStorage = new TemplateStorage(); | ||||
| 		internal readonly ComponentDepot TemplateComponentDepot; | ||||
| 
 | ||||
| 
 | ||||
| 		public World() | ||||
| 		{ | ||||
| 			ComponentDepot = new ComponentDepot(ComponentTypeIndices); | ||||
|  | @ -29,6 +31,13 @@ | |||
| 
 | ||||
| 		public void Set<TComponent>(Entity entity, in TComponent component) where TComponent : unmanaged | ||||
| 		{ | ||||
| #if DEBUG | ||||
| 			// check for use after destroy | ||||
| 			if (!EntityStorage.Exists(entity)) | ||||
| 			{ | ||||
| 				throw new InvalidOperationException("This entity is not valid!"); | ||||
| 			} | ||||
| #endif | ||||
| 			if (EntityStorage.SetComponent(entity.ID, ComponentTypeIndices.GetIndex<TComponent>())) | ||||
| 			{ | ||||
| 				FilterStorage.Check<TComponent>(entity.ID); | ||||
|  | @ -44,11 +53,12 @@ | |||
| 
 | ||||
| 		public void Set<TComponent>(in Template template, in TComponent component) where TComponent : unmanaged | ||||
| 		{ | ||||
| 			TemplateStorage.SetComponent(template.ID, ComponentTypeIndices.GetIndex<TComponent>()); | ||||
| 			var componentTypeIndex = ComponentTypeIndices.GetIndex<TComponent>(); | ||||
| 			TemplateStorage.SetComponent(template.ID, componentTypeIndex); | ||||
| 			TemplateComponentDepot.Set(template.ID, component); | ||||
| 			ComponentDepot.Register<TComponent>(componentTypeIndex); | ||||
| 		} | ||||
| 
 | ||||
| 		// TODO: TEST ME!!! | ||||
| 		public Entity Instantiate(in Template template) | ||||
| 		{ | ||||
| 			var entity = EntityStorage.Create(); | ||||
|  | @ -68,14 +78,31 @@ | |||
| 			MessageDepot.Add(message); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Destroy(in Entity entity) | ||||
| 		{ | ||||
| 			foreach (var componentTypeIndex in EntityStorage.ComponentTypeIndices(entity.ID)) | ||||
| 			{ | ||||
| 				ComponentDepot.Remove(entity.ID, componentTypeIndex); | ||||
| 				FilterStorage.RemoveEntity(entity.ID, componentTypeIndex); | ||||
| 			} | ||||
| 
 | ||||
| 			foreach (var relationTypeIndex in EntityStorage.RelationTypeIndices(entity.ID)) | ||||
| 			{ | ||||
| 				RelationDepot.UnrelateAll(entity.ID, relationTypeIndex); | ||||
| 			} | ||||
| 
 | ||||
| 			EntityStorage.Destroy(entity); | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 		public void FinishUpdate() | ||||
| 		{ | ||||
| 			MessageDepot.Clear(); | ||||
| 		} | ||||
| 
 | ||||
| 		public WorldState CreateState() | ||||
| 		public Snapshot CreateSnapshot() | ||||
| 		{ | ||||
| 			return new WorldState(); | ||||
| 			return new Snapshot(this); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue