Davaris Posted July 3, 2010 Share Posted July 3, 2010 I thought I'd post this here, because we are writing C# code and I don't want to keep bugging the C++ people with what we are doing. This is the original thread, if you want to see what we were talking about: http://leadwerks.com/werkspace/index.php?/topic/2150-component-propertyattribute-design/ What I am working on is similar to Rick's component idea but is also very different, in that you no longer have objects containing private data and the functions that operate on them. You have data as a separate entity and functions as separate entities. When the functions want to do something, they access the data pool. The other big idea, is you can stack data on top of each other, in a hierarchy to build up complexity and if you write a wrapper class (AKA Decorator) as described below, you can share a common pool of data with all your game entities. I took the idea from this excellent article. Read it to get an idea of what my code does: http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html You can write a wrapper class for it that provides a second parent pointer, so you can share all the parent data among your game entities base data. All it has to do is change StateCore's parent pointer to its own, before it performs an operation and then restore it when it is complete. As for permission, you are free to use this code in commercial or free projects, as long as you take full responsibility if it causes any damage. Also if you see a way to improve it, let me know as I am a C# newbie. TBH, it is probably safer to get the general idea and write your own. namespace Game { public class StateCore { // OrderedDictionary sorts as it inserts (bah!) // LinkedHashMap maintains insertion order, but you have to buy a decent one // and I don't know if it works on anything other than PC private OrderedDictionary<string, object> mList; private string mName; private StateCore mParent; public const string cBlank = "$_Blank_$"; private bool mIsReadOnly; public string Name { get { return mName; } set { mName = value; } } public OrderedDictionary<string, object> List { get { return mList; } } public StateCore Parent { get { return mParent; } set { mParent = value; } } public bool IsReadOnly { get { return mIsReadOnly; } set { mIsReadOnly = value; } } public StateCore(string name) { mName = name; mList = new OrderedDictionary<string, object>(); mParent = null; mIsReadOnly = false; } public bool Put<T>(string key, T val) { AssertIsReadOnly(); AssertTypeCompatibiltyAll<T>(key); if (PutPrivate<T>(key, val)) { DebugPrintKeyVal("Put", key); return true; } return false; } public bool Get<T>(string key, ref T ret_val) { object val; for (StateCore p = this; p != null; p = p.mParent) { if (p.mList.TryGetValue(key, out val)) { if (p.IsBlank(val)) return false;// not present p.AssertTypeCompatibiltyVal<T>(val); p.DebugPrintKeyVal("Get", key); ret_val = (T)val; return true; } } return false; // not present } public bool Has<T>(string key) { object val; for (StateCore p = this; p != null; p = p.mParent) { if (p.mList.TryGetValue(key, out val)) { if (p.IsBlank(val)) return false;// not present p.AssertTypeCompatibiltyVal<T>(val); p.DebugPrintKeyVal("Has", key); return true; } } return false;// not present } public bool Remove<T>(string key) { object val; AssertIsReadOnly(); if (mList.TryGetValue(key, out val)) { if (!IsBlank(val)) AssertTypeCompatibiltyAll<T>(key); DebugPrintKeyVal("Remove", key); mList.Remove(key); return true; } return true; } public bool SetIsBlank<T>(string key) { AssertIsReadOnly(); AssertTypeCompatibiltyAll<T>(key); if (PutPrivate(key, cBlank)) { DebugPrintKeyVal("SetIsBlank", key); return true; } return false; } public void PrintContents() { Console.WriteLine("****************************"); Console.WriteLine("PrintContents"); Console.WriteLine("****************************"); for (StateCore p = this; p != null; p = p.Parent) { Console.WriteLine(""); Console.WriteLine("CONT = {0}", p.Name); Console.WriteLine(""); foreach (KeyValuePair<string, object> entry in p.List) { if (entry.Value == null) Console.WriteLine("({0}, null) TYPE: null", entry.Key); else Console.WriteLine("({0}, {1}) TYPE: {2}", entry.Key, entry.Value, entry.Value.GetType()); Console.WriteLine(""); } } Console.WriteLine(""); } // ***************** private bool PutPrivate<T>(string key, T val) { object ret_val; // Cannot put null values if (val == null) throw new Exception("null values are not allowed"); // assert key type is allowed GameState.AssertObjectType(val.GetType()); if (mList.TryGetValue(key, out ret_val)) { if (!((T)val).Equals(ret_val)) // val will be changed { mList[key] = val; return true; } } else // new key { mList.Add(key, val); return true; } return false; // no change } private bool IsBlank(object val) { return val.GetType() == cBlank.GetType() && ((string)val) == cBlank; } private void AssertTypeCompatibiltyVal<T>(object val) { if (val.GetType() != typeof(T)) throw new Exception("Type is incompatible"); } private void AssertTypeCompatibiltyAll<T>(string key) { object val; for (StateCore p = this; p != null; p = p.mParent) { if (p.mList.TryGetValue(key, out val)) { p.AssertTypeCompatibiltyVal<T>(val); break; } } } private void DebugPrintKeyVal(string function, string key) { /* if (mList[key] == null) Console.WriteLine("{0}: ({1},null) TYPE: null, CONT: {2}", function, key, Name); else Console.WriteLine("{0}: ({1},{2}) TYPE: {3}, CONT: {4}", function, key, mList[key], mList[key].GetType(), Name); Console.WriteLine(""); */ } private void AssertIsReadOnly() { if (mIsReadOnly) throw new Exception(string.Format("{0} is read only and cannot be altered", Name)); } } } Quote Win 7 Pro 64 bit AMD Phenom II X3 720 2.8GHz GeForce 9800 GTX/9800 GTX+ 4 GB RAM Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.