diff --git a/OpenRA.Game/Sync.cs b/OpenRA.Game/Sync.cs index 78881db317..94f5a3cb32 100755 --- a/OpenRA.Game/Sync.cs +++ b/OpenRA.Game/Sync.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; @@ -22,19 +23,36 @@ namespace OpenRA public static class Sync { - static Cache> hashFuncCache = new Cache>( t => GenerateHashFunc( t ) ); + static Cache> hashFuncCache = new Cache>(t => GenerateHashFunc(t)); - public static int CalculateSyncHash( object obj ) + public static int CalculateSyncHash(object obj) { - return hashFuncCache[ obj.GetType() ]( obj ); + return hashFuncCache[obj.GetType()](obj); } + static Dictionary hashFunctions = new Dictionary() + { + {typeof(int2), ((Func)hash_int2).Method}, + {typeof(CPos), ((Func)hash_CPos).Method}, + {typeof(CVec), ((Func)hash_CVec).Method}, + {typeof(PPos), ((Func)hash_PPos).Method}, + {typeof(PVecInt), ((Func)hash_PVecInt).Method}, + {typeof(PSubPos), ((Func)hash_PSubPos).Method}, + {typeof(PSubVec), ((Func)hash_PSubVec).Method}, + {typeof(WRange), ((Func)hash).Method}, + {typeof(WPos), ((Func)hash).Method}, + {typeof(WVec), ((Func)hash).Method}, + {typeof(WAngle), ((Func)hash).Method}, + {typeof(WRot), ((Func)hash).Method}, + {typeof(TypeDictionary), ((Func)hash_tdict).Method}, + {typeof(Actor), ((Func)hash_actor).Method}, + {typeof(Player), ((Func)hash_player).Method}, + }; + static void EmitSyncOpcodes(Type type, ILGenerator il) { - if (type == typeof(int)) - { - il.Emit(OpCodes.Xor); - } + if (hashFunctions.ContainsKey(type)) + il.EmitCall(OpCodes.Call, hashFunctions[type], null); else if (type == typeof(bool)) { var l = il.DefineLabel(); @@ -43,90 +61,13 @@ namespace OpenRA il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldc_I4, 0x555); il.MarkLabel(l); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(int2)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_int2).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(CPos)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_CPos).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(CVec)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_CVec).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(PPos)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_PPos).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(PVecInt)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_PVecInt).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(PSubPos)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_PSubPos).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(PSubVec)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_PSubVec).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WRange)) - { - il.EmitCall(OpCodes.Call, ((Func)hash).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WPos)) - { - il.EmitCall(OpCodes.Call, ((Func)hash).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WVec)) - { - il.EmitCall(OpCodes.Call, ((Func)hash).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WAngle)) - { - il.EmitCall(OpCodes.Call, ((Func)hash).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WRot)) - { - il.EmitCall(OpCodes.Call, ((Func)hash).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(TypeDictionary)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_tdict).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(Actor)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_actor).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(Player)) - { - il.EmitCall(OpCodes.Call, ((Func)hash_player).Method, null); - il.Emit(OpCodes.Xor); } else if (type.HasAttribute()) - { il.EmitCall(OpCodes.Call, ((Func)CalculateSyncHash).Method, null); - il.Emit(OpCodes.Xor); - } - else + else if (type != typeof(int)) throw new NotImplementedException("SyncAttribute on member of unhashable type: {0}".F(type.FullName)); + + il.Emit(OpCodes.Xor); } public static Func GenerateHashFunc(Type t) @@ -160,29 +101,29 @@ namespace OpenRA return (Func)d.CreateDelegate(typeof(Func)); } - public static int hash_int2( int2 i2 ) + public static int hash_int2(int2 i2) { - return ( ( i2.X * 5 ) ^ ( i2.Y * 3 ) ) / 4; + return ((i2.X * 5) ^ (i2.Y * 3)) / 4; } - public static int hash_CPos( CPos i2 ) + public static int hash_CPos(CPos i2) { - return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4; + return ((i2.X * 5) ^ (i2.Y * 3)) / 4; } - public static int hash_CVec( CVec i2 ) + public static int hash_CVec(CVec i2) { - return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4; + return ((i2.X * 5) ^ (i2.Y * 3)) / 4; } - public static int hash_PPos( PPos i2 ) + public static int hash_PPos(PPos i2) { - return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4; + return ((i2.X * 5) ^ (i2.Y * 3)) / 4; } - public static int hash_PVecInt( PVecInt i2 ) + public static int hash_PVecInt(PVecInt i2) { - return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4; + return ((i2.X * 5) ^ (i2.Y * 3)) / 4; } public static int hash_PSubPos(PSubPos i2) @@ -195,25 +136,25 @@ namespace OpenRA return ((i2.X * 5) ^ (i2.Y * 3)) / 4; } - public static int hash_tdict( TypeDictionary d ) + public static int hash_tdict(TypeDictionary d) { int ret = 0; - foreach( var o in d ) - ret += CalculateSyncHash( o ); + foreach (var o in d) + ret += CalculateSyncHash(o); return ret; } - public static int hash_actor( Actor a ) + public static int hash_actor(Actor a) { - if( a != null ) - return (int)( a.ActorID << 16 ); + if (a != null) + return (int)(a.ActorID << 16); return 0; } - public static int hash_player( Player p ) + public static int hash_player(Player p) { - if( p != null ) - return (int)( p.PlayerActor.ActorID << 16 ) * 0x567; + if (p != null) + return (int)(p.PlayerActor.ActorID << 16) * 0x567; return 0; } @@ -222,16 +163,18 @@ namespace OpenRA return t.GetHashCode(); } - public static void CheckSyncUnchanged( World world, Action fn ) + public static void CheckSyncUnchanged(World world, Action fn) { - CheckSyncUnchanged( world, () => { fn(); return true; } ); + CheckSyncUnchanged(world, () => { fn(); return true; }); } static bool inUnsyncedCode = false; - public static T CheckSyncUnchanged( World world, Func fn ) + public static T CheckSyncUnchanged(World world, Func fn) { - if( world == null ) return fn(); + if (world == null) + return fn(); + var shouldCheckSync = Game.Settings.Debug.SanityCheckUnsyncedCode; int sync = shouldCheckSync ? world.SyncHash() : 0; bool prevInUnsyncedCode = inUnsyncedCode; @@ -244,15 +187,15 @@ namespace OpenRA finally { inUnsyncedCode = prevInUnsyncedCode; - if( shouldCheckSync && sync != world.SyncHash() ) - throw new InvalidOperationException( "CheckSyncUnchanged: sync-changing code may not run here" ); + if (shouldCheckSync && sync != world.SyncHash()) + throw new InvalidOperationException("CheckSyncUnchanged: sync-changing code may not run here"); } } - public static void AssertUnsynced( string message ) + public static void AssertUnsynced(string message) { - if( !inUnsyncedCode ) - throw new InvalidOperationException( message ); + if (!inUnsyncedCode) + throw new InvalidOperationException(message); } } }