store entity state + some garbage optimizations
							parent
							
								
									be95e80265
								
							
						
					
					
						commit
						190d1413ca
					
				|  | @ -221,36 +221,31 @@ namespace MoonTools.ECS | |||
| 			TypesWithDisabledSerialization.Add(typeof(TComponent)); | ||||
| 		} | ||||
| 
 | ||||
| 		public ComponentDepotState CreateState() | ||||
| 		{ | ||||
| 			return new ComponentDepotState(); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Serialize(ComponentDepotState state) | ||||
| 		{ | ||||
| 			// FIXME: this is creating garbage | ||||
| 			state.StorageStates.Clear(); | ||||
| 			foreach (var (type, storage) in storages) | ||||
| 			{ | ||||
| 				// FIXME: we could cache this | ||||
| 				if (!TypesWithDisabledSerialization.Contains(type)) | ||||
| 				{ | ||||
| 					var storageState = storage.CreateState(); | ||||
| 					storage.Serialize(storageState); | ||||
| 					state.StorageStates.Add(type, storageState); | ||||
| 					if (!state.StorageStates.ContainsKey(type)) | ||||
| 					{ | ||||
| 						state.StorageStates.Add(type, storage.CreateState()); | ||||
| 					} | ||||
| 
 | ||||
| 					storage.Serialize(state.StorageStates[type]); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// FIXME: this is creating garbage | ||||
| 			state.FilterStates.Clear(); | ||||
| 			foreach (var (signature, set) in filterSignatureToEntityIDs) | ||||
| 			{ | ||||
| 				// FIXME: we could cache this | ||||
| 				if (!signature.Included.Overlaps(TypesWithDisabledSerialization) && !signature.Excluded.Overlaps(TypesWithDisabledSerialization)) | ||||
| 				{ | ||||
| 					var setState = new IndexableSetState<int>(set.Count); | ||||
| 					set.Save(setState); | ||||
| 					state.FilterStates[signature] = setState; | ||||
| 					if (!state.FilterStates.ContainsKey(signature)) | ||||
| 					{ | ||||
| 						state.FilterStates[signature] = new IndexableSetState<int>(set.Count); | ||||
| 					} | ||||
| 					set.Save(state.FilterStates[signature]); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -1,22 +1,75 @@ | |||
| namespace MoonTools.ECS | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	internal class EntityStorage | ||||
| 	{ | ||||
| 		public IDStorage idStorage = new IDStorage(); | ||||
| 		private int nextID = 0; | ||||
| 		private readonly Stack<int> availableIDs = new Stack<int>(); | ||||
| 		private readonly HashSet<int> availableIDHash = new HashSet<int>(); | ||||
| 
 | ||||
| 		public Entity Create() | ||||
| 		{ | ||||
| 			return new Entity(idStorage.NextID()); | ||||
| 			return new Entity(NextID()); | ||||
| 		} | ||||
| 
 | ||||
| 		public bool Exists(in Entity entity) | ||||
| 		{ | ||||
| 			return idStorage.Taken(entity.ID); | ||||
| 			return Taken(entity.ID); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Destroy(in Entity entity) | ||||
| 		{ | ||||
| 			idStorage.Release(entity.ID); | ||||
| 			Release(entity.ID); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Serialize(EntityStorageState state) | ||||
| 		{ | ||||
| 			state.NextID = nextID; | ||||
| 			state.availableIDs.Clear(); | ||||
| 			foreach (var id in availableIDs) | ||||
| 			{ | ||||
| 				state.availableIDs.Add(id); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public void Deserialize(EntityStorageState state) | ||||
| 		{ | ||||
| 			nextID = state.NextID; | ||||
| 			availableIDs.Clear(); | ||||
| 			availableIDHash.Clear(); | ||||
| 			foreach (var id in state.availableIDs) | ||||
| 			{ | ||||
| 				availableIDs.Push(id); | ||||
| 				availableIDHash.Add(id); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private int NextID() | ||||
| 		{ | ||||
| 			if (availableIDs.Count > 0) | ||||
| 			{ | ||||
| 				var id = availableIDs.Pop(); | ||||
| 				availableIDHash.Remove(id); | ||||
| 				return id; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				var id = nextID; | ||||
| 				nextID += 1; | ||||
| 				return id; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private bool Taken(int id) | ||||
| 		{ | ||||
| 			return !availableIDHash.Contains(id) && id < nextID; | ||||
| 		} | ||||
| 
 | ||||
| 		private void Release(int id) | ||||
| 		{ | ||||
| 			availableIDs.Push(id); | ||||
| 			availableIDHash.Add(id); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,39 +0,0 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	internal class IDStorage | ||||
| 	{ | ||||
| 		private int nextID = 0; | ||||
| 
 | ||||
| 		private readonly Stack<int> availableIDs = new Stack<int>(); | ||||
| 		private readonly HashSet<int> availableIDHash = new HashSet<int>(); | ||||
| 
 | ||||
| 		public int NextID() | ||||
| 		{ | ||||
| 			if (availableIDs.Count > 0) | ||||
| 			{ | ||||
| 				var id = availableIDs.Pop(); | ||||
| 				availableIDHash.Remove(id); | ||||
| 				return id; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				var id = nextID; | ||||
| 				nextID += 1; | ||||
| 				return id; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public bool Taken(int id) | ||||
| 		{ | ||||
| 			return !availableIDHash.Contains(id) && id < nextID; | ||||
| 		} | ||||
| 
 | ||||
| 		public void Release(int id) | ||||
| 		{ | ||||
| 			availableIDs.Push(id); | ||||
| 			availableIDHash.Add(id); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -3,7 +3,7 @@ using System.Collections.Generic; | |||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	public class ComponentDepotState | ||||
| 	internal class ComponentDepotState | ||||
| 	{ | ||||
| 		public Dictionary<Type, ComponentStorageState> StorageStates = new Dictionary<Type, ComponentStorageState>(); | ||||
| 		public Dictionary<FilterSignature, IndexableSetState<int>> FilterStates = new Dictionary<FilterSignature, IndexableSetState<int>>(); | ||||
|  | @ -2,8 +2,7 @@ using System.Collections.Generic; | |||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
| 	// for saving and loading component storage | ||||
|     public class ComponentStorageState | ||||
|     internal class ComponentStorageState | ||||
|     { | ||||
| 		public int Count; | ||||
| 		public Dictionary<int, int> EntityIdToStorageIndex; | ||||
|  | @ -0,0 +1,10 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
|     internal class EntityStorageState | ||||
|     { | ||||
| 		public int NextID; | ||||
| 		public List<int> availableIDs = new List<int>(); | ||||
| 	} | ||||
| } | ||||
|  | @ -1,9 +1,8 @@ | |||
| using System.Collections.Generic; | ||||
| using System.Runtime.InteropServices; | ||||
| 
 | ||||
| namespace MoonTools.ECS | ||||
| { | ||||
|     public class IndexableSetState<T> where T : unmanaged | ||||
|     internal class IndexableSetState<T> where T : unmanaged | ||||
|     { | ||||
| 		public int Count; | ||||
| 		public Dictionary<T, int> Indices; | ||||
|  | @ -0,0 +1,14 @@ | |||
| namespace MoonTools.ECS | ||||
| { | ||||
|     public class WorldState | ||||
|     { | ||||
| 		internal ComponentDepotState ComponentDepotState; | ||||
| 		internal EntityStorageState EntityStorageState; | ||||
| 
 | ||||
| 		public WorldState() | ||||
|         { | ||||
| 			ComponentDepotState = new ComponentDepotState(); | ||||
| 			EntityStorageState = new EntityStorageState(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/World.cs
								
								
								
								
							
							
						
						
									
										17
									
								
								src/World.cs
								
								
								
								
							|  | @ -32,16 +32,21 @@ | |||
| 			ComponentDepot.DisableSerialization<TComponent>(); | ||||
| 		} | ||||
| 
 | ||||
| 		public ComponentDepotState Serialize() | ||||
| 		public WorldState CreateState() | ||||
| 		{ | ||||
| 			var state = ComponentDepot.CreateState(); | ||||
| 			ComponentDepot.Serialize(state); | ||||
| 			return state; | ||||
| 			return new WorldState(); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Deserialize(ComponentDepotState state) | ||||
| 		public void Serialize(WorldState state) | ||||
| 		{ | ||||
| 			ComponentDepot.Deserialize(state); | ||||
| 			ComponentDepot.Serialize(state.ComponentDepotState); | ||||
| 			EntityStorage.Serialize(state.EntityStorageState); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Deserialize(WorldState state) | ||||
| 		{ | ||||
| 			ComponentDepot.Deserialize(state.ComponentDepotState); | ||||
| 			EntityStorage.Deserialize(state.EntityStorageState); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue