diff --git a/.editorconfig b/.editorconfig index 30946753a6..02295b6d10 100644 --- a/.editorconfig +++ b/.editorconfig @@ -427,10 +427,7 @@ dotnet_diagnostic.IDE0077.severity = warning ### Formatting Rules (IDE0055) ### https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0055 - -# We may eventually wish to enforce this rule, however some existing formatting conflicts with the rule despite being reasonable. -# Additionally, the rule is buggy and likes to report spuriously after invoking Format Document in the IDE. -dotnet_diagnostic.IDE0055.severity = none +dotnet_diagnostic.IDE0055.severity = warning #dotnet_sort_system_directives_first = true #dotnet_separate_import_directive_groups = false @@ -448,7 +445,7 @@ dotnet_diagnostic.IDE0055.severity = none #csharp_indent_labels = one_less_than_current #csharp_indent_block_contents = true #csharp_indent_braces = false -#csharp_indent_case_contents_when_block = true +csharp_indent_case_contents_when_block = false #csharp_space_after_cast = false #csharp_space_after_keywords_in_control_flow_statements = true diff --git a/OpenRA.Game/FileFormats/Png.cs b/OpenRA.Game/FileFormats/Png.cs index f6588207ff..6a229d9bb7 100644 --- a/OpenRA.Game/FileFormats/Png.cs +++ b/OpenRA.Game/FileFormats/Png.cs @@ -50,7 +50,7 @@ namespace OpenRA.FileFormats var length = IPAddress.NetworkToHostOrder(s.ReadInt32()); var type = s.ReadASCII(4); var content = s.ReadBytes(length); - /*var crc = */s.ReadInt32(); + s.ReadInt32(); // crc if (!headerParsed && type != "IHDR") throw new InvalidDataException("Invalid PNG file - header does not appear first."); @@ -76,7 +76,7 @@ namespace OpenRA.FileFormats Data = new byte[Width * Height * PixelStride]; var compression = ms.ReadUInt8(); - /*var filter = */ms.ReadUInt8(); + ms.ReadUInt8(); // filter var interlace = ms.ReadUInt8(); if (compression != 0) diff --git a/OpenRA.Game/Graphics/ModelVertex.cs b/OpenRA.Game/Graphics/ModelVertex.cs index 42ffbf6e6d..0eecad7a9a 100644 --- a/OpenRA.Game/Graphics/ModelVertex.cs +++ b/OpenRA.Game/Graphics/ModelVertex.cs @@ -43,7 +43,7 @@ namespace OpenRA.Graphics : base("model") { } - public override ShaderVertexAttribute[] Attributes { get; } = new[] + public override ShaderVertexAttribute[] Attributes { get; } = new[] { new ShaderVertexAttribute("aVertexPosition", ShaderVertexAttributeType.Float, 3, 0), new ShaderVertexAttribute("aVertexTexCoord", ShaderVertexAttributeType.Float, 4, 12), diff --git a/OpenRA.Game/Graphics/TerrainSpriteLayer.cs b/OpenRA.Game/Graphics/TerrainSpriteLayer.cs index 58913cd21b..802e5e85b9 100644 --- a/OpenRA.Game/Graphics/TerrainSpriteLayer.cs +++ b/OpenRA.Game/Graphics/TerrainSpriteLayer.cs @@ -55,7 +55,7 @@ namespace OpenRA.Graphics indexRowStride = 6 * map.MapSize.X; lock (IndexBuffers) - { + { indexBufferWrapper = IndexBuffers.GetValue(world, world => new IndexBufferRc(world)); indexBufferWrapper.AddRef(); } diff --git a/OpenRA.Game/Graphics/Vertex.cs b/OpenRA.Game/Graphics/Vertex.cs index c3b90d1cd4..9e31c99279 100644 --- a/OpenRA.Game/Graphics/Vertex.cs +++ b/OpenRA.Game/Graphics/Vertex.cs @@ -53,7 +53,7 @@ namespace OpenRA.Graphics : base("combined") { } - public override ShaderVertexAttribute[] Attributes { get; } = new[] + public override ShaderVertexAttribute[] Attributes { get; } = new[] { new ShaderVertexAttribute("aVertexPosition", ShaderVertexAttributeType.Float, 3, 0), new ShaderVertexAttribute("aVertexTexCoord", ShaderVertexAttributeType.Float, 4, 12), diff --git a/OpenRA.Game/Map/ActorReference.cs b/OpenRA.Game/Map/ActorReference.cs index c82c55bdf3..e42483ba6c 100644 --- a/OpenRA.Game/Map/ActorReference.cs +++ b/OpenRA.Game/Map/ActorReference.cs @@ -152,8 +152,9 @@ namespace OpenRA // If a more specific init is not available, fall back to an unnamed init. // If duplicate inits are defined, take the last to match standard yaml override expectations if (info != null && !string.IsNullOrEmpty(info.InstanceName)) - return inits.LastOrDefault(i => i.InstanceName == info.InstanceName) ?? - inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName)); + return + inits.LastOrDefault(i => i.InstanceName == info.InstanceName) ?? + inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName)); // Untagged traits will only use untagged inits return inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName)); diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index a84111212a..a2e365b1ad 100644 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -58,158 +58,158 @@ namespace OpenRA.Network // Client side translated server message case "LocalizedMessage": - { - if (string.IsNullOrEmpty(order.TargetString)) - break; - - var yaml = MiniYaml.FromString(order.TargetString); - foreach (var node in yaml) - { - var localizedMessage = new LocalizedMessage(node.Value); - if (localizedMessage.Key == Joined) - TextNotificationsManager.AddPlayerJoinedLine(localizedMessage.Key, localizedMessage.Arguments); - else if (localizedMessage.Key == Left) - TextNotificationsManager.AddPlayerLeftLine(localizedMessage.Key, localizedMessage.Arguments); - else - TextNotificationsManager.AddSystemLine(localizedMessage.Key, localizedMessage.Arguments); - } - + { + if (string.IsNullOrEmpty(order.TargetString)) break; + + var yaml = MiniYaml.FromString(order.TargetString); + foreach (var node in yaml) + { + var localizedMessage = new LocalizedMessage(node.Value); + if (localizedMessage.Key == Joined) + TextNotificationsManager.AddPlayerJoinedLine(localizedMessage.Key, localizedMessage.Arguments); + else if (localizedMessage.Key == Left) + TextNotificationsManager.AddPlayerLeftLine(localizedMessage.Key, localizedMessage.Arguments); + else + TextNotificationsManager.AddSystemLine(localizedMessage.Key, localizedMessage.Arguments); } + break; + } + case "DisableChatEntry": - { - if (OrderNotFromServerOrWorldIsReplay(clientId, world)) - break; - - // Server may send MaxValue to indicate that it is disabled until further notice - if (order.ExtraData == uint.MaxValue) - TextNotificationsManager.ChatDisabledUntil = uint.MaxValue; - else - TextNotificationsManager.ChatDisabledUntil = Game.RunTime + order.ExtraData; - + { + if (OrderNotFromServerOrWorldIsReplay(clientId, world)) break; - } + + // Server may send MaxValue to indicate that it is disabled until further notice + if (order.ExtraData == uint.MaxValue) + TextNotificationsManager.ChatDisabledUntil = uint.MaxValue; + else + TextNotificationsManager.ChatDisabledUntil = Game.RunTime + order.ExtraData; + + break; + } case "StartKickVote": - { - if (OrderNotFromServerOrWorldIsReplay(clientId, world)) - break; - - KickVoteTarget = (int)order.ExtraData; + { + if (OrderNotFromServerOrWorldIsReplay(clientId, world)) break; - } + + KickVoteTarget = (int)order.ExtraData; + break; + } case "EndKickVote": - { - if (OrderNotFromServerOrWorldIsReplay(clientId, world)) - break; - - if (KickVoteTarget == (int)order.ExtraData) - KickVoteTarget = null; - + { + if (OrderNotFromServerOrWorldIsReplay(clientId, world)) break; - } + + if (KickVoteTarget == (int)order.ExtraData) + KickVoteTarget = null; + + break; + } case "Chat": + { + var client = orderManager.LobbyInfo.ClientWithIndex(clientId); + if (client == null) + break; + + // Cut chat messages to the hard limit to avoid exploits + var message = order.TargetString; + if (message.Length > ChatMessageMaxLength) + message = order.TargetString[..ChatMessageMaxLength]; + + // ExtraData 0 means this is a normal chat order, everything else is team chat + if (order.ExtraData == 0) { - var client = orderManager.LobbyInfo.ClientWithIndex(clientId); - if (client == null) - break; + var p = world?.FindPlayerByClient(client); + var suffix = (p != null && p.WinState == WinState.Lost) ? " (Dead)" : ""; + suffix = client.IsObserver ? " (Spectator)" : suffix; - // Cut chat messages to the hard limit to avoid exploits - var message = order.TargetString; - if (message.Length > ChatMessageMaxLength) - message = order.TargetString[..ChatMessageMaxLength]; + if (orderManager.LocalClient != null && client != orderManager.LocalClient && client.Team > 0 && client.Team == orderManager.LocalClient.Team) + suffix += " (Ally)"; - // ExtraData 0 means this is a normal chat order, everything else is team chat - if (order.ExtraData == 0) - { - var p = world?.FindPlayerByClient(client); - var suffix = (p != null && p.WinState == WinState.Lost) ? " (Dead)" : ""; - suffix = client.IsObserver ? " (Spectator)" : suffix; + TextNotificationsManager.AddChatLine(clientId, client.Name + suffix, message, client.Color); + break; + } - if (orderManager.LocalClient != null && client != orderManager.LocalClient && client.Team > 0 && client.Team == orderManager.LocalClient.Team) - suffix += " (Ally)"; - - TextNotificationsManager.AddChatLine(clientId, client.Name + suffix, message, client.Color); - break; - } - - // We are still in the lobby - if (world == null) - { - var prefix = order.ExtraData == uint.MaxValue ? "[Spectators] " : "[Team] "; - if (orderManager.LocalClient != null && client.Team == orderManager.LocalClient.Team) - TextNotificationsManager.AddChatLine(clientId, prefix + client.Name, message, client.Color); - - break; - } - - var player = world.FindPlayerByClient(client); - var localClientIsObserver = world.IsReplay || (orderManager.LocalClient != null && orderManager.LocalClient.IsObserver) - || (world.LocalPlayer != null && world.LocalPlayer.WinState != WinState.Undefined); - - // ExtraData gives us the team number, uint.MaxValue means Spectators - if (order.ExtraData == uint.MaxValue && localClientIsObserver) - { - // Validate before adding the line - if (client.IsObserver || (player != null && player.WinState != WinState.Undefined)) - TextNotificationsManager.AddChatLine(clientId, "[Spectators] " + client.Name, message, client.Color); - - break; - } - - var valid = client.Team == order.ExtraData && player != null && player.WinState == WinState.Undefined; - var isSameTeam = orderManager.LocalClient != null && order.ExtraData == orderManager.LocalClient.Team - && world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Undefined; - - if (valid && (isSameTeam || world.IsReplay)) - TextNotificationsManager.AddChatLine(clientId, "[Team" + (world.IsReplay ? " " + order.ExtraData : "") + "] " + client.Name, message, client.Color); + // We are still in the lobby + if (world == null) + { + var prefix = order.ExtraData == uint.MaxValue ? "[Spectators] " : "[Team] "; + if (orderManager.LocalClient != null && client.Team == orderManager.LocalClient.Team) + TextNotificationsManager.AddChatLine(clientId, prefix + client.Name, message, client.Color); break; } + var player = world.FindPlayerByClient(client); + var localClientIsObserver = world.IsReplay || (orderManager.LocalClient != null && orderManager.LocalClient.IsObserver) + || (world.LocalPlayer != null && world.LocalPlayer.WinState != WinState.Undefined); + + // ExtraData gives us the team number, uint.MaxValue means Spectators + if (order.ExtraData == uint.MaxValue && localClientIsObserver) + { + // Validate before adding the line + if (client.IsObserver || (player != null && player.WinState != WinState.Undefined)) + TextNotificationsManager.AddChatLine(clientId, "[Spectators] " + client.Name, message, client.Color); + + break; + } + + var valid = client.Team == order.ExtraData && player != null && player.WinState == WinState.Undefined; + var isSameTeam = orderManager.LocalClient != null && order.ExtraData == orderManager.LocalClient.Team + && world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Undefined; + + if (valid && (isSameTeam || world.IsReplay)) + TextNotificationsManager.AddChatLine(clientId, "[Team" + (world.IsReplay ? " " + order.ExtraData : "") + "] " + client.Name, message, client.Color); + + break; + } + case "StartGame": + { + if (Game.ModData.MapCache[orderManager.LobbyInfo.GlobalSettings.Map].Status != MapStatus.Available) { - if (Game.ModData.MapCache[orderManager.LobbyInfo.GlobalSettings.Map].Status != MapStatus.Available) - { - Game.Disconnect(); - Game.LoadShellMap(); + Game.Disconnect(); + Game.LoadShellMap(); - // TODO: After adding a startup error dialog, notify the replay load failure. - break; - } - - if (!string.IsNullOrEmpty(order.TargetString)) - { - var data = MiniYaml.FromString(order.TargetString); - var saveLastOrdersFrame = data.FirstOrDefault(n => n.Key == "SaveLastOrdersFrame"); - if (saveLastOrdersFrame != null) - orderManager.GameSaveLastFrame = - FieldLoader.GetValue("saveLastOrdersFrame", saveLastOrdersFrame.Value.Value); - - var saveSyncFrame = data.FirstOrDefault(n => n.Key == "SaveSyncFrame"); - if (saveSyncFrame != null) - orderManager.GameSaveLastSyncFrame = - FieldLoader.GetValue("SaveSyncFrame", saveSyncFrame.Value.Value); - } - else - TextNotificationsManager.AddSystemLine(GameStarted); - - Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map, WorldType.Regular); + // TODO: After adding a startup error dialog, notify the replay load failure. break; } + if (!string.IsNullOrEmpty(order.TargetString)) + { + var data = MiniYaml.FromString(order.TargetString); + var saveLastOrdersFrame = data.FirstOrDefault(n => n.Key == "SaveLastOrdersFrame"); + if (saveLastOrdersFrame != null) + orderManager.GameSaveLastFrame = + FieldLoader.GetValue("saveLastOrdersFrame", saveLastOrdersFrame.Value.Value); + + var saveSyncFrame = data.FirstOrDefault(n => n.Key == "SaveSyncFrame"); + if (saveSyncFrame != null) + orderManager.GameSaveLastSyncFrame = + FieldLoader.GetValue("SaveSyncFrame", saveSyncFrame.Value.Value); + } + else + TextNotificationsManager.AddSystemLine(GameStarted); + + Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map, WorldType.Regular); + break; + } + case "SaveTraitData": - { - var data = MiniYaml.FromString(order.TargetString)[0]; - var traitIndex = Exts.ParseInt32Invariant(data.Key); + { + var data = MiniYaml.FromString(order.TargetString)[0]; + var traitIndex = Exts.ParseInt32Invariant(data.Key); - world?.AddGameSaveTraitData(traitIndex, data.Value); + world?.AddGameSaveTraitData(traitIndex, data.Value); - break; - } + break; + } case "GameSaved": if (!orderManager.World.IsReplay) @@ -220,188 +220,188 @@ namespace OpenRA.Network break; case "PauseGame": + { + var client = orderManager.LobbyInfo.ClientWithIndex(clientId); + if (client != null) { - var client = orderManager.LobbyInfo.ClientWithIndex(clientId); - if (client != null) - { - var pause = order.TargetString == "Pause"; + var pause = order.TargetString == "Pause"; - // Prevent injected unpause orders from restarting a finished game - if (orderManager.World.IsGameOver && !pause) - break; + // Prevent injected unpause orders from restarting a finished game + if (orderManager.World.IsGameOver && !pause) + break; - if (orderManager.World.Paused != pause && world != null && world.LobbyInfo.NonBotClients.Count() > 1) - TextNotificationsManager.AddSystemLine(pause ? GamePaused : GameUnpaused, Translation.Arguments("player", client.Name)); + if (orderManager.World.Paused != pause && world != null && world.LobbyInfo.NonBotClients.Count() > 1) + TextNotificationsManager.AddSystemLine(pause ? GamePaused : GameUnpaused, Translation.Arguments("player", client.Name)); - orderManager.World.Paused = pause; - orderManager.World.PredictedPaused = pause; - } - - break; + orderManager.World.Paused = pause; + orderManager.World.PredictedPaused = pause; } + break; + } + case "HandshakeRequest": + { + // Switch to the server's mod if we need and are able to + var mod = Game.ModData.Manifest; + var request = HandshakeRequest.Deserialize(order.TargetString); + + var externalKey = ExternalMod.MakeKey(request.Mod, request.Version); + if ((request.Mod != mod.Id || request.Version != mod.Metadata.Version) && + Game.ExternalMods.TryGetValue(externalKey, out var external)) { - // Switch to the server's mod if we need and are able to - var mod = Game.ModData.Manifest; - var request = HandshakeRequest.Deserialize(order.TargetString); - - var externalKey = ExternalMod.MakeKey(request.Mod, request.Version); - if ((request.Mod != mod.Id || request.Version != mod.Metadata.Version) && - Game.ExternalMods.TryGetValue(externalKey, out var external)) - { - // The ConnectionFailedLogic will prompt the user to switch mods - CurrentServerSettings.ServerExternalMod = external; - orderManager.Connection.Dispose(); - break; - } - - Game.Settings.Player.Name = Settings.SanitizedPlayerName(Game.Settings.Player.Name); - Game.Settings.Save(); - - // Otherwise send the handshake with our current settings and let the server reject us - var info = new Session.Client() - { - Name = Game.Settings.Player.Name, - PreferredColor = Game.Settings.Player.Color, - Color = Game.Settings.Player.Color, - Faction = "Random", - SpawnPoint = 0, - Team = 0, - State = Session.ClientState.Invalid - }; - - var localProfile = Game.LocalPlayerProfile; - var response = new HandshakeResponse() - { - Client = info, - Mod = mod.Id, - Version = mod.Metadata.Version, - Password = CurrentServerSettings.Password, - Fingerprint = localProfile.Fingerprint, - OrdersProtocol = ProtocolVersion.Orders - }; - - if (request.AuthToken != null && response.Fingerprint != null) - response.AuthSignature = localProfile.Sign(request.AuthToken); - - orderManager.IssueOrder(new Order("HandshakeResponse", null, false) - { - Type = OrderType.Handshake, - IsImmediate = true, - TargetString = response.Serialize() - }); - + // The ConnectionFailedLogic will prompt the user to switch mods + CurrentServerSettings.ServerExternalMod = external; + orderManager.Connection.Dispose(); break; } + Game.Settings.Player.Name = Settings.SanitizedPlayerName(Game.Settings.Player.Name); + Game.Settings.Save(); + + // Otherwise send the handshake with our current settings and let the server reject us + var info = new Session.Client() + { + Name = Game.Settings.Player.Name, + PreferredColor = Game.Settings.Player.Color, + Color = Game.Settings.Player.Color, + Faction = "Random", + SpawnPoint = 0, + Team = 0, + State = Session.ClientState.Invalid + }; + + var localProfile = Game.LocalPlayerProfile; + var response = new HandshakeResponse() + { + Client = info, + Mod = mod.Id, + Version = mod.Metadata.Version, + Password = CurrentServerSettings.Password, + Fingerprint = localProfile.Fingerprint, + OrdersProtocol = ProtocolVersion.Orders + }; + + if (request.AuthToken != null && response.Fingerprint != null) + response.AuthSignature = localProfile.Sign(request.AuthToken); + + orderManager.IssueOrder(new Order("HandshakeResponse", null, false) + { + Type = OrderType.Handshake, + IsImmediate = true, + TargetString = response.Serialize() + }); + + break; + } + case "ServerError": - { - orderManager.ServerError = order.TargetString; - orderManager.AuthenticationFailed = false; - break; - } + { + orderManager.ServerError = order.TargetString; + orderManager.AuthenticationFailed = false; + break; + } case "AuthenticationError": - { - // The ConnectionFailedLogic will prompt the user for the password - orderManager.ServerError = order.TargetString; - orderManager.AuthenticationFailed = true; - break; - } + { + // The ConnectionFailedLogic will prompt the user for the password + orderManager.ServerError = order.TargetString; + orderManager.AuthenticationFailed = true; + break; + } case "SyncInfo": - { - orderManager.LobbyInfo = Session.Deserialize(order.TargetString); - Game.SyncLobbyInfo(); - break; - } + { + orderManager.LobbyInfo = Session.Deserialize(order.TargetString); + Game.SyncLobbyInfo(); + break; + } case "SyncLobbyClients": + { + var clients = new List(); + var nodes = MiniYaml.FromString(order.TargetString); + foreach (var node in nodes) { - var clients = new List(); - var nodes = MiniYaml.FromString(order.TargetString); - foreach (var node in nodes) - { - var strings = node.Key.Split('@'); - if (strings[0] == "Client") - clients.Add(Session.Client.Deserialize(node.Value)); - } - - orderManager.LobbyInfo.Clients = clients; - Game.SyncLobbyInfo(); - break; + var strings = node.Key.Split('@'); + if (strings[0] == "Client") + clients.Add(Session.Client.Deserialize(node.Value)); } + orderManager.LobbyInfo.Clients = clients; + Game.SyncLobbyInfo(); + break; + } + case "SyncLobbySlots": + { + var slots = new Dictionary(); + var nodes = MiniYaml.FromString(order.TargetString); + foreach (var node in nodes) { - var slots = new Dictionary(); - var nodes = MiniYaml.FromString(order.TargetString); - foreach (var node in nodes) + var strings = node.Key.Split('@'); + if (strings[0] == "Slot") { - var strings = node.Key.Split('@'); - if (strings[0] == "Slot") - { - var slot = Session.Slot.Deserialize(node.Value); - slots.Add(slot.PlayerReference, slot); - } + var slot = Session.Slot.Deserialize(node.Value); + slots.Add(slot.PlayerReference, slot); } - - orderManager.LobbyInfo.Slots = slots; - Game.SyncLobbyInfo(); - break; } + orderManager.LobbyInfo.Slots = slots; + Game.SyncLobbyInfo(); + break; + } + case "SyncLobbyGlobalSettings": + { + var nodes = MiniYaml.FromString(order.TargetString); + foreach (var node in nodes) { - var nodes = MiniYaml.FromString(order.TargetString); - foreach (var node in nodes) - { - var strings = node.Key.Split('@'); - if (strings[0] == "GlobalSettings") - orderManager.LobbyInfo.GlobalSettings = Session.Global.Deserialize(node.Value); - } - - Game.SyncLobbyInfo(); - break; + var strings = node.Key.Split('@'); + if (strings[0] == "GlobalSettings") + orderManager.LobbyInfo.GlobalSettings = Session.Global.Deserialize(node.Value); } + Game.SyncLobbyInfo(); + break; + } + case "SyncConnectionQuality": + { + var nodes = MiniYaml.FromString(order.TargetString); + foreach (var node in nodes) { - var nodes = MiniYaml.FromString(order.TargetString); - foreach (var node in nodes) + var strings = node.Key.Split('@'); + if (strings[0] == "ConnectionQuality") { - var strings = node.Key.Split('@'); - if (strings[0] == "ConnectionQuality") - { - var client = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.Index == Exts.ParseInt32Invariant(strings[1])); - if (client != null) - client.ConnectionQuality = FieldLoader.GetValue("ConnectionQuality", node.Value.Value); - } + var client = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.Index == Exts.ParseInt32Invariant(strings[1])); + if (client != null) + client.ConnectionQuality = FieldLoader.GetValue("ConnectionQuality", node.Value.Value); } - - break; } + break; + } + case "SyncMapPool": - { - orderManager.ServerMapPool = FieldLoader.GetValue>("SyncMapPool", order.TargetString); - break; - } + { + orderManager.ServerMapPool = FieldLoader.GetValue>("SyncMapPool", order.TargetString); + break; + } default: - { - if (world == null) - break; - - if (order.GroupedActors == null) - ResolveOrder(order, world, orderManager, clientId); - else - foreach (var subject in order.GroupedActors) - ResolveOrder(Order.FromGroupedOrder(order, subject), world, orderManager, clientId); - + { + if (world == null) break; - } + + if (order.GroupedActors == null) + ResolveOrder(order, world, orderManager, clientId); + else + foreach (var subject in order.GroupedActors) + ResolveOrder(Order.FromGroupedOrder(order, subject), world, orderManager, clientId); + + break; + } } } diff --git a/OpenRA.Game/Platform.cs b/OpenRA.Game/Platform.cs index 008ba93256..d8e7c78622 100644 --- a/OpenRA.Game/Platform.cs +++ b/OpenRA.Game/Platform.cs @@ -274,7 +274,7 @@ namespace OpenRA throw new DirectoryNotFoundException(path); if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) && - !path.EndsWith(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal)) + !path.EndsWith(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal)) path += Path.DirectorySeparatorChar; engineDirAccessed = true; diff --git a/OpenRA.Game/Primitives/Color.cs b/OpenRA.Game/Primitives/Color.cs index 520b7d028b..9fc71faeb7 100644 --- a/OpenRA.Game/Primitives/Color.cs +++ b/OpenRA.Game/Primitives/Color.cs @@ -169,12 +169,12 @@ namespace OpenRA.Primitives byte alpha = 255; if (!byte.TryParse(value.AsSpan(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var red) - || !byte.TryParse(value.AsSpan(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var green) - || !byte.TryParse(value.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var blue)) + || !byte.TryParse(value.AsSpan(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var green) + || !byte.TryParse(value.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var blue)) return false; if (value.Length == 8 - && !byte.TryParse(value.AsSpan(6, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out alpha)) + && !byte.TryParse(value.AsSpan(6, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out alpha)) return false; color = FromArgb(alpha, red, green, blue); diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index 931f32855e..b98e69b5a7 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -280,7 +280,8 @@ namespace OpenRA.Server } } } - }) { Name = $"Connection listener ({listener.LocalEndpoint})", IsBackground = true }.Start(); + }) + { Name = $"Connection listener ({listener.LocalEndpoint})", IsBackground = true }.Start(); } catch (SocketException ex) { @@ -990,70 +991,42 @@ namespace OpenRA.Server switch (o.OrderString) { case "Command": + { + var handledBy = serverTraits.WithInterface() + .FirstOrDefault(t => t.InterpretCommand(this, conn, GetClient(conn), o.TargetString)); + + if (handledBy == null) { - var handledBy = serverTraits.WithInterface() - .FirstOrDefault(t => t.InterpretCommand(this, conn, GetClient(conn), o.TargetString)); - - if (handledBy == null) - { - Log.Write("server", $"Unknown server command: {o.TargetString}"); - SendLocalizedMessageTo(conn, UnknownServerCommand, Translation.Arguments("command", o.TargetString)); - } - - break; + Log.Write("server", $"Unknown server command: {o.TargetString}"); + SendLocalizedMessageTo(conn, UnknownServerCommand, Translation.Arguments("command", o.TargetString)); } + break; + } + case "Chat": - { - if (Type == ServerType.Local || !playerMessageTracker.IsPlayerAtFloodLimit(conn)) - DispatchOrdersToClients(conn, 0, o.Serialize()); + { + if (Type == ServerType.Local || !playerMessageTracker.IsPlayerAtFloodLimit(conn)) + DispatchOrdersToClients(conn, 0, o.Serialize()); - break; - } + break; + } case "GameSaveTraitData": + { + if (GameSave != null) { - if (GameSave != null) - { - var data = MiniYaml.FromString(o.TargetString)[0]; - GameSave.AddTraitData(OpenRA.Exts.ParseInt32Invariant(data.Key), data.Value); - } - - break; + var data = MiniYaml.FromString(o.TargetString)[0]; + GameSave.AddTraitData(OpenRA.Exts.ParseInt32Invariant(data.Key), data.Value); } + break; + } + case "CreateGameSave": + { + if (GameSave != null) { - if (GameSave != null) - { - // Sanitize potentially malicious input - var filename = o.TargetString; - var invalidIndex = -1; - var invalidChars = Path.GetInvalidFileNameChars(); - while ((invalidIndex = filename.IndexOfAny(invalidChars)) != -1) - filename = filename.Remove(invalidIndex, 1); - - var baseSavePath = Path.Combine( - Platform.SupportDir, - "Saves", - ModData.Manifest.Id, - ModData.Manifest.Metadata.Version); - - if (!Directory.Exists(baseSavePath)) - Directory.CreateDirectory(baseSavePath); - - GameSave.Save(Path.Combine(baseSavePath, filename)); - DispatchServerOrdersToClients(Order.FromTargetString("GameSaved", filename, true)); - } - - break; - } - - case "LoadGameSave": - { - if (Type == ServerType.Dedicated || State >= ServerState.GameStarted) - break; - // Sanitize potentially malicious input var filename = o.TargetString; var invalidIndex = -1; @@ -1061,62 +1034,90 @@ namespace OpenRA.Server while ((invalidIndex = filename.IndexOfAny(invalidChars)) != -1) filename = filename.Remove(invalidIndex, 1); - var savePath = Path.Combine( + var baseSavePath = Path.Combine( Platform.SupportDir, "Saves", ModData.Manifest.Id, - ModData.Manifest.Metadata.Version, - filename); + ModData.Manifest.Metadata.Version); - GameSave = new GameSave(savePath); - LobbyInfo.GlobalSettings = GameSave.GlobalSettings; - LobbyInfo.Slots = GameSave.Slots; + if (!Directory.Exists(baseSavePath)) + Directory.CreateDirectory(baseSavePath); - // Reassign clients to slots - // - Bot ordering is preserved - // - Humans are assigned on a first-come-first-serve basis - // - Leftover humans become spectators - - // Start by removing all bots and assigning all players as spectators - foreach (var c in LobbyInfo.Clients) - { - if (c.Bot != null) - LobbyInfo.Clients.Remove(c); - else - c.Slot = null; - } - - // Rebuild/remap the saved client state - // TODO: Multiplayer saves should leave all humans as spectators so they can manually pick slots - var adminClientIndex = LobbyInfo.Clients.First(c => c.IsAdmin).Index; - foreach (var kv in GameSave.SlotClients) - { - if (kv.Value.Bot != null) - { - var bot = new Session.Client() - { - Index = ChooseFreePlayerIndex(), - State = Session.ClientState.NotReady, - BotControllerClientIndex = adminClientIndex - }; - - kv.Value.ApplyTo(bot); - LobbyInfo.Clients.Add(bot); - } - else - { - // This will throw if the server doesn't have enough human clients to fill all player slots - // See TODO above - this isn't a problem in practice because MP saves won't use this - var client = LobbyInfo.Clients.First(c => c.Slot == null); - kv.Value.ApplyTo(client); - } - } - - SyncLobbyInfo(); - SyncLobbyClients(); - - break; + GameSave.Save(Path.Combine(baseSavePath, filename)); + DispatchServerOrdersToClients(Order.FromTargetString("GameSaved", filename, true)); } + + break; + } + + case "LoadGameSave": + { + if (Type == ServerType.Dedicated || State >= ServerState.GameStarted) + break; + + // Sanitize potentially malicious input + var filename = o.TargetString; + var invalidIndex = -1; + var invalidChars = Path.GetInvalidFileNameChars(); + while ((invalidIndex = filename.IndexOfAny(invalidChars)) != -1) + filename = filename.Remove(invalidIndex, 1); + + var savePath = Path.Combine( + Platform.SupportDir, + "Saves", + ModData.Manifest.Id, + ModData.Manifest.Metadata.Version, + filename); + + GameSave = new GameSave(savePath); + LobbyInfo.GlobalSettings = GameSave.GlobalSettings; + LobbyInfo.Slots = GameSave.Slots; + + // Reassign clients to slots + // - Bot ordering is preserved + // - Humans are assigned on a first-come-first-serve basis + // - Leftover humans become spectators + + // Start by removing all bots and assigning all players as spectators + foreach (var c in LobbyInfo.Clients) + { + if (c.Bot != null) + LobbyInfo.Clients.Remove(c); + else + c.Slot = null; + } + + // Rebuild/remap the saved client state + // TODO: Multiplayer saves should leave all humans as spectators so they can manually pick slots + var adminClientIndex = LobbyInfo.Clients.First(c => c.IsAdmin).Index; + foreach (var kv in GameSave.SlotClients) + { + if (kv.Value.Bot != null) + { + var bot = new Session.Client() + { + Index = ChooseFreePlayerIndex(), + State = Session.ClientState.NotReady, + BotControllerClientIndex = adminClientIndex + }; + + kv.Value.ApplyTo(bot); + LobbyInfo.Clients.Add(bot); + } + else + { + // This will throw if the server doesn't have enough human clients to fill all player slots + // See TODO above - this isn't a problem in practice because MP saves won't use this + var client = LobbyInfo.Clients.First(c => c.Slot == null); + kv.Value.ApplyTo(client); + } + } + + SyncLobbyInfo(); + SyncLobbyClients(); + + break; + } } } } @@ -1504,9 +1505,9 @@ namespace OpenRA.Server readonly int[] pingHistory; // TODO: future net code changes - #pragma warning disable IDE0052 +#pragma warning disable IDE0052 readonly byte queueLength; - #pragma warning restore IDE0052 +#pragma warning restore IDE0052 public ConnectionPingEvent(Connection connection, int[] pingHistory, byte queueLength) { diff --git a/OpenRA.Game/WRot.cs b/OpenRA.Game/WRot.cs index c581d762c1..dde7d7ae03 100644 --- a/OpenRA.Game/WRot.cs +++ b/OpenRA.Game/WRot.cs @@ -157,28 +157,26 @@ namespace OpenRA var lsq = x * x + y * y + z * z + w * w; // Quaternion components use 10 bits, so there's no risk of overflow - #pragma warning disable SA1115 // Allow blank lines to visually separate matrix rows mtx = new Int32Matrix4x4( lsq - 2 * (y * y + z * z), 2 * (x * y + z * w), 2 * (x * z - y * w), 0, - + /* row */ 2 * (x * y - z * w), lsq - 2 * (x * x + z * z), 2 * (y * z + x * w), 0, - + /* row */ 2 * (x * z + y * w), 2 * (y * z - x * w), lsq - 2 * (x * x + y * y), 0, - + /* row */ 0, 0, 0, lsq); - #pragma warning restore SA1115 } public Int32Matrix4x4 AsMatrix() diff --git a/OpenRA.Mods.Cnc/Activities/LeapAttack.cs b/OpenRA.Mods.Cnc/Activities/LeapAttack.cs index 2ab0f27b51..0df455f26f 100644 --- a/OpenRA.Mods.Cnc/Activities/LeapAttack.cs +++ b/OpenRA.Mods.Cnc/Activities/LeapAttack.cs @@ -51,7 +51,7 @@ namespace OpenRA.Mods.Cnc.Activities // The target may become hidden between the initial order request and the first tick (e.g. if queued) // Moving to any position (even if quite stale) is still better than immediately giving up if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) - || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) + || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) { lastVisibleTarget = Target.FromPos(target.CenterPosition); lastVisibleMinRange = attack.GetMinimumRangeVersusTarget(target); diff --git a/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs b/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs index d180a9e1e3..ec725f12e4 100644 --- a/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs +++ b/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs @@ -171,53 +171,53 @@ namespace OpenRA.Mods.Cnc.AudioLoaders { // Sound data case 1: + { + if (block.Length < 2) + throw new InvalidDataException("Invalid sound data block length in voc file"); + var freqDiv = stream.ReadUInt8(); + block.SampleBlock.Rate = GetSampleRateFromVocRate(freqDiv); + var codec = stream.ReadUInt8(); + if (codec != 0) + throw new InvalidDataException("Unhandled codec used in voc file"); + skip = block.Length - 2; + block.SampleBlock.Samples = skip; + block.SampleBlock.Offset = stream.Position; + + // See if last block contained additional information + if (blockList.Count > 0) { - if (block.Length < 2) - throw new InvalidDataException("Invalid sound data block length in voc file"); - var freqDiv = stream.ReadUInt8(); - block.SampleBlock.Rate = GetSampleRateFromVocRate(freqDiv); - var codec = stream.ReadUInt8(); - if (codec != 0) - throw new InvalidDataException("Unhandled codec used in voc file"); - skip = block.Length - 2; - block.SampleBlock.Samples = skip; - block.SampleBlock.Offset = stream.Position; - - // See if last block contained additional information - if (blockList.Count > 0) + var b = blockList.Last(); + if (b.Code == 8) { - var b = blockList.Last(); - if (b.Code == 8) - { - block.SampleBlock.Rate = b.SampleBlock.Rate; - blockList.Remove(b); - } + block.SampleBlock.Rate = b.SampleBlock.Rate; + blockList.Remove(b); } - - sampleRate = Math.Max(sampleRate, block.SampleBlock.Rate); - break; } + sampleRate = Math.Max(sampleRate, block.SampleBlock.Rate); + break; + } + // Silence case 3: - { - if (block.Length != 3) - throw new InvalidDataException("Invalid silence block length in voc file"); - block.SampleBlock.Offset = 0; - block.SampleBlock.Samples = stream.ReadUInt16() + 1; - var freqDiv = stream.ReadUInt8(); - block.SampleBlock.Rate = GetSampleRateFromVocRate(freqDiv); - break; - } + { + if (block.Length != 3) + throw new InvalidDataException("Invalid silence block length in voc file"); + block.SampleBlock.Offset = 0; + block.SampleBlock.Samples = stream.ReadUInt16() + 1; + var freqDiv = stream.ReadUInt8(); + block.SampleBlock.Rate = GetSampleRateFromVocRate(freqDiv); + break; + } // Repeat start case 6: - { - if (block.Length != 2) - throw new InvalidDataException("Invalid repeat start block length in voc file"); - block.LoopBlock.Count = stream.ReadUInt16() + 1; - break; - } + { + if (block.Length != 2) + throw new InvalidDataException("Invalid repeat start block length in voc file"); + block.LoopBlock.Count = stream.ReadUInt16() + 1; + break; + } // Repeat end case 7: @@ -225,23 +225,23 @@ namespace OpenRA.Mods.Cnc.AudioLoaders // Extra info case 8: - { - if (block.Length != 4) - throw new InvalidDataException("Invalid info block length in voc file"); - int freqDiv = stream.ReadUInt16(); - if (freqDiv == 65536) - throw new InvalidDataException("Invalid frequency divisor 65536 in voc file"); - var codec = stream.ReadUInt8(); - if (codec != 0) - throw new InvalidDataException("Unhandled codec used in voc file"); - var channels = stream.ReadUInt8() + 1; - if (channels != 1) - throw new InvalidDataException("Unhandled number of channels in voc file"); - block.SampleBlock.Offset = 0; - block.SampleBlock.Samples = 0; - block.SampleBlock.Rate = (int)(256000000L / (65536L - freqDiv)); - break; - } + { + if (block.Length != 4) + throw new InvalidDataException("Invalid info block length in voc file"); + int freqDiv = stream.ReadUInt16(); + if (freqDiv == 65536) + throw new InvalidDataException("Invalid frequency divisor 65536 in voc file"); + var codec = stream.ReadUInt8(); + if (codec != 0) + throw new InvalidDataException("Unhandled codec used in voc file"); + var channels = stream.ReadUInt8() + 1; + if (channels != 1) + throw new InvalidDataException("Unhandled number of channels in voc file"); + block.SampleBlock.Offset = 0; + block.SampleBlock.Samples = 0; + block.SampleBlock.Rate = (int)(256000000L / (65536L - freqDiv)); + break; + } // Sound data (New format) case 9: diff --git a/OpenRA.Mods.Cnc/FileFormats/LZOCompression.cs b/OpenRA.Mods.Cnc/FileFormats/LZOCompression.cs index cdf71de52e..a7e0037c02 100644 --- a/OpenRA.Mods.Cnc/FileFormats/LZOCompression.cs +++ b/OpenRA.Mods.Cnc/FileFormats/LZOCompression.cs @@ -251,9 +251,7 @@ namespace OpenRA.Mods.Cnc.FileFormats *op++ = *ip++; if (t > 2) { - #pragma warning disable IDE0047 - (*op++) = *ip++; - #pragma warning restore IDE0047 + *op++ = *ip++; } } diff --git a/OpenRA.Mods.Cnc/FileFormats/VqaVideo.cs b/OpenRA.Mods.Cnc/FileFormats/VqaVideo.cs index 6b62ed82ed..7884ed513d 100644 --- a/OpenRA.Mods.Cnc/FileFormats/VqaVideo.cs +++ b/OpenRA.Mods.Cnc/FileFormats/VqaVideo.cs @@ -68,13 +68,13 @@ namespace OpenRA.Mods.Cnc.FileFormats // Decode FORM chunk if (stream.ReadASCII(4) != "FORM") throw new InvalidDataException("Invalid vqa (invalid FORM section)"); - /*var length = */stream.ReadUInt32(); + stream.ReadUInt32(); // length if (stream.ReadASCII(8) != "WVQAVQHD") throw new InvalidDataException("Invalid vqa (not WVQAVQHD)"); - /*var length2 = */stream.ReadUInt32(); + stream.ReadUInt32(); // length2 - /*var version = */stream.ReadUInt16(); + stream.ReadUInt16(); // version videoFlags = stream.ReadUInt16(); FrameCount = stream.ReadUInt16(); Width = stream.ReadUInt16(); @@ -87,20 +87,20 @@ namespace OpenRA.Mods.Cnc.FileFormats blocks = new int2(Width / blockWidth, Height / blockHeight); numColors = stream.ReadUInt16(); - /*var maxBlocks = */stream.ReadUInt16(); - /*var unknown1 = */stream.ReadUInt16(); - /*var unknown2 = */stream.ReadUInt32(); + stream.ReadUInt16(); // maxBlocks + stream.ReadUInt16(); // unknown1 + stream.ReadUInt32(); // unknown2 // Audio SampleRate = stream.ReadUInt16(); AudioChannels = stream.ReadUInt8(); SampleBits = stream.ReadUInt8(); - /*var unknown3 =*/stream.ReadUInt32(); - /*var unknown4 =*/stream.ReadUInt16(); - /*maxCbfzSize =*/stream.ReadUInt32(); // Unreliable + stream.ReadUInt32(); // unknown3 + stream.ReadUInt16(); // unknown4 + stream.ReadUInt32(); // maxCbfzSize, unreliable - /*var unknown5 =*/stream.ReadUInt32(); + stream.ReadUInt32(); // unknown5 if (IsHqVqa) { @@ -131,8 +131,8 @@ namespace OpenRA.Mods.Cnc.FileFormats throw new NotSupportedException($"Vqa uses unknown Subtype: {type}"); } - /*var length = */stream.ReadUInt16(); - /*var unknown4 = */stream.ReadUInt16(); + stream.ReadUInt16(); // length + stream.ReadUInt16(); // unknown4 // Frame offsets offsets = new uint[FrameCount]; diff --git a/OpenRA.Mods.Cnc/FileFormats/WsaVideo.cs b/OpenRA.Mods.Cnc/FileFormats/WsaVideo.cs index 581b7a71bd..e096946119 100644 --- a/OpenRA.Mods.Cnc/FileFormats/WsaVideo.cs +++ b/OpenRA.Mods.Cnc/FileFormats/WsaVideo.cs @@ -45,13 +45,13 @@ namespace OpenRA.Mods.Cnc.FileFormats FrameCount = stream.ReadUInt16(); - /*var x = */stream.ReadUInt16(); - /*var y = */stream.ReadUInt16(); + stream.ReadUInt16(); // x + stream.ReadUInt16(); // y Width = stream.ReadUInt16(); Height = stream.ReadUInt16(); - /*var delta = */stream.ReadUInt16(); /* + 37*/ + stream.ReadUInt16(); // delta (+37) var flags = stream.ReadUInt16(); frameOffsets = new uint[FrameCount + 2]; diff --git a/OpenRA.Mods.Cnc/FileSystem/BigFile.cs b/OpenRA.Mods.Cnc/FileSystem/BigFile.cs index bd6f1dcf1b..f5d9f0bdf5 100644 --- a/OpenRA.Mods.Cnc/FileSystem/BigFile.cs +++ b/OpenRA.Mods.Cnc/FileSystem/BigFile.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.Cnc.FileSystem try { - /* var signature = */ s.ReadASCII(4); + s.ReadASCII(4); // signature // Total archive size. s.ReadUInt32(); diff --git a/OpenRA.Mods.Cnc/FileSystem/MixFile.cs b/OpenRA.Mods.Cnc/FileSystem/MixFile.cs index 41bacf8bec..7e6d1e17a4 100644 --- a/OpenRA.Mods.Cnc/FileSystem/MixFile.cs +++ b/OpenRA.Mods.Cnc/FileSystem/MixFile.cs @@ -113,7 +113,7 @@ namespace OpenRA.Mods.Cnc.FileSystem { s.Seek(offset, SeekOrigin.Begin); var numFiles = s.ReadUInt16(); - /*uint dataSize = */s.ReadUInt32(); + s.ReadUInt32(); // dataSize var items = new List(); for (var i = 0; i < numFiles; i++) diff --git a/OpenRA.Mods.Cnc/FileSystem/PackageEntry.cs b/OpenRA.Mods.Cnc/FileSystem/PackageEntry.cs index 7a64139a74..eb5b39c3ff 100644 --- a/OpenRA.Mods.Cnc/FileSystem/PackageEntry.cs +++ b/OpenRA.Mods.Cnc/FileSystem/PackageEntry.cs @@ -69,38 +69,38 @@ namespace OpenRA.Mods.Cnc.FileSystem switch (type) { case PackageHashType.Classic: - { - for (var p = 0; p < padding; p++) - upperPaddedName[paddedLength - 1 - p] = '\0'; + { + for (var p = 0; p < padding; p++) + upperPaddedName[paddedLength - 1 - p] = '\0'; - var asciiBytes = paddedLength < 64 ? stackalloc byte[paddedLength] : new byte[paddedLength]; - Encoding.ASCII.GetBytes(upperPaddedName, asciiBytes); + var asciiBytes = paddedLength < 64 ? stackalloc byte[paddedLength] : new byte[paddedLength]; + Encoding.ASCII.GetBytes(upperPaddedName, asciiBytes); - var data = MemoryMarshal.Cast(asciiBytes); - var result = 0u; - foreach (var next in data) - result = ((result << 1) | (result >> 31)) + next; + var data = MemoryMarshal.Cast(asciiBytes); + var result = 0u; + foreach (var next in data) + result = ((result << 1) | (result >> 31)) + next; - return result; - } + return result; + } case PackageHashType.CRC32: + { + var length = name.Length; + var lengthRoundedDownToFour = length / 4 * 4; + if (length != lengthRoundedDownToFour) { - var length = name.Length; - var lengthRoundedDownToFour = length / 4 * 4; - if (length != lengthRoundedDownToFour) - { - upperPaddedName[length] = (char)(length - lengthRoundedDownToFour); - for (var p = 1; p < padding; p++) - upperPaddedName[length + p] = upperPaddedName[lengthRoundedDownToFour]; - } - - var asciiBytes = paddedLength < 64 ? stackalloc byte[paddedLength] : new byte[paddedLength]; - Encoding.ASCII.GetBytes(upperPaddedName, asciiBytes); - - return CRC32.Calculate(asciiBytes); + upperPaddedName[length] = (char)(length - lengthRoundedDownToFour); + for (var p = 1; p < padding; p++) + upperPaddedName[length + p] = upperPaddedName[lengthRoundedDownToFour]; } + var asciiBytes = paddedLength < 64 ? stackalloc byte[paddedLength] : new byte[paddedLength]; + Encoding.ASCII.GetBytes(upperPaddedName, asciiBytes); + + return CRC32.Calculate(asciiBytes); + } + default: throw new NotImplementedException($"Unknown hash type `{type}`"); } } diff --git a/OpenRA.Mods.Cnc/Graphics/ClassicTilesetSpecificSpriteSequence.cs b/OpenRA.Mods.Cnc/Graphics/ClassicTilesetSpecificSpriteSequence.cs index 736a23eb69..d0c6945d29 100644 --- a/OpenRA.Mods.Cnc/Graphics/ClassicTilesetSpecificSpriteSequence.cs +++ b/OpenRA.Mods.Cnc/Graphics/ClassicTilesetSpecificSpriteSequence.cs @@ -27,7 +27,7 @@ namespace OpenRA.Mods.Cnc.Graphics } [Desc("A sprite sequence that can have tileset-specific variants and has the oddities " + - "that come with first-generation Westwood titles.")] + "that come with first-generation Westwood titles.")] public class ClassicTilesetSpecificSpriteSequence : ClassicSpriteSequence { [Desc("Dictionary of : filename to override the Filename key.")] diff --git a/OpenRA.Mods.Cnc/Graphics/ModelRenderable.cs b/OpenRA.Mods.Cnc/Graphics/ModelRenderable.cs index a5fc236b02..22ba14693e 100644 --- a/OpenRA.Mods.Cnc/Graphics/ModelRenderable.cs +++ b/OpenRA.Mods.Cnc/Graphics/ModelRenderable.cs @@ -37,7 +37,8 @@ namespace OpenRA.Mods.Cnc.Graphics : this(renderer, models, pos, zOffset, camera, scale, lightSource, lightAmbientColor, lightDiffuseColor, color, normals, shadow, 1f, - float3.Ones, TintModifiers.None) { } + float3.Ones, TintModifiers.None) + { } public ModelRenderable( ModelRenderer renderer, IEnumerable models, WPos pos, int zOffset, in WRot camera, float scale, diff --git a/OpenRA.Mods.Cnc/SpriteLoaders/ShpTDLoader.cs b/OpenRA.Mods.Cnc/SpriteLoaders/ShpTDLoader.cs index a989e718d9..2605ed86af 100644 --- a/OpenRA.Mods.Cnc/SpriteLoaders/ShpTDLoader.cs +++ b/OpenRA.Mods.Cnc/SpriteLoaders/ShpTDLoader.cs @@ -172,26 +172,26 @@ namespace OpenRA.Mods.Cnc.SpriteLoaders { case Format.XORPrev: case Format.XORLCW: + { + if (h.RefImage.Data == null) { - if (h.RefImage.Data == null) - { - ++recurseDepth; - Decompress(h.RefImage); - --recurseDepth; - } - - h.Data = CopyImageData(h.RefImage.Data); - XORDeltaCompression.DecodeInto(shpBytes, h.Data, (int)(h.FileOffset - shpBytesFileOffset)); - break; + ++recurseDepth; + Decompress(h.RefImage); + --recurseDepth; } + h.Data = CopyImageData(h.RefImage.Data); + XORDeltaCompression.DecodeInto(shpBytes, h.Data, (int)(h.FileOffset - shpBytesFileOffset)); + break; + } + case Format.LCW: - { - var imageBytes = new byte[Size.Width * Size.Height]; - LCWCompression.DecodeInto(shpBytes, imageBytes, (int)(h.FileOffset - shpBytesFileOffset)); - h.Data = imageBytes; - break; - } + { + var imageBytes = new byte[Size.Width * Size.Height]; + LCWCompression.DecodeInto(shpBytes, imageBytes, (int)(h.FileOffset - shpBytesFileOffset)); + h.Data = imageBytes; + break; + } default: throw new InvalidDataException(); diff --git a/OpenRA.Mods.Cnc/Traits/TDGunboat.cs b/OpenRA.Mods.Cnc/Traits/TDGunboat.cs index 958b2cfbfb..4d13a24802 100644 --- a/OpenRA.Mods.Cnc/Traits/TDGunboat.cs +++ b/OpenRA.Mods.Cnc/Traits/TDGunboat.cs @@ -196,18 +196,24 @@ namespace OpenRA.Mods.Cnc.Traits } public Activity MoveTo(CPos cell, int nearEnough = 0, Actor ignoreActor = null, - bool evaluateNearestMovableCell = false, Color? targetLineColor = null) { return null; } + bool evaluateNearestMovableCell = false, Color? targetLineColor = null) + { return null; } public Activity MoveWithinRange(in Target target, WDist range, - WPos? initialTargetPosition = null, Color? targetLineColor = null) { return null; } + WPos? initialTargetPosition = null, Color? targetLineColor = null) + { return null; } public Activity MoveWithinRange(in Target target, WDist minRange, WDist maxRange, - WPos? initialTargetPosition = null, Color? targetLineColor = null) { return null; } + WPos? initialTargetPosition = null, Color? targetLineColor = null) + { return null; } public Activity MoveFollow(Actor self, in Target target, WDist minRange, WDist maxRange, - WPos? initialTargetPosition = null, Color? targetLineColor = null) { return null; } + WPos? initialTargetPosition = null, Color? targetLineColor = null) + { return null; } public Activity ReturnToCell(Actor self) { return null; } public Activity MoveToTarget(Actor self, in Target target, - WPos? initialTargetPosition = null, Color? targetLineColor = null) { return null; } + WPos? initialTargetPosition = null, Color? targetLineColor = null) + { return null; } public Activity MoveOntoTarget(Actor self, in Target target, in WVec offset, - WAngle? facing, Color? targetLineColor = null) { return null; } + WAngle? facing, Color? targetLineColor = null) + { return null; } public Activity MoveIntoTarget(Actor self, in Target target) { return null; } public Activity LocalMove(Actor self, WPos fromPos, WPos toPos) { return null; } diff --git a/OpenRA.Mods.Cnc/Traits/World/ModelRenderer.cs b/OpenRA.Mods.Cnc/Traits/World/ModelRenderer.cs index cce2dbac61..1964c5a915 100644 --- a/OpenRA.Mods.Cnc/Traits/World/ModelRenderer.cs +++ b/OpenRA.Mods.Cnc/Traits/World/ModelRenderer.cs @@ -194,7 +194,7 @@ namespace OpenRA.Mods.Cnc.Traits var correctionTransform = Util.MatrixMultiply(translateMtx, FlipMtx); var shadowCorrectionTransform = Util.MatrixMultiply(shadowTranslateMtx, ShadowScaleFlipMtx); - doRender.Add((sprite.Sheet, () => + void RenderFunc() { foreach (var m in models) { @@ -235,7 +235,9 @@ namespace OpenRA.Mods.Cnc.Traits ShadowAmbient, ShadowDiffuse, shadowPalette.TextureIndex, normals.TextureIndex); } } - })); + } + + doRender.Add((sprite.Sheet, RenderFunc)); var screenLightVector = Util.MatrixVectorMultiply(invShadowTransform, ZVector); screenLightVector = Util.MatrixVectorMultiply(cameraTransform, screenLightVector); diff --git a/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs b/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs index 4eb8fb0c41..990d7d3e3a 100644 --- a/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs +++ b/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs @@ -119,10 +119,10 @@ namespace OpenRA.Mods.Cnc.UtilityCommands var rx = mf.ReadUInt16(); var ry = mf.ReadUInt16(); var tilenum = mf.ReadUInt16(); - /*var zero1 = */mf.ReadInt16(); + mf.ReadInt16(); // zero1 var subtile = mf.ReadUInt8(); var z = mf.ReadUInt8(); - /*var zero2 = */mf.ReadUInt8(); + mf.ReadUInt8(); // zero2 var uv = ToMPos(rx, ry, fullSize.X); diff --git a/OpenRA.Mods.Cnc/UtilityCommands/LegacyTilesetImporter.cs b/OpenRA.Mods.Cnc/UtilityCommands/LegacyTilesetImporter.cs index c4fb270787..efd3391958 100644 --- a/OpenRA.Mods.Cnc/UtilityCommands/LegacyTilesetImporter.cs +++ b/OpenRA.Mods.Cnc/UtilityCommands/LegacyTilesetImporter.cs @@ -115,8 +115,8 @@ namespace OpenRA.Mods.Cnc.UtilityCommands var templateWidth = s.ReadUInt32(); var templateHeight = s.ReadUInt32(); - /* var tileWidth = */s.ReadInt32(); - /* var tileHeight = */s.ReadInt32(); + s.ReadInt32(); // tileWidth + s.ReadInt32(); // tileHeight var offsets = new uint[templateWidth * templateHeight]; for (var j = 0; j < offsets.Length; j++) offsets[j] = s.ReadUInt32(); diff --git a/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs b/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs index ea4577ecff..074b3f814f 100644 --- a/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs +++ b/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs @@ -40,15 +40,15 @@ namespace OpenRA.Mods.Cnc.VideoLoaders if (frames <= 1) // TODO: find a better way to differentiate .shp icons return false; - /* var x = */ s.ReadUInt16(); - /* var y = */ s.ReadUInt16(); + s.ReadUInt16(); // x + s.ReadUInt16(); // y var width = s.ReadUInt16(); var height = s.ReadUInt16(); if (width <= 0 || height <= 0) return false; - /*var delta = */ s.ReadUInt16(); /* + 37;*/ + s.ReadUInt16(); // delta (+37) var flags = s.ReadUInt16(); @@ -58,7 +58,7 @@ namespace OpenRA.Mods.Cnc.VideoLoaders if (flags == 1) { - /* var palette = */ s.ReadBytes(768); + s.ReadBytes(768); // palette for (var i = 0; i < offsets.Length; i++) offsets[i] += 768; } diff --git a/OpenRA.Mods.Common/Activities/Air/Fly.cs b/OpenRA.Mods.Common/Activities/Air/Fly.cs index 482432ed40..c7063571bc 100644 --- a/OpenRA.Mods.Common/Activities/Air/Fly.cs +++ b/OpenRA.Mods.Common/Activities/Air/Fly.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Activities // The target may become hidden between the initial order request and the first tick (e.g. if queued) // Moving to any position (even if quite stale) is still better than immediately giving up if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) - || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) + || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) lastVisibleTarget = Target.FromPos(target.CenterPosition); else if (initialTargetPosition.HasValue) lastVisibleTarget = Target.FromPos(initialTargetPosition.Value); diff --git a/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs b/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs index 96f40c3a38..04c4a9ac10 100644 --- a/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs +++ b/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Activities // The target may become hidden between the initial order request and the first tick (e.g. if queued) // Moving to any position (even if quite stale) is still better than immediately giving up if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) - || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) + || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) lastVisibleTarget = Target.FromPos(target.CenterPosition); else if (initialTargetPosition.HasValue) lastVisibleTarget = Target.FromPos(initialTargetPosition.Value); diff --git a/OpenRA.Mods.Common/Activities/Attack.cs b/OpenRA.Mods.Common/Activities/Attack.cs index ea062da4a0..84ea1e91b3 100644 --- a/OpenRA.Mods.Common/Activities/Attack.cs +++ b/OpenRA.Mods.Common/Activities/Attack.cs @@ -64,7 +64,7 @@ namespace OpenRA.Mods.Common.Activities // The target may become hidden between the initial order request and the first tick (e.g. if queued) // Moving to any position (even if quite stale) is still better than immediately giving up if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) - || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) + || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) { lastVisibleTarget = Target.FromPos(target.CenterPosition); diff --git a/OpenRA.Mods.Common/Activities/Move/Follow.cs b/OpenRA.Mods.Common/Activities/Move/Follow.cs index e70c580941..c6d10c6d47 100644 --- a/OpenRA.Mods.Common/Activities/Move/Follow.cs +++ b/OpenRA.Mods.Common/Activities/Move/Follow.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Activities // The target may become hidden between the initial order request and the first tick (e.g. if queued) // Moving to any position (even if quite stale) is still better than immediately giving up if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) - || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) + || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) lastVisibleTarget = Target.FromPos(target.CenterPosition); else if (initialTargetPosition.HasValue) lastVisibleTarget = Target.FromPos(initialTargetPosition.Value); diff --git a/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs b/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs index 24b3d46487..0204b6dbcd 100644 --- a/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs +++ b/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Activities // The target may become hidden between the initial order request and the first tick (e.g. if queued) // Moving to any position (even if quite stale) is still better than immediately giving up if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) - || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) + || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) { lastVisibleTarget = Target.FromPos(target.CenterPosition); SetVisibleTargetLocation(self, target); diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs index df0f377a0d..1a2bac87c4 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs @@ -106,7 +106,7 @@ namespace OpenRA.Mods.Common.Widgets { editorActorPreview = editorLayer.Add(actor); Text = TranslationProvider.GetString(AddedActor, - Translation.Arguments("name", editorActorPreview.Info.Name, "id", editorActorPreview.ID)); + Translation.Arguments("name", editorActorPreview.Info.Name, "id", editorActorPreview.ID)); } public void Undo() diff --git a/OpenRA.Mods.Common/FileSystem/InstallShieldPackage.cs b/OpenRA.Mods.Common/FileSystem/InstallShieldPackage.cs index 9941e1c32b..9fcd247091 100644 --- a/OpenRA.Mods.Common/FileSystem/InstallShieldPackage.cs +++ b/OpenRA.Mods.Common/FileSystem/InstallShieldPackage.cs @@ -49,11 +49,11 @@ namespace OpenRA.Mods.Common.FileSystem try { // Parse package header - /*var signature = */s.ReadUInt32(); + s.ReadUInt32(); // signature s.Position += 8; - /*var FileCount = */s.ReadUInt16(); + s.ReadUInt16(); // FileCount s.Position += 4; - /*var ArchiveSize = */s.ReadUInt32(); + s.ReadUInt32(); // ArchiveSize s.Position += 19; var tocAddress = s.ReadInt32(); s.Position += 4; diff --git a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs index fbea95a537..9dc819fb5b 100644 --- a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs +++ b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs @@ -139,7 +139,7 @@ namespace OpenRA.Mods.Common.Graphics protected static readonly SpriteSequenceField Tick = new(nameof(Tick), 40); [Desc("Value controlling the Z-order. A higher values means rendering on top of other sprites at the same position. " + - "Use power of 2 values to avoid glitches.")] + "Use power of 2 values to avoid glitches.")] protected static readonly SpriteSequenceField ZOffset = new(nameof(ZOffset), WDist.Zero); [Desc("Additional sprite depth Z offset to apply as a function of sprite Y (0: vertical, 1: flat on terrain)")] diff --git a/OpenRA.Mods.Common/Graphics/TextAnnotationRenderable.cs b/OpenRA.Mods.Common/Graphics/TextAnnotationRenderable.cs index df628db344..353f1f8a55 100644 --- a/OpenRA.Mods.Common/Graphics/TextAnnotationRenderable.cs +++ b/OpenRA.Mods.Common/Graphics/TextAnnotationRenderable.cs @@ -38,7 +38,8 @@ namespace OpenRA.Mods.Common.Graphics : this(font, pos, zOffset, color, ChromeMetrics.Get("TextContrastColorDark"), ChromeMetrics.Get("TextContrastColorLight"), - text) { } + text) + { } public WPos Pos { get; } public int ZOffset { get; } diff --git a/OpenRA.Mods.Common/Graphics/UITextRenderable.cs b/OpenRA.Mods.Common/Graphics/UITextRenderable.cs index 2149593e7f..0b54f793ce 100644 --- a/OpenRA.Mods.Common/Graphics/UITextRenderable.cs +++ b/OpenRA.Mods.Common/Graphics/UITextRenderable.cs @@ -40,7 +40,8 @@ namespace OpenRA.Mods.Common.Graphics : this(font, effectiveWorldPos, screenPos, zOffset, color, ChromeMetrics.Get("TextContrastColorDark"), ChromeMetrics.Get("TextContrastColorLight"), - text) { } + text) + { } public WPos Pos { get; } public int ZOffset { get; } diff --git a/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs index 0871a94c50..0973759a7b 100644 --- a/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/MapGlobal.cs @@ -136,7 +136,7 @@ namespace OpenRA.Mods.Common.Scripting public Actor[] NamedActors => sma.Actors.Values.ToArray(); [Desc("Returns the actor that was specified with a given name in " + - "the map file (or nil, if the actor is dead or not found).")] + "the map file (or nil, if the actor is dead or not found).")] public Actor NamedActor(string actorName) { if (!sma.Actors.TryGetValue(actorName, out var ret)) diff --git a/OpenRA.Mods.Common/Scripting/Properties/PowerProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/PowerProperties.cs index de32e63453..dc36978958 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/PowerProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/PowerProperties.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Scripting public int PowerDrained => pm.PowerDrained; [Desc("Returns the player's power state " + - "(\"Normal\", \"Low\" or \"Critical\").")] + "(\"Normal\", \"Low\" or \"Critical\").")] public string PowerState => pm.PowerState.ToString(); [Desc("Triggers low power for the chosen amount of ticks.")] diff --git a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs index c52204b90c..0d701607d8 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs @@ -1192,7 +1192,7 @@ namespace OpenRA.Mods.Common.Server return true; if (!Exts.TryParseInt32Invariant(parts[1], out var spawnPoint) - || spawnPoint < 0 || spawnPoint > server.Map.SpawnPoints.Length) + || spawnPoint < 0 || spawnPoint > server.Map.SpawnPoints.Length) { Log.Write("server", $"Invalid spawn point: {parts[1]}"); return true; diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index d1438a37d6..3b72249ca8 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -1262,9 +1262,8 @@ namespace OpenRA.Mods.Common.Traits foreach (var cell in rallyPoint) self.QueueActivity(new AttackMoveActivity(self, () => aircraft.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed))); } - else - if (self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition).Length <= aircraft.LandAltitude.Length) - QueueChild(new TakeOff(self)); + else if (self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition).Length <= aircraft.LandAltitude.Length) + QueueChild(new TakeOff(self)); aircraft.UnReserve(); return true; diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs index 938ca4eada..5c5980c000 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs @@ -142,7 +142,7 @@ namespace OpenRA.Mods.Common.Traits IsAiming = CanAimAtTarget(self, OpportunityTarget, opportunityForceAttack); if (!IsAiming && Info.OpportunityFire && autoTarget != null && - !autoTarget.IsTraitDisabled && autoTarget.Stance >= UnitStance.Defend) + !autoTarget.IsTraitDisabled && autoTarget.Stance >= UnitStance.Defend) { OpportunityTarget = autoTarget.ScanForTarget(self, false, false); opportunityForceAttack = false; @@ -265,7 +265,7 @@ namespace OpenRA.Mods.Common.Traits // The target may become hidden between the initial order request and the first tick (e.g. if queued) // Moving to any position (even if quite stale) is still better than immediately giving up if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) - || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) + || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain) { lastVisibleTarget = Target.FromPos(target.CenterPosition); lastVisibleMaximumRange = attack.GetMaximumRangeVersusTarget(target); diff --git a/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs b/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs index 7979a76dc5..d04046245d 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs @@ -204,9 +204,9 @@ namespace OpenRA.Mods.Common.Traits var explored = self.Owner.Shroud.IsExplored(location); if (!self.World.Map.Contains(location) || - !(self.CurrentActivity is Transform || mobile.transforms.Any(t => !t.IsTraitDisabled && !t.IsTraitPaused)) - || (!explored && !mobile.locomotor.Info.MoveIntoShroud) - || (explored && !CanEnterCell(self, location))) + !(self.CurrentActivity is Transform || mobile.transforms.Any(t => !t.IsTraitDisabled && !t.IsTraitPaused)) + || (!explored && !mobile.locomotor.Info.MoveIntoShroud) + || (explored && !CanEnterCell(self, location))) cursor = mobile.Info.BlockedCursor; else if (!explored || !mobile.Info.TerrainCursors.TryGetValue(self.World.Map.GetTerrainInfo(location).Type, out cursor)) cursor = mobile.Info.Cursor; diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 443cabdca2..7f748b74df 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -409,7 +409,7 @@ namespace OpenRA.Mods.Common.Traits } void INotifyKilled.Killed(Actor self, AttackInfo e) - { + { // IsAtGroundLevel contains Map.Contains(self.Location) check. if (Info.EjectOnDeath && self.IsAtGroundLevel() && (!checkTerrainType || Info.UnloadTerrainTypes.Contains(self.World.Map.GetTerrainInfo(self.Location).Type))) { diff --git a/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeployWithCharge.cs b/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeployWithCharge.cs index ed718caeb2..56aa10d729 100644 --- a/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeployWithCharge.cs +++ b/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeployWithCharge.cs @@ -217,8 +217,10 @@ namespace OpenRA.Mods.Common.Traits chargedToken = self.RevokeCondition(chargedToken); } else + { if (chargedToken == Actor.InvalidConditionToken) chargedToken = self.GrantCondition(Info.ChargedCondition); + } } } diff --git a/OpenRA.Mods.Common/Traits/Player/GameSaveViewportManager.cs b/OpenRA.Mods.Common/Traits/Player/GameSaveViewportManager.cs index 89759b8732..53722a18a1 100644 --- a/OpenRA.Mods.Common/Traits/Player/GameSaveViewportManager.cs +++ b/OpenRA.Mods.Common/Traits/Player/GameSaveViewportManager.cs @@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Traits // TODO: This won't make sense for MP saves var localPlayer = worldRenderer.World.LocalPlayer; if ((localPlayer != null && localPlayer.PlayerActor != self) || - (localPlayer == null && self.Owner != self.World.Players.FirstOrDefault(p => p.IsBot))) + (localPlayer == null && self.Owner != self.World.Players.FirstOrDefault(p => p.IsBot))) return null; var nodes = new List() diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/AddControlGroups.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/AddControlGroups.cs index 19032a5eab..db60175c7b 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/AddControlGroups.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/AddControlGroups.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode) { if (actorNode.ChildrenMatching("Selection").Any(x => !x.IsRemoval()) - && !actorNode.ChildrenMatching("ControlGroups").Any()) + && !actorNode.ChildrenMatching("ControlGroups").Any()) actorNode.AddNode(new MiniYamlNodeBuilder("ControlGroups", "")); yield break; diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/RemovePlaceBuildingPalette.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/RemovePlaceBuildingPalette.cs index 569cd22ff1..3d7bd41ac5 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/RemovePlaceBuildingPalette.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/RemovePlaceBuildingPalette.cs @@ -27,10 +27,11 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules public override IEnumerable AfterUpdate(ModData modData) { if (locations.Count > 0) - yield return "The *Palette fields have been removed from the *PlaceBuildingPreview traits.\n" + - "You may wish to inspect the following definitions and define new Alpha or\n" + - "LineBuildSegmentAlpha properties as appropriate to recreate transparency effects:\n" + - UpdateUtils.FormatMessageList(locations); + yield return + "The *Palette fields have been removed from the *PlaceBuildingPreview traits.\n" + + "You may wish to inspect the following definitions and define new Alpha or\n" + + "LineBuildSegmentAlpha properties as appropriate to recreate transparency effects:\n" + + UpdateUtils.FormatMessageList(locations); locations.Clear(); } diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/ReplaceWithColoredOverlayPalette.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/ReplaceWithColoredOverlayPalette.cs index f0b31ba33d..6fbe10ad83 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/ReplaceWithColoredOverlayPalette.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/ReplaceWithColoredOverlayPalette.cs @@ -24,8 +24,9 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules public override IEnumerable AfterUpdate(ModData modData) { if (locations.Count > 0) - yield return "You must define new Color fields on the following traits:\n" + - UpdateUtils.FormatMessageList(locations); + yield return + "You must define new Color fields on the following traits:\n" + + UpdateUtils.FormatMessageList(locations); locations.Clear(); } diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs index ca4160eb5d..d3bca49118 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs @@ -56,9 +56,10 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules if (requiredMetadata.Count != 0) { - yield return $"The ExplicitSequenceFilenames rule requires {requiredMetadata.JoinWith(", ")}\n" + - "to be defined under the SpriteSequenceFormat definition in mod.yaml.\n" + - "Add these definitions back and run the update rule again."; + yield return + $"The ExplicitSequenceFilenames rule requires {requiredMetadata.JoinWith(", ")}\n" + + "to be defined under the SpriteSequenceFormat definition in mod.yaml.\n" + + "Add these definitions back and run the update rule again."; disabled = true; } } @@ -457,8 +458,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules var overrideFilename = filename; if (useTilesetCode) - overrideFilename = filename[..1] + tilesetCodes[sequenceTileset] + - filename[2..]; + overrideFilename = filename[..1] + tilesetCodes[sequenceTileset] + filename[2..]; if (addExtension) overrideFilename += useTilesetExtension ? tilesetExtensions[sequenceTileset] : defaultSpriteExtension; diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveSequenceHasEmbeddedPalette.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveSequenceHasEmbeddedPalette.cs index 43eb67b751..53da4f0b79 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveSequenceHasEmbeddedPalette.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveSequenceHasEmbeddedPalette.cs @@ -26,9 +26,10 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules public override IEnumerable AfterUpdate(ModData modData) { if (locations.Count > 0) - yield return "The PaletteFromEmbeddedSpritePalette trait no longer references a sequence.\n" + - "You must manually define Filename (and Frame if needed) on the following actors:\n" + - UpdateUtils.FormatMessageList(locations); + yield return + "The PaletteFromEmbeddedSpritePalette trait no longer references a sequence.\n" + + "You must manually define Filename (and Frame if needed) on the following actors:\n" + + UpdateUtils.FormatMessageList(locations); locations.Clear(); } diff --git a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs index 4a2fd886a5..9306108d31 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs @@ -79,9 +79,7 @@ namespace OpenRA.Mods.Common.UtilityCommands } var png = new Png(pngData, SpriteFrameType.Indexed8, frameSize.Width, frameSize.Height, palColors); - #pragma warning disable SA1003 png.Save($"{prefix}-{count++:D4}.png"); - #pragma warning restore SA1003 } Console.WriteLine("Saved {0}-[0..{1}].png", prefix, count - 1); diff --git a/OpenRA.Mods.Common/Widgets/ColorMixerWidget.cs b/OpenRA.Mods.Common/Widgets/ColorMixerWidget.cs index a9d3366698..9689f647ff 100644 --- a/OpenRA.Mods.Common/Widgets/ColorMixerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ColorMixerWidget.cs @@ -73,9 +73,7 @@ namespace OpenRA.Mods.Common.Widgets { for (var s = 0; s < 256; s++) { - #pragma warning disable IDE0047 - (*(c + s * 256 + v)) = Color.FromAhsv(newHue.Value, 1 - s / 255f, v / 255f).ToArgb(); - #pragma warning restore IDE0047 + *(c + s * 256 + v) = Color.FromAhsv(newHue.Value, 1 - s / 255f, v / 255f).ToArgb(); } } } diff --git a/OpenRA.Mods.Common/Widgets/HueSliderWidget.cs b/OpenRA.Mods.Common/Widgets/HueSliderWidget.cs index 2c9f9dca10..1d12756740 100644 --- a/OpenRA.Mods.Common/Widgets/HueSliderWidget.cs +++ b/OpenRA.Mods.Common/Widgets/HueSliderWidget.cs @@ -39,9 +39,7 @@ namespace OpenRA.Mods.Common.Widgets var c = (int*)cc; for (var h = 0; h < 256; h++) { - #pragma warning disable IDE0047 - (*(c + 0 * 256 + h)) = Color.FromAhsv(h / 255f, 1, 1).ToArgb(); - #pragma warning restore IDE0047 + *(c + 0 * 256 + h) = Color.FromAhsv(h / 255f, 1, 1).ToArgb(); } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/WorldTooltipLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/WorldTooltipLogic.cs index 73c4783601..1e55ed57fe 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/WorldTooltipLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/WorldTooltipLogic.cs @@ -65,24 +65,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic labelText = viewport.ResourceTooltip; break; case WorldTooltipType.Actor: - { - o = viewport.ActorTooltip.Owner; - showOwner = o != null && !o.NonCombatant && viewport.ActorTooltip.TooltipInfo.IsOwnerRowVisible; + { + o = viewport.ActorTooltip.Owner; + showOwner = o != null && !o.NonCombatant && viewport.ActorTooltip.TooltipInfo.IsOwnerRowVisible; - var stance = o == null || world.RenderPlayer == null ? PlayerRelationship.None : o.RelationshipWith(world.RenderPlayer); - labelText = viewport.ActorTooltip.TooltipInfo.TooltipForPlayerStance(stance); - break; - } + var stance = o == null || world.RenderPlayer == null ? PlayerRelationship.None : o.RelationshipWith(world.RenderPlayer); + labelText = viewport.ActorTooltip.TooltipInfo.TooltipForPlayerStance(stance); + break; + } case WorldTooltipType.FrozenActor: - { - o = viewport.FrozenActorTooltip.TooltipOwner; - showOwner = o != null && !o.NonCombatant && viewport.FrozenActorTooltip.TooltipInfo.IsOwnerRowVisible; + { + o = viewport.FrozenActorTooltip.TooltipOwner; + showOwner = o != null && !o.NonCombatant && viewport.FrozenActorTooltip.TooltipInfo.IsOwnerRowVisible; - var stance = o == null || world.RenderPlayer == null ? PlayerRelationship.None : o.RelationshipWith(world.RenderPlayer); - labelText = viewport.FrozenActorTooltip.TooltipInfo.TooltipForPlayerStance(stance); - break; - } + var stance = o == null || world.RenderPlayer == null ? PlayerRelationship.None : o.RelationshipWith(world.RenderPlayer); + labelText = viewport.FrozenActorTooltip.TooltipInfo.TooltipForPlayerStance(stance); + break; + } } if (viewport.ActorTooltipExtra != null) diff --git a/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs index 18581affab..0a805996f0 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs @@ -749,8 +749,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic var players = item.GetOrNull("PLAYERS"); if (players != null) { - var label = $"{game.Players + game.Bots} / {game.MaxPlayers + game.Bots}" - + (game.Spectators > 0 ? $" + {game.Spectators}" : ""); + var label = + $"{game.Players + game.Bots} / {game.MaxPlayers + game.Bots}" + + (game.Spectators > 0 ? $" + {game.Spectators}" : ""); var color = canJoin ? players.TextColor : incompatibleGameColor; players.GetText = () => label; diff --git a/OpenRA.Platforms.Default/Sdl2Input.cs b/OpenRA.Platforms.Default/Sdl2Input.cs index ba555fbd67..19cb6c53e0 100644 --- a/OpenRA.Platforms.Default/Sdl2Input.cs +++ b/OpenRA.Platforms.Default/Sdl2Input.cs @@ -79,147 +79,87 @@ namespace OpenRA.Platforms.Default break; case SDL.SDL_EventType.SDL_WINDOWEVENT: + { + switch (e.window.windowEvent) { - switch (e.window.windowEvent) - { - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_LOST: - device.HasInputFocus = false; - break; + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_LOST: + device.HasInputFocus = false; + break; - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED: - device.HasInputFocus = true; - break; + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED: + device.HasInputFocus = true; + break; - // Triggered when moving between displays with different DPI settings - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED: - device.WindowSizeChanged(); - break; + // Triggered when moving between displays with different DPI settings + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED: + device.WindowSizeChanged(); + break; - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_HIDDEN: - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MINIMIZED: - device.IsSuspended = true; - break; + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_HIDDEN: + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MINIMIZED: + device.IsSuspended = true; + break; - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_EXPOSED: - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SHOWN: - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MAXIMIZED: - case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESTORED: - device.IsSuspended = false; - break; - } - - break; + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_EXPOSED: + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SHOWN: + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MAXIMIZED: + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESTORED: + device.IsSuspended = false; + break; } + break; + } + case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN: case SDL.SDL_EventType.SDL_MOUSEBUTTONUP: + { + // Mouse 1, Mouse 2 and Mouse 3 are handled as mouse inputs + // Mouse 4 and Mouse 5 are treated as (pseudo) keyboard inputs + if (e.button.button == SDL.SDL_BUTTON_LEFT || + e.button.button == SDL.SDL_BUTTON_MIDDLE || + e.button.button == SDL.SDL_BUTTON_RIGHT) { - // Mouse 1, Mouse 2 and Mouse 3 are handled as mouse inputs - // Mouse 4 and Mouse 5 are treated as (pseudo) keyboard inputs - if (e.button.button == SDL.SDL_BUTTON_LEFT || - e.button.button == SDL.SDL_BUTTON_MIDDLE || - e.button.button == SDL.SDL_BUTTON_RIGHT) + if (pendingMotion != null) { - if (pendingMotion != null) - { - inputHandler.OnMouseInput(pendingMotion.Value); - pendingMotion = null; - } - - var button = MakeButton(e.button.button); - - if (e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN) - lastButtonBits |= button; - else - lastButtonBits &= ~button; - - var input = lockedMousePosition ?? new int2(e.button.x, e.button.y); - var pos = EventPosition(device, input.X, input.Y); - - if (e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN) - inputHandler.OnMouseInput(new MouseInput( - MouseInputEvent.Down, button, pos, int2.Zero, mods, - MultiTapDetection.DetectFromMouse(e.button.button, pos))); - else - inputHandler.OnMouseInput(new MouseInput( - MouseInputEvent.Up, button, pos, int2.Zero, mods, - MultiTapDetection.InfoFromMouse(e.button.button))); + inputHandler.OnMouseInput(pendingMotion.Value); + pendingMotion = null; } - if (e.button.button == SDL.SDL_BUTTON_X1 || - e.button.button == SDL.SDL_BUTTON_X2) - { - Keycode keyCode; + var button = MakeButton(e.button.button); - if (e.button.button == SDL.SDL_BUTTON_X1) - keyCode = Keycode.MOUSE4; - else - keyCode = Keycode.MOUSE5; + if (e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN) + lastButtonBits |= button; + else + lastButtonBits &= ~button; - var type = e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN ? - KeyInputEvent.Down : KeyInputEvent.Up; - - var tapCount = e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN ? - MultiTapDetection.DetectFromKeyboard(keyCode, mods) : - MultiTapDetection.InfoFromKeyboard(keyCode, mods); - - var keyEvent = new KeyInput - { - Event = type, - Key = keyCode, - Modifiers = mods, - UnicodeChar = '?', - MultiTapCount = tapCount, - IsRepeat = e.key.repeat != 0 - }; - inputHandler.OnKeyInput(keyEvent); - } - - break; - } - - case SDL.SDL_EventType.SDL_MOUSEMOTION: - { - var mousePos = new int2(e.motion.x, e.motion.y); - var input = lockedMousePosition ?? mousePos; + var input = lockedMousePosition ?? new int2(e.button.x, e.button.y); var pos = EventPosition(device, input.X, input.Y); - var delta = lockedMousePosition == null - ? EventPosition(device, e.motion.xrel, e.motion.yrel) - : mousePos - lockedMousePosition.Value; - - pendingMotion = new MouseInput( - MouseInputEvent.Move, lastButtonBits, pos, delta, mods, 0); - - break; + if (e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN) + inputHandler.OnMouseInput(new MouseInput( + MouseInputEvent.Down, button, pos, int2.Zero, mods, + MultiTapDetection.DetectFromMouse(e.button.button, pos))); + else + inputHandler.OnMouseInput(new MouseInput( + MouseInputEvent.Up, button, pos, int2.Zero, mods, + MultiTapDetection.InfoFromMouse(e.button.button))); } - case SDL.SDL_EventType.SDL_MOUSEWHEEL: + if (e.button.button == SDL.SDL_BUTTON_X1 || + e.button.button == SDL.SDL_BUTTON_X2) { - SDL.SDL_GetMouseState(out var x, out var y); + Keycode keyCode; - var pos = EventPosition(device, x, y); - inputHandler.OnMouseInput(new MouseInput(MouseInputEvent.Scroll, MouseButton.None, pos, new int2(0, e.wheel.y), mods, 0)); + if (e.button.button == SDL.SDL_BUTTON_X1) + keyCode = Keycode.MOUSE4; + else + keyCode = Keycode.MOUSE5; - break; - } - - case SDL.SDL_EventType.SDL_TEXTINPUT: - { - var rawBytes = new byte[SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE]; - unsafe { Marshal.Copy((IntPtr)e.text.text, rawBytes, 0, SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE); } - inputHandler.OnTextInput(Encoding.UTF8.GetString(rawBytes, 0, Array.IndexOf(rawBytes, (byte)0))); - break; - } - - case SDL.SDL_EventType.SDL_KEYDOWN: - case SDL.SDL_EventType.SDL_KEYUP: - { - var keyCode = (Keycode)e.key.keysym.sym; - var type = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? + var type = e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN ? KeyInputEvent.Down : KeyInputEvent.Up; - var tapCount = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? + var tapCount = e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN ? MultiTapDetection.DetectFromKeyboard(keyCode, mods) : MultiTapDetection.InfoFromKeyboard(keyCode, mods); @@ -228,20 +168,80 @@ namespace OpenRA.Platforms.Default Event = type, Key = keyCode, Modifiers = mods, - UnicodeChar = (char)e.key.keysym.sym, + UnicodeChar = '?', MultiTapCount = tapCount, IsRepeat = e.key.repeat != 0 }; - - // Special case workaround for windows users - if (e.key.keysym.sym == SDL.SDL_Keycode.SDLK_F4 && mods.HasModifier(Modifiers.Alt) && - Platform.CurrentPlatform == PlatformType.Windows) - Game.Exit(); - else - inputHandler.OnKeyInput(keyEvent); - - break; + inputHandler.OnKeyInput(keyEvent); } + + break; + } + + case SDL.SDL_EventType.SDL_MOUSEMOTION: + { + var mousePos = new int2(e.motion.x, e.motion.y); + var input = lockedMousePosition ?? mousePos; + var pos = EventPosition(device, input.X, input.Y); + + var delta = lockedMousePosition == null + ? EventPosition(device, e.motion.xrel, e.motion.yrel) + : mousePos - lockedMousePosition.Value; + + pendingMotion = new MouseInput( + MouseInputEvent.Move, lastButtonBits, pos, delta, mods, 0); + + break; + } + + case SDL.SDL_EventType.SDL_MOUSEWHEEL: + { + SDL.SDL_GetMouseState(out var x, out var y); + + var pos = EventPosition(device, x, y); + inputHandler.OnMouseInput(new MouseInput(MouseInputEvent.Scroll, MouseButton.None, pos, new int2(0, e.wheel.y), mods, 0)); + + break; + } + + case SDL.SDL_EventType.SDL_TEXTINPUT: + { + var rawBytes = new byte[SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE]; + unsafe { Marshal.Copy((IntPtr)e.text.text, rawBytes, 0, SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE); } + inputHandler.OnTextInput(Encoding.UTF8.GetString(rawBytes, 0, Array.IndexOf(rawBytes, (byte)0))); + break; + } + + case SDL.SDL_EventType.SDL_KEYDOWN: + case SDL.SDL_EventType.SDL_KEYUP: + { + var keyCode = (Keycode)e.key.keysym.sym; + var type = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? + KeyInputEvent.Down : KeyInputEvent.Up; + + var tapCount = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? + MultiTapDetection.DetectFromKeyboard(keyCode, mods) : + MultiTapDetection.InfoFromKeyboard(keyCode, mods); + + var keyEvent = new KeyInput + { + Event = type, + Key = keyCode, + Modifiers = mods, + UnicodeChar = (char)e.key.keysym.sym, + MultiTapCount = tapCount, + IsRepeat = e.key.repeat != 0 + }; + + // Special case workaround for windows users + if (e.key.keysym.sym == SDL.SDL_Keycode.SDLK_F4 && mods.HasModifier(Modifiers.Alt) && + Platform.CurrentPlatform == PlatformType.Windows) + Game.Exit(); + else + inputHandler.OnKeyInput(keyEvent); + + break; + } } } diff --git a/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs b/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs index 61b3449f09..8589cda373 100644 --- a/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs +++ b/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs @@ -99,7 +99,7 @@ namespace OpenRA.Platforms.Default getCreateVertexBuffer = tuple => { - (object t, var type) = ((int, Type))tuple; + (object t, var type) = ((int, Type))tuple; var vertexBuffer = context.GetType().GetMethod(nameof(CreateVertexBuffer)).MakeGenericMethod(type).Invoke(context, new[] { t }); return typeof(ThreadedVertexBuffer<>).MakeGenericType(type).GetConstructors()[0].Invoke(new[] { this, vertexBuffer }); };