diff --git a/OpenRA.Game/Sync.cs b/OpenRA.Game/Sync.cs index 7e41470919..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)(a => a.GetHashCode())).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WPos)) - { - il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WVec)) - { - il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WAngle)) - { - il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); - il.Emit(OpCodes.Xor); - } - else if (type == typeof(WRot)) - { - il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).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,38 +136,45 @@ 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; } - public static void CheckSyncUnchanged( World world, Action fn ) + public static int hash(T t) { - CheckSyncUnchanged( world, () => { fn(); return true; } ); + return t.GetHashCode(); + } + + public static void CheckSyncUnchanged(World world, Action fn) + { + 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; @@ -239,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); } } } diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 9d0466db0f..04664d7c07 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -90,8 +90,13 @@ namespace OpenRA.Traits return false; // Target ranges are calculated in 2D, so ignore height differences - return Positions.Any(t => (t.X - origin.X)*(t.X - origin.X) + - (t.Y - origin.Y)*(t.Y - origin.Y) <= range.Range*range.Range); + var rangeSquared = range.Range*range.Range; + return Positions.Any(t => + { + var dx = (long)(t.X - origin.X); + var dy = (long)(t.Y - origin.Y); + return dx*dx + dy*dy <= rangeSquared; + }); } } diff --git a/OpenRA.Game/Widgets/BackgroundWidget.cs b/OpenRA.Game/Widgets/BackgroundWidget.cs index a4fd1321ec..936e568c4b 100644 --- a/OpenRA.Game/Widgets/BackgroundWidget.cs +++ b/OpenRA.Game/Widgets/BackgroundWidget.cs @@ -30,8 +30,12 @@ namespace OpenRA.Widgets public override bool HandleMouseInput(MouseInput mi) { - if (ClickThrough) return false; - if (!Draggable || moving && (!TakeFocus(mi) || mi.Button != MouseButton.Left)) return true; + if (ClickThrough || !Bounds.Contains(mi.Location)) + return false; + + if (!Draggable || moving && (!TakeFocus(mi) || mi.Button != MouseButton.Left)) + return true; + if (prevMouseLocation == null) prevMouseLocation = mi.Location; var vec = mi.Location - (int2)prevMouseLocation; @@ -51,6 +55,7 @@ namespace OpenRA.Widgets Bounds = new Rectangle(Bounds.X + vec.X, Bounds.Y + vec.Y, Bounds.Width, Bounds.Height); break; } + return true; } diff --git a/OpenRA.Mods.RA/Widgets/RadarWidget.cs b/OpenRA.Mods.RA/Widgets/RadarWidget.cs index 6e4f57c716..36539fdefe 100755 --- a/OpenRA.Mods.RA/Widgets/RadarWidget.cs +++ b/OpenRA.Mods.RA/Widgets/RadarWidget.cs @@ -22,14 +22,15 @@ namespace OpenRA.Mods.RA.Widgets public int AnimationLength = 5; public string RadarOnlineSound = null; public string RadarOfflineSound = null; - public Func IsEnabled = () => false; + public Func IsEnabled = () => true; public Action AfterOpen = () => {}; public Action AfterClose = () => {}; float radarMinimapHeight; - int frame = 0; - bool hasRadar = false; - int updateTicks = 0; + int frame; + bool hasRadar; + bool cachedEnabled; + int updateTicks; float previewScale = 0; int2 previewOrigin = int2.Zero; @@ -43,7 +44,10 @@ namespace OpenRA.Mods.RA.Widgets readonly World world; [ObjectCreator.UseCtor] - public RadarWidget(World world) { this.world = world; } + public RadarWidget(World world) + { + this.world = world; + } public override void Initialize(WidgetArgs args) { @@ -85,7 +89,7 @@ namespace OpenRA.Mods.RA.Widgets Modifiers = Game.GetModifierKeys() }; - var cursor = world.OrderGenerator.GetCursor( world, loc, mi ); + var cursor = world.OrderGenerator.GetCursor(world, loc, mi); if (cursor == null) return "default"; @@ -94,10 +98,10 @@ namespace OpenRA.Mods.RA.Widgets public override bool HandleMouseInput(MouseInput mi) { - if (!hasRadar) - return true; - if (!mapRect.Contains(mi.Location)) + return false; + + if (!hasRadar) return true; var loc = MinimapPixelToCell(mi.Location); @@ -127,8 +131,6 @@ namespace OpenRA.Mods.RA.Widgets return true; } - public override Rectangle EventBounds { get { return mapRect; } } - public override void Draw() { if (world == null) @@ -157,7 +159,6 @@ namespace OpenRA.Mods.RA.Widgets } } - bool cachedEnabled; public override void Tick() { // Update the radar animation even when its closed