/src/Mooege/Net/GS/Message/GameAttributeMap.cs

https://github.com/K42/mooege · C# · 328 lines · 265 code · 37 blank · 26 comment · 52 complexity · 9cd687aaf2ddc931d9c84753238b8bee MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 mooege project
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. */
  18. using System;
  19. using System.Collections.Generic;
  20. using Mooege.Net.GS.Message.Definitions.Attribute;
  21. namespace Mooege.Net.GS.Message
  22. {
  23. public class GameAttributeMap
  24. {
  25. struct KeyId
  26. {
  27. // was using Id | (Key << 12) like Blizz at first but im not 100% sure it will work... /cm
  28. public int Id;
  29. public int? Key;
  30. public override bool Equals(object obj)
  31. {
  32. if (obj is KeyId)
  33. {
  34. var other = (KeyId)obj;
  35. if (Key.HasValue != other.Key.HasValue)
  36. return false;
  37. if (Key.HasValue && Key.Value != other.Key.Value)
  38. return false;
  39. return Id == other.Id;
  40. }
  41. return false;
  42. }
  43. public override int GetHashCode()
  44. {
  45. if (Key.HasValue)
  46. return Id | (Key.Value << 12);
  47. return Id;
  48. }
  49. }
  50. private HashSet<KeyId> _changedAttributes = new HashSet<KeyId>();
  51. private Dictionary<KeyId, GameAttributeValue> _attributeValues = new Dictionary<KeyId, GameAttributeValue>();
  52. public int Count { get { return _attributeValues.Count; } }
  53. public int ChangedCount { get { return _changedAttributes.Count; } }
  54. public void SendMessage(GameClient client, uint actorID)
  55. {
  56. var list = GetMessageList(actorID);
  57. foreach (var msg in list)
  58. client.SendMessage(msg);
  59. _changedAttributes.Clear();
  60. }
  61. /// <summary>
  62. /// Send only the changed attributes. How nice is that?
  63. /// </summary>
  64. /// <param name="client">the client we send it to</param>
  65. /// <param name="actorID">the actor this attribs belong to</param>
  66. public void SendChangedMessage(GameClient client, uint actorID)
  67. {
  68. var list = GetChangedMessageList(actorID);
  69. foreach (var msg in list)
  70. client.SendMessage(msg);
  71. _changedAttributes.Clear();
  72. }
  73. public void SendChangedMessage(IEnumerable<GameClient> clients, uint actorID)
  74. {
  75. if (_changedAttributes.Count == 0)
  76. return;
  77. var list = GetChangedMessageList(actorID);
  78. foreach (var msg in list)
  79. {
  80. foreach(var client in clients)
  81. client.SendMessage(msg);
  82. }
  83. _changedAttributes.Clear();
  84. }
  85. public void ClearChanged()
  86. {
  87. _changedAttributes.Clear();
  88. }
  89. public GameAttributeMap CombineMap(GameAttributeMap map)
  90. {
  91. Dictionary<KeyId, GameAttributeValue> mapValues = map._attributeValues;
  92. if (mapValues.Count == 0)
  93. {
  94. return this;
  95. }
  96. var e = mapValues.GetEnumerator();
  97. while (e.MoveNext())
  98. {
  99. if (_attributeValues.ContainsKey(e.Current.Key))
  100. {
  101. _attributeValues[e.Current.Key] = e.Current.Value;
  102. }
  103. else
  104. {
  105. _attributeValues.Add(e.Current.Key, e.Current.Value);
  106. }
  107. _changedAttributes.Add(e.Current.Key);
  108. }
  109. return this;
  110. }
  111. public GameAttributeMap AddMap(GameAttributeMap map)
  112. {
  113. Dictionary<KeyId, GameAttributeValue> mapValues = map._attributeValues;
  114. if (mapValues.Count == 0)
  115. {
  116. return this;
  117. }
  118. var e = mapValues.GetEnumerator();
  119. while (e.MoveNext())
  120. {
  121. if (_attributeValues.ContainsKey(e.Current.Key))
  122. {
  123. if (mapValues[e.Current.Key].ValueF != 0f)
  124. {
  125. // guess it's float
  126. _attributeValues[e.Current.Key] = new GameAttributeValue(_attributeValues[e.Current.Key].ValueF + mapValues[e.Current.Key].ValueF);
  127. }
  128. else if (mapValues[e.Current.Key].Value != 0)
  129. {
  130. // guess it's int or true boolean
  131. _attributeValues[e.Current.Key] = new GameAttributeValue(_attributeValues[e.Current.Key].Value + mapValues[e.Current.Key].Value);
  132. } // 0 in both fields means nothing to add
  133. }
  134. else
  135. {
  136. _attributeValues.Add(e.Current.Key, e.Current.Value);
  137. }
  138. }
  139. return this;
  140. }
  141. public List<GameMessage> GetMessageList(uint actorID)
  142. {
  143. var e = _attributeValues.Keys.GetEnumerator();
  144. return GetMessageListFromEnumerator(actorID, e, _attributeValues.Count);
  145. }
  146. public List<GameMessage> GetChangedMessageList(uint actorID)
  147. {
  148. var e = _changedAttributes.GetEnumerator();
  149. return GetMessageListFromEnumerator(actorID, e, _changedAttributes.Count);
  150. }
  151. private List<GameMessage> GetMessageListFromEnumerator(uint actorID, IEnumerator<KeyId> e, int count)
  152. {
  153. var messageList = new List<GameMessage>();
  154. if (count == 0)
  155. return messageList;
  156. if (count == 1)
  157. {
  158. AttributeSetValueMessage msg = new AttributeSetValueMessage();
  159. if (!e.MoveNext())
  160. throw new Exception("Expected value in enumerator.");
  161. var keyid = e.Current;
  162. var value = _attributeValues[keyid];
  163. int id = keyid.Id;
  164. msg.ActorID = actorID;
  165. msg.Field1 = new Fields.NetAttributeKeyValue();
  166. msg.Field1.Field0 = keyid.Key;
  167. // FIXME: need to rework NetAttributeKeyValue, and maybe rename GameAttribute to NetAttribute?
  168. msg.Field1.Attribute = GameAttribute.Attributes[id]; // FIXME
  169. if (msg.Field1.Attribute.IsInteger)
  170. msg.Field1.Int = value.Value;
  171. else
  172. msg.Field1.Float = value.ValueF;
  173. messageList.Add(msg);
  174. }
  175. else
  176. {
  177. // FIXME: probably need to rework AttributesSetValues as well a bit
  178. if (count >= 15)
  179. {
  180. for (; count >= 15; count -= 15)
  181. {
  182. AttributesSetValuesMessage msg = new AttributesSetValuesMessage();
  183. msg.ActorID = actorID;
  184. msg.atKeyVals = new Fields.NetAttributeKeyValue[15];
  185. for (int i = 0; i < 15; i++)
  186. msg.atKeyVals[i] = new Fields.NetAttributeKeyValue();
  187. for (int i = 0; i < 15; i++)
  188. {
  189. if (!e.MoveNext())
  190. throw new Exception("Expected values in enumerator.");
  191. var kv = msg.atKeyVals[i];
  192. var keyid = e.Current;
  193. var value = _attributeValues[keyid];
  194. var id = keyid.Id;
  195. kv.Field0 = keyid.Key;
  196. kv.Attribute = GameAttribute.Attributes[id];
  197. if (kv.Attribute.IsInteger)
  198. kv.Int = value.Value;
  199. else
  200. kv.Float = value.ValueF;
  201. }
  202. messageList.Add(msg);
  203. }
  204. }
  205. if (count > 0)
  206. {
  207. AttributesSetValuesMessage msg = new AttributesSetValuesMessage();
  208. msg.ActorID = actorID;
  209. msg.atKeyVals = new Fields.NetAttributeKeyValue[count];
  210. for (int i = 0; i < count; i++)
  211. {
  212. if (!e.MoveNext())
  213. throw new Exception("Expected values in enumerator.");
  214. var kv = new Fields.NetAttributeKeyValue();
  215. msg.atKeyVals[i] = kv;
  216. var keyid = e.Current;
  217. var value = _attributeValues[keyid];
  218. var id = keyid.Id;
  219. kv.Field0 = keyid.Key;
  220. kv.Attribute = GameAttribute.Attributes[id];
  221. if (kv.Attribute.IsInteger)
  222. kv.Int = value.Value;
  223. else
  224. kv.Float = value.ValueF;
  225. }
  226. messageList.Add(msg);
  227. }
  228. }
  229. return messageList;
  230. }
  231. GameAttributeValue GetAttributeValue(GameAttribute attribute, int? key)
  232. {
  233. KeyId keyid;
  234. keyid.Id = attribute.Id;
  235. keyid.Key = key;
  236. GameAttributeValue gaValue;
  237. if (_attributeValues.TryGetValue(keyid, out gaValue))
  238. return gaValue;
  239. return attribute._DefaultValue;
  240. }
  241. void SetAttributeValue(GameAttribute attribute, int? key, GameAttributeValue value)
  242. {
  243. KeyId keyid;
  244. keyid.Id = attribute.Id;
  245. keyid.Key = key;
  246. if (!_changedAttributes.Contains(keyid))
  247. _changedAttributes.Add(keyid);
  248. if (attribute.EncodingType == GameAttributeEncoding.IntMinMax)
  249. {
  250. if (value.Value < attribute.Min.Value || value.Value > attribute.Max.Value)
  251. throw new ArgumentOutOfRangeException("GameAttribute." + attribute.Name.Replace(' ', '_'), "Min: " + attribute.Min.Value + " Max: " + attribute.Max.Value + " Tried to set: " + value.Value);
  252. }
  253. else if (attribute.EncodingType == GameAttributeEncoding.Float16)
  254. {
  255. if (value.ValueF < GameAttribute.Float16Min || value.ValueF > GameAttribute.Float16Max)
  256. throw new ArgumentOutOfRangeException("GameAttribute." + attribute.Name.Replace(' ', '_'), "Min: " + GameAttribute.Float16Min + " Max " + GameAttribute.Float16Max + " Tried to set: " + value.ValueF);
  257. }
  258. _attributeValues[keyid] = value;
  259. }
  260. public int this[GameAttributeI attribute]
  261. {
  262. get { return GetAttributeValue(attribute, null).Value; }
  263. set { SetAttributeValue(attribute, null, new GameAttributeValue(value)); }
  264. }
  265. public int this[GameAttributeI attribute, int key]
  266. {
  267. get { return GetAttributeValue(attribute, key).Value; }
  268. set { SetAttributeValue(attribute, key, new GameAttributeValue(value)); }
  269. }
  270. public float this[GameAttributeF attribute]
  271. {
  272. get { return GetAttributeValue(attribute, null).ValueF; }
  273. set { SetAttributeValue(attribute, null, new GameAttributeValue(value)); }
  274. }
  275. public float this[GameAttributeF attribute, int key]
  276. {
  277. get { return GetAttributeValue(attribute, key).ValueF; }
  278. set { SetAttributeValue(attribute, key, new GameAttributeValue(value)); }
  279. }
  280. public bool this[GameAttributeB attribute]
  281. {
  282. get { return GetAttributeValue(attribute, null).Value != 0; }
  283. set { SetAttributeValue(attribute, null, new GameAttributeValue(value ? 1 : 0)); }
  284. }
  285. public bool this[GameAttributeB attribute, int key]
  286. {
  287. get { return GetAttributeValue(attribute, key).Value != 0; }
  288. set { SetAttributeValue(attribute, key, new GameAttributeValue(value ? 1 : 0)); }
  289. }
  290. }
  291. }