From ebf3ec0e90734d07a292a7aa234b81ed79ef4e23 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 28 May 2018 12:01:23 +0000 Subject: [PATCH] Add some basic safeguards around RenderPlayer.set. --- OpenRA.Game/Player.cs | 18 +++++++++++++++ OpenRA.Game/Traits/TraitsInterfaces.cs | 3 +++ OpenRA.Game/World.cs | 23 +++++++++++++++---- .../Traits/Player/DeveloperMode.cs | 4 +++- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/OpenRA.Game/Player.cs b/OpenRA.Game/Player.cs index 16ce3e0bf2..3933ecce50 100644 --- a/OpenRA.Game/Player.cs +++ b/OpenRA.Game/Player.cs @@ -68,6 +68,20 @@ namespace OpenRA public Shroud Shroud; public World World { get; private set; } + readonly bool inMissionMap; + readonly IUnlocksRenderPlayer[] unlockRenderPlayer; + + public bool UnlockedRenderPlayer + { + get + { + if (unlockRenderPlayer.Any(x => x.RenderPlayerUnlocked)) + return true; + + return WinState != WinState.Undefined && !inMissionMap; + } + } + readonly StanceColors stanceColors; static FactionInfo ChooseFaction(World world, string name, bool requireSelectable = true) @@ -105,6 +119,8 @@ namespace OpenRA InternalName = pr.Name; PlayerReference = pr; + inMissionMap = world.Map.Visibility.HasFlag(MapVisibility.MissionSelector); + // Real player or host-created bot if (client != null) { @@ -156,6 +172,8 @@ namespace OpenRA stanceColors.Allies = ChromeMetrics.Get("PlayerStanceColorAllies"); stanceColors.Enemies = ChromeMetrics.Get("PlayerStanceColorEnemies"); stanceColors.Neutrals = ChromeMetrics.Get("PlayerStanceColorNeutrals"); + + unlockRenderPlayer = PlayerActor.TraitsImplementing().ToArray(); } public override string ToString() diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index c468982700..dbc8c1c3e5 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -467,4 +467,7 @@ namespace OpenRA.Traits return playerName + " " + BoolValues[newValue] + " " + Name + "."; } } + + [RequireExplicitImplementation] + public interface IUnlocksRenderPlayer { bool RenderPlayerUnlocked { get; } } } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index da964ae239..58641d327b 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -73,8 +73,16 @@ namespace OpenRA Player renderPlayer; public Player RenderPlayer { - get { return renderPlayer == null || (renderPlayer.WinState != WinState.Undefined && !Map.Visibility.HasFlag(MapVisibility.MissionSelector)) ? null : renderPlayer; } - set { renderPlayer = value; } + get + { + return renderPlayer; + } + + set + { + if (LocalPlayer == null || LocalPlayer.UnlockedRenderPlayer) + renderPlayer = value; + } } public bool FogObscures(Actor a) { return RenderPlayer != null && !a.CanBeViewedByPlayer(RenderPlayer); } @@ -101,7 +109,9 @@ namespace OpenRA return; LocalPlayer = localPlayer; - RenderPlayer = LocalPlayer; + + // Set the property backing field directly + renderPlayer = LocalPlayer; } public readonly Actor WorldActor; @@ -410,7 +420,12 @@ namespace OpenRA ret += n++ * Sync.Hash(sync); // Hash the shared random number generator. - ret += SharedRandom.Last; + ret += SharedRandom.Last; + + // Hash player RenderPlayer status + foreach (var p in Players) + if (p.UnlockedRenderPlayer) + ret += Sync.HashPlayer(p); return ret; } diff --git a/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs b/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs index b2a0230e4b..a34d072cf5 100644 --- a/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs +++ b/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs @@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits public object Create(ActorInitializer init) { return new DeveloperMode(this); } } - public class DeveloperMode : IResolveOrder, ISync, INotifyCreated + public class DeveloperMode : IResolveOrder, ISync, INotifyCreated, IUnlocksRenderPlayer { readonly DeveloperModeInfo info; public bool Enabled { get; private set; } @@ -245,5 +245,7 @@ namespace OpenRA.Mods.Common.Traits Game.Debug("Cheat used: {0} by {1}", order.OrderString, self.Owner.PlayerName); } + + bool IUnlocksRenderPlayer.RenderPlayerUnlocked { get { return Enabled; } } } }