PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Classes/Object/ObjectContainer.cs

http://github.com/Concliff/Maze
C# | 307 lines | 190 code | 40 blank | 77 comment | 34 complexity | ef1c6fa1e7d2ce7b609ee0bfdfe731aa MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace Maze.Classes
  6. {
  7. /// <summary>
  8. /// Represents the storage of all existing Objects in the game.
  9. /// </summary>
  10. public sealed class ObjectContainer
  11. {
  12. #region Singleton Part
  13. private static ObjectContainer instance;
  14. /// <summary>
  15. /// Gets reference to the ObjectContainer instance.
  16. /// </summary>
  17. public static ObjectContainer Instance
  18. {
  19. get
  20. {
  21. if (instance == null)
  22. instance = new ObjectContainer();
  23. return instance;
  24. }
  25. private set { ;}
  26. }
  27. #endregion
  28. public static uint GUIDCounter;
  29. /// <summary>
  30. /// Safety check for changing objects while they are under Update.
  31. /// </summary>
  32. private bool isUpdating;
  33. private List<Object> objects;
  34. private Stack<Object> objectsToRemove;
  35. private Stack<Object> objectsToAdd;
  36. private Stack<uint> releasedGUIDs;
  37. /// <summary>
  38. /// Contains Unit instances by their location.
  39. /// </summary>
  40. private Dictionary<GridLocation, List<Unit>> unitContainer;
  41. /// <summary>
  42. /// Contains GridObject instances by their location.
  43. /// </summary>
  44. private Dictionary<GridLocation, List<GridObject>> gridObjectContainer;
  45. private ObjectContainer()
  46. {
  47. this.objects = new List<Object>();
  48. this.objectsToRemove = new Stack<Object>();
  49. this.objectsToAdd = new Stack<Object>();
  50. this.releasedGUIDs = new Stack<uint>();
  51. GUIDCounter = 0;
  52. this.isUpdating = false;
  53. this.unitContainer = new Dictionary<GridLocation, List<Unit>>();
  54. this.gridObjectContainer = new Dictionary<GridLocation, List<GridObject>>();
  55. }
  56. /// <summary>
  57. /// Inserts new object into ObjectContainer and defines its GUID.
  58. /// </summary>
  59. /// <param name="newObject">Reference to the recentry created object.</param>
  60. /// <returns>New object GUID</returns>
  61. public uint CreateObject(Object newObject)
  62. {
  63. if (this.isUpdating)
  64. this.objectsToAdd.Push(newObject);
  65. else
  66. {
  67. AddNewObject(newObject);
  68. }
  69. // Define GUID of the new object
  70. if (this.releasedGUIDs.Count > 0)
  71. return this.releasedGUIDs.Pop();
  72. else
  73. return ++GUIDCounter;
  74. }
  75. /*
  76. // Temporary Disable this method
  77. public Object GetObjectByGUID(uint GUID)
  78. {
  79. for (int i = 0; i < this.objects.Count; ++i)
  80. if (this.objects[i].GetGUID() == GUID)
  81. return this.objects[i];
  82. return null;
  83. }*/
  84. /// <summary>
  85. /// Returns all Objects at specified location.
  86. /// </summary>
  87. public List<Object> GetObjects(GridLocation location)
  88. {
  89. // Get List<Unit> and List<GridObject>
  90. // Cast them to List<Object>
  91. // And then add to summary list
  92. List<Object> objects = new List<Object>();
  93. objects.AddRange(GetGridObjects(location).Cast<Object>());
  94. objects.AddRange(GetUnits(location).Cast<Object>());
  95. return objects;
  96. }
  97. /// <summary>
  98. /// Returns all GridObjects at specified location.
  99. /// </summary>
  100. public List<GridObject> GetGridObjects(GridLocation location)
  101. {
  102. List<GridObject> objects;
  103. if (this.gridObjectContainer.TryGetValue(location, out objects))
  104. {
  105. return objects;
  106. }
  107. return new List<GridObject>();
  108. }
  109. /// <summary>
  110. /// Returns all Units at specified location.
  111. /// </summary>
  112. public List<Unit> GetUnits(GridLocation location)
  113. {
  114. List<Unit> objects;
  115. if (this.unitContainer.TryGetValue(location, out objects))
  116. {
  117. return objects;
  118. }
  119. return new List<Unit>();
  120. }
  121. /// <summary>
  122. /// Updates all Objects on current Map.
  123. /// </summary>
  124. /// <param name="timeP">Timer Tick Time.</param>
  125. public void UpdateState(int timeP)
  126. {
  127. this.isUpdating = true;
  128. foreach (Object obj in this.objectsToAdd)
  129. {
  130. AddNewObject(obj);
  131. }
  132. this.objectsToAdd.Clear();
  133. // Update each object or add to RemoveStack
  134. foreach (Object objectF in this.objects)
  135. {
  136. if (objectF.ObjectState == ObjectStates.Removed)
  137. {
  138. this.objectsToRemove.Push(objectF);
  139. }
  140. else
  141. {
  142. objectF.UpdateState(timeP);
  143. }
  144. }
  145. RemoveTaggedObjects();
  146. this.isUpdating = false;
  147. }
  148. /// <summary>
  149. /// Delete all objects, which is tagged as 'Removed'.
  150. /// </summary>
  151. private void RemoveTaggedObjects()
  152. {
  153. // Delete all removed objects
  154. int removeCount = this.objectsToRemove.Count;
  155. if (removeCount == 0) // Skip deletion
  156. return;
  157. for (int i = 0; i < removeCount; ++i)
  158. {
  159. Object objectToRemove = this.objectsToRemove.Pop();
  160. // Store free GUIDs
  161. releasedGUIDs.Push(objectToRemove.GUID);
  162. // Remove from common List
  163. this.objects.Remove(objectToRemove);
  164. // Remove from specific container
  165. if (objectToRemove.ObjectType == ObjectTypes.GridObject)
  166. RemoveObject<GridObject>(this.gridObjectContainer, objectToRemove.Position.Location, (GridObject)objectToRemove);
  167. else
  168. RemoveObject<Unit>(this.unitContainer, objectToRemove.Position.Location, (Unit)objectToRemove);
  169. }
  170. this.objectsToRemove.Clear();
  171. }
  172. /// <summary>
  173. /// Places object into appropriate container and common objects List
  174. /// </summary>
  175. private void AddNewObject(Object newObject)
  176. {
  177. // Add GridObject
  178. if (newObject.ObjectType == ObjectTypes.GridObject)
  179. {
  180. AddNewObject<GridObject>(this.gridObjectContainer, (GridObject)newObject);
  181. }
  182. // Add Unit
  183. else if (newObject.ObjectType == ObjectTypes.Slug || newObject.ObjectType == ObjectTypes.Unit)
  184. {
  185. AddNewObject<Unit>(this.unitContainer, (Unit)newObject);
  186. }
  187. // Do not add any other object types
  188. else
  189. return;
  190. // Place object into common list
  191. this.objects.Add(newObject);
  192. newObject.LocationChanged += OnObjectLocationChanged;
  193. }
  194. private void AddNewObject<T>(Dictionary<GridLocation, List<T>> container, T newObject) where T : Object
  195. {
  196. List<T> objects;
  197. // Exists at this Location
  198. if (container.TryGetValue(newObject.Position.Location, out objects))
  199. {
  200. objects.Add((T)newObject);
  201. }
  202. // Add new
  203. else
  204. {
  205. objects = new List<T>() { newObject };
  206. container.Add(newObject.Position.Location, objects);
  207. }
  208. }
  209. private void RemoveObject<T>(Dictionary<GridLocation, List<T>> container, GridLocation location, T obj)
  210. {
  211. List<T> objects;
  212. if (container.TryGetValue(location, out objects))
  213. {
  214. objects.Remove(obj);
  215. // List is empty
  216. // Remove from dictionary
  217. if (objects.Count == 0)
  218. container.Remove(location);
  219. }
  220. }
  221. /// <summary>
  222. /// Calls Unit.StartMotion for every unit object.
  223. /// </summary>
  224. public void StartMotion()
  225. {
  226. foreach (KeyValuePair<GridLocation, List<Unit>> kvp in this.unitContainer)
  227. {
  228. foreach(Unit unit in kvp.Value)
  229. unit.StartMotion();
  230. }
  231. }
  232. /// <summary>
  233. /// Removes all Objects except Slug
  234. /// </summary>
  235. public void ClearEnvironment(bool isRemoveSlug)
  236. {
  237. foreach (Object objectF in this.objects)
  238. {
  239. if (objectF.ObjectType == ObjectTypes.Slug && !isRemoveSlug)
  240. continue;
  241. this.objectsToRemove.Push(objectF);
  242. }
  243. }
  244. private void OnObjectLocationChanged(object sender, PositionEventArgs e)
  245. {
  246. // Relocate object, changing its Key in the container.
  247. if (((Object)sender).ObjectType == ObjectTypes.GridObject)
  248. {
  249. RelocateObject<GridObject>(this.gridObjectContainer, e.PrevPosition.Location, e.NewPosition.Location, (GridObject)sender);
  250. }
  251. else if (((Object)sender).ObjectType == ObjectTypes.Slug || ((Object)sender).ObjectType == ObjectTypes.Unit)
  252. {
  253. RelocateObject<Unit>(this.unitContainer, e.PrevPosition.Location, e.NewPosition.Location, (Unit)sender);
  254. }
  255. }
  256. /// <summary>
  257. /// Move Object to another location Key within its container
  258. /// </summary>
  259. private void RelocateObject<T>(Dictionary<GridLocation, List<T>> container, GridLocation prevLocation, GridLocation newLocation, T obj) where T : Object
  260. {
  261. // Remove from prev location
  262. RemoveObject<T>(container, prevLocation, obj);
  263. // Add this object as a new one
  264. AddNewObject<T>(container, obj);
  265. }
  266. }
  267. }