diff --git a/OpenRA.Game/Network/Order.cs b/OpenRA.Game/Network/Order.cs index 46382df681..9a5cee248c 100644 --- a/OpenRA.Game/Network/Order.cs +++ b/OpenRA.Game/Network/Order.cs @@ -195,9 +195,12 @@ namespace OpenRA // Named constructors for Orders. // Now that Orders are resolved by individual Actors, these are weird; you unpack orders manually, but not pack them. - public static Order Chat(bool team, string text) + public static Order Chat(bool team, string text, int teamNumber = 0) { - return new Order(team ? "TeamChat" : "Chat", null, false) { IsImmediate = true, TargetString = text }; + if (!team) + return new Order("Chat", null, false) { IsImmediate = true, TargetString = text }; + + return new Order("TeamChat", null, false) { IsImmediate = true, TargetString = text, ExtraData = (uint)teamNumber }; } public static Order HandshakeResponse(string text) diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index 12deefd4e7..3bb9156819 100644 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -100,14 +100,25 @@ namespace OpenRA.Network if (orderManager.LocalClient == null) break; - if (client.IsObserver && (orderManager.LocalClient.IsObserver || world.IsReplay)) + var player = world.FindPlayerByClient(client); + var localClientIsObserver = orderManager.LocalClient.IsObserver || (world.LocalPlayer != null && world.LocalPlayer.WinState != WinState.Undefined); + + // ExtraData gives us the team number, 0 means Spectators + if (order.ExtraData == 0 && (localClientIsObserver || world.IsReplay)) { - Game.AddChatLine(client.Color, "[Spectators] " + client.Name, message); + // Validate before adding the line + if (client.IsObserver || (player != null && player.WinState != WinState.Undefined)) + Game.AddChatLine(client.Color, "[Spectators] " + client.Name, message); + break; } - if (client.Team == orderManager.LocalClient.Team || world.IsReplay) - Game.AddChatLine(client.Color, "[Team" + (world.IsReplay ? " " + client.Team : "") + "] " + client.Name, message); + var valid = client.Team == order.ExtraData && player != null && player.WinState == WinState.Undefined; + var isSameTeam = order.ExtraData == orderManager.LocalClient.Team && world.LocalPlayer != null + && world.LocalPlayer.WinState == WinState.Undefined; + + if (valid && (isSameTeam || world.IsReplay)) + Game.AddChatLine(client.Color, "[Team" + (world.IsReplay ? " " + order.ExtraData : "") + "] " + client.Name, message); break; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs index 402a15d392..c50d493b53 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs @@ -124,7 +124,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (chatText.Text != "") { if (!chatText.Text.StartsWith("/", StringComparison.Ordinal)) - orderManager.IssueOrder(Order.Chat(team, chatText.Text.Trim())); + { + // This should never happen, but avoid a crash if it does somehow (chat will just stay open) + if (!isObserver && orderManager.LocalClient == null && world.LocalPlayer == null) + return true; + + var teamNumber = (isObserver || world.LocalPlayer.WinState != WinState.Undefined) ? 0 : orderManager.LocalClient.Team; + orderManager.IssueOrder(Order.Chat(team, chatText.Text.Trim(), teamNumber)); + } else if (chatTraits != null) { var text = chatText.Text.Trim(); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index 136b22149a..f445a3c3f0 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -402,7 +402,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic // Always scroll to bottom when we've typed something lobbyChatPanel.ScrollToBottom(); - orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text)); + var teamNumber = 0; + if (teamChat && orderManager.LocalClient != null && !orderManager.LocalClient.IsObserver) + teamNumber = orderManager.LocalClient.Team; + + orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text, teamNumber)); chatTextField.Text = ""; return true; };