From 5a0bcc01a61854b3274e128659355ab96def5cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Mail=C3=A4nder?= Date: Sun, 11 Apr 2021 14:30:00 +0100 Subject: [PATCH] Add a lint check for trait placement on hardcoded actor names. --- OpenRA.Game/Actor.cs | 9 ++++ OpenRA.Game/GameRules/Ruleset.cs | 4 +- OpenRA.Game/Graphics/CursorProvider.cs | 2 +- OpenRA.Game/Map/Map.cs | 2 +- OpenRA.Game/Map/MapPlayers.cs | 2 +- OpenRA.Game/Player.cs | 13 ++--- OpenRA.Game/Primitives/ActorInfoDictionary.cs | 48 +++++++++++++++++++ OpenRA.Game/Scripting/ScriptContext.cs | 2 +- OpenRA.Game/Server/Server.cs | 2 +- OpenRA.Game/Settings.cs | 2 +- OpenRA.Game/Traits/DebugPauseState.cs | 1 + OpenRA.Game/Traits/LintAttributes.cs | 10 ++++ OpenRA.Game/Traits/Player/FrozenActorLayer.cs | 1 + .../Traits/Player/PlayerColorPalette.cs | 3 +- OpenRA.Game/Traits/Player/Shroud.cs | 1 + .../Traits/World/DebugVisualizations.cs | 1 + OpenRA.Game/Traits/World/Faction.cs | 1 + OpenRA.Game/Traits/World/ScreenMap.cs | 1 + OpenRA.Game/Traits/World/ScreenShaker.cs | 1 + OpenRA.Game/World.cs | 4 +- OpenRA.Mods.Cnc/Traits/GpsWatcher.cs | 1 + .../ChronoshiftPaletteEffect.cs | 1 + .../PaletteEffects/LightPaletteRotator.cs | 1 + OpenRA.Mods.Cnc/Traits/World/ShroudPalette.cs | 1 + .../Traits/World/TSShroudPalette.cs | 1 + .../UtilityCommands/RemapShpCommand.cs | 4 +- OpenRA.Mods.Common/Commands/ChatCommands.cs | 1 + .../Commands/DebugVisualizationCommands.cs | 1 + OpenRA.Mods.Common/Commands/DevCommands.cs | 1 + OpenRA.Mods.Common/Commands/HelpCommand.cs | 1 + OpenRA.Mods.Common/Commands/PlayerCommands.cs | 1 + .../Lint/CheckLocomotorReferences.cs | 2 +- OpenRA.Mods.Common/Lint/CheckPlayers.cs | 2 +- OpenRA.Mods.Common/Lint/CheckSequences.cs | 2 +- OpenRA.Mods.Common/Lint/CheckTraitLocation.cs | 43 +++++++++++++++++ .../ServerTraits/LobbyCommands.cs | 18 +++---- .../ServerTraits/LobbySettingsNotification.cs | 4 +- OpenRA.Mods.Common/Traits/Buildings/Bridge.cs | 2 +- .../Traits/Buildings/BuildingInfluence.cs | 1 + .../Traits/Buildings/TransformsIntoMobile.cs | 2 +- OpenRA.Mods.Common/Traits/Mobile.cs | 2 +- .../Traits/Modifiers/FrozenUnderFog.cs | 2 +- .../PaletteEffects/FlashPaletteEffect.cs | 1 + .../PaletteEffects/MenuPaletteEffect.cs | 1 + .../PaletteEffects/RotationPaletteEffect.cs | 1 + .../Traits/Player/AllyRepair.cs | 1 + .../Traits/Player/BaseAttackNotifier.cs | 1 + .../Player/ClassicParallelProductionQueue.cs | 1 + .../Traits/Player/ClassicProductionQueue.cs | 1 + .../Player/ConquestVictoryConditions.cs | 2 +- .../Traits/Player/DeveloperMode.cs | 1 + .../Traits/Player/EnemyWatcher.cs | 1 + .../GrantConditionOnPrerequisiteManager.cs | 2 +- .../Traits/Player/HarvesterAttackNotifier.cs | 1 + .../Traits/Player/MissionObjectives.cs | 3 ++ .../Traits/Player/PlaceBeacon.cs | 1 + .../Traits/Player/PlaceBuilding.cs | 1 + .../Traits/Player/PlayerExperience.cs | 1 + .../Traits/Player/PlayerRadarTerrain.cs | 2 +- .../Traits/Player/PlayerResources.cs | 1 + .../Traits/Player/PlayerStatistics.cs | 1 + .../Traits/Player/ProvidesTechPrerequisite.cs | 1 + .../Traits/Player/ResourceStorageWarning.cs | 1 + OpenRA.Mods.Common/Traits/Player/TechTree.cs | 1 + .../Traits/Player/TimeLimitManager.cs | 1 + .../Traits/Power/Player/PowerManager.cs | 1 + .../Traits/ProductionQueueFromSelection.cs | 1 + .../Traits/ProximityCapturable.cs | 2 +- .../Render/CustomTerrainDebugOverlay.cs | 1 + .../Traits/Render/ProductionBar.cs | 2 +- .../Render/VeteranProductionIconOverlay.cs | 1 + .../SupportPowers/SupportPowerManager.cs | 1 + .../Traits/TerrainLightSource.cs | 2 +- OpenRA.Mods.Common/Traits/World/ActorMap.cs | 1 + .../Traits/World/ActorSpawnManager.cs | 1 + .../Traits/World/CrateSpawner.cs | 1 + .../Traits/World/CreateMapPlayers.cs | 5 +- .../Traits/World/DomainIndex.cs | 1 + .../Traits/World/EditorActionManager.cs | 1 + .../Traits/World/EditorActorLayer.cs | 1 + .../Traits/World/EditorCursorLayer.cs | 1 + .../Traits/World/EditorResourceLayer.cs | 3 +- .../Traits/World/EditorSelectionLayer.cs | 1 + .../Traits/World/GameSaveViewportManager.cs | 1 + .../Traits/World/IndexedPalette.cs | 1 + .../Traits/World/LegacyBridgeLayer.cs | 1 + .../Traits/World/LoadWidgetAtGameStart.cs | 1 + .../Traits/World/LobbyPrerequisiteCheckbox.cs | 1 + OpenRA.Mods.Common/Traits/World/Locomotor.cs | 1 + .../Traits/World/MapBuildRadius.cs | 1 + OpenRA.Mods.Common/Traits/World/MapCreeps.cs | 1 + OpenRA.Mods.Common/Traits/World/MapOptions.cs | 3 +- .../Traits/World/MapStartingLocations.cs | 1 + .../Traits/World/MapStartingUnits.cs | 1 + .../Traits/World/MusicPlaylist.cs | 1 + .../Traits/World/PaletteFromFile.cs | 1 + .../Traits/World/PaletteFromGimpOrJascFile.cs | 1 + .../World/PaletteFromPaletteWithAlpha.cs | 1 + .../PaletteFromPlayerPaletteWithAlpha.cs | 1 + .../Traits/World/PaletteFromPng.cs | 1 + .../Traits/World/PaletteFromRGBA.cs | 1 + OpenRA.Mods.Common/Traits/World/PathFinder.cs | 1 + OpenRA.Mods.Common/Traits/World/RadarPings.cs | 1 + .../Traits/World/ResourceClaimLayer.cs | 1 + .../Traits/World/ResourceLayer.cs | 1 + .../Traits/World/ResourceRenderer.cs | 1 + OpenRA.Mods.Common/Traits/World/Selection.cs | 1 + .../Traits/World/ShroudRenderer.cs | 1 + .../Traits/World/SmudgeLayer.cs | 1 + .../Traits/World/SpawnMapActors.cs | 1 + .../Traits/World/SpawnStartingUnits.cs | 5 +- .../Traits/World/StartGameNotification.cs | 1 + .../Traits/World/TerrainGeometryOverlay.cs | 1 + .../Traits/World/TerrainRenderer.cs | 1 + .../Traits/World/ValidateOrder.cs | 1 + .../Traits/World/WarheadDebugOverlay.cs | 1 + .../UtilityCommands/CheckMissingSprites.cs | 2 +- .../Logic/Ingame/GameInfoBriefingLogic.cs | 2 +- .../Widgets/Logic/Ingame/GameInfoLogic.cs | 2 +- .../Widgets/Logic/Ingame/IngameMenuLogic.cs | 2 +- .../Logic/Ingame/MenuButtonsChromeLogic.cs | 2 +- .../Widgets/Logic/Lobby/LobbyLogic.cs | 6 +-- .../Widgets/Logic/Lobby/LobbyOptionsLogic.cs | 4 +- .../Widgets/Logic/Lobby/LobbyUtils.cs | 2 +- .../Widgets/Logic/MissionBrowserLogic.cs | 6 +-- .../Widgets/Logic/ReplayBrowserLogic.cs | 2 +- .../Widgets/Logic/ServerListLogic.cs | 2 +- .../Traits/World/BuildableTerrainLayer.cs | 1 + .../Traits/World/D2kResourceRenderer.cs | 2 + 129 files changed, 266 insertions(+), 67 deletions(-) create mode 100644 OpenRA.Game/Primitives/ActorInfoDictionary.cs create mode 100644 OpenRA.Mods.Common/Lint/CheckTraitLocation.cs diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index 19b842cd39..fc84eaa999 100644 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -24,6 +24,15 @@ using OpenRA.Traits; namespace OpenRA { + [Flags] + public enum SystemActors + { + Player = 0, + EditorPlayer = 1, + World = 2, + EditorWorld = 4 + } + public sealed class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable, IDisposable { internal readonly struct SyncHash diff --git a/OpenRA.Game/GameRules/Ruleset.cs b/OpenRA.Game/GameRules/Ruleset.cs index 4e3982c740..235a4dc551 100644 --- a/OpenRA.Game/GameRules/Ruleset.cs +++ b/OpenRA.Game/GameRules/Ruleset.cs @@ -22,7 +22,7 @@ namespace OpenRA { public class Ruleset { - public readonly IReadOnlyDictionary Actors; + public readonly ActorInfoDictionary Actors; public readonly IReadOnlyDictionary Weapons; public readonly IReadOnlyDictionary Voices; public readonly IReadOnlyDictionary Notifications; @@ -41,7 +41,7 @@ namespace OpenRA SequenceProvider sequences, IReadOnlyDictionary modelSequences) { - Actors = actors; + Actors = new ActorInfoDictionary(actors); Weapons = weapons; Voices = voices; Notifications = notifications; diff --git a/OpenRA.Game/Graphics/CursorProvider.cs b/OpenRA.Game/Graphics/CursorProvider.cs index 13edc2f045..370dc09a68 100644 --- a/OpenRA.Game/Graphics/CursorProvider.cs +++ b/OpenRA.Game/Graphics/CursorProvider.cs @@ -31,7 +31,7 @@ namespace OpenRA.Graphics // Overwrite previous definitions if there are duplicates var pals = new Dictionary(); - foreach (var p in modData.DefaultRules.Actors["world"].TraitInfos()) + foreach (var p in modData.DefaultRules.Actors[SystemActors.World].TraitInfos()) if (p.Palette != null) pals[p.Palette] = p; diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 6bd505a182..0f75bcc6c8 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -708,7 +708,7 @@ namespace OpenRA } // ResourceLayer is on world actor, which isn't caught above, so an extra check for it. - var worldActorInfo = Rules.Actors["world"]; + var worldActorInfo = Rules.Actors[SystemActors.World]; var worldimpsis = worldActorInfo.TraitInfos(); foreach (var worldimpsi in worldimpsis) worldimpsi.PopulateMapPreviewSignatureCells(this, worldActorInfo, null, positions); diff --git a/OpenRA.Game/Map/MapPlayers.cs b/OpenRA.Game/Map/MapPlayers.cs index 5cab1716ce..8a45a12978 100644 --- a/OpenRA.Game/Map/MapPlayers.cs +++ b/OpenRA.Game/Map/MapPlayers.cs @@ -30,7 +30,7 @@ namespace OpenRA public MapPlayers(Ruleset rules, int playerCount) { - var firstFaction = rules.Actors["world"].TraitInfos() + var firstFaction = rules.Actors[SystemActors.World].TraitInfos() .First(f => f.Selectable).InternalName; Players = new Dictionary diff --git a/OpenRA.Game/Player.cs b/OpenRA.Game/Player.cs index 73a2252054..a9c0f65a12 100644 --- a/OpenRA.Game/Player.cs +++ b/OpenRA.Game/Player.cs @@ -37,9 +37,6 @@ namespace OpenRA public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding { - public const string PlayerActorType = "Player"; - public const string EditorPlayerActorType = "EditorPlayer"; - struct StanceColors { public Color Self; @@ -129,13 +126,13 @@ namespace OpenRA static FactionInfo ResolveFaction(World world, string factionName, MersenneTwister playerRandom, bool requireSelectable) { - var factionInfos = world.Map.Rules.Actors["world"].TraitInfos(); + var factionInfos = world.Map.Rules.Actors[SystemActors.World].TraitInfos(); return ResolveFaction(factionName, factionInfos, playerRandom, requireSelectable); } static FactionInfo ResolveDisplayFaction(World world, string factionName) { - var factions = world.Map.Rules.Actors["world"].TraitInfos().ToArray(); + var factions = world.Map.Rules.Actors[SystemActors.World].TraitInfos().ToArray(); return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First(); } @@ -165,7 +162,7 @@ namespace OpenRA { ClientIndex = client.Index; Color = client.Color; - PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors["player"].TraitInfos()); + PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors[SystemActors.Player].TraitInfos()); BotType = client.Bot; Faction = ResolveFaction(world, client.Faction, playerRandom, !pr.LockFaction); @@ -206,8 +203,8 @@ namespace OpenRA // querying player traits in INotifyCreated.Created would crash. // Therefore assign the uninitialized actor and run the Created callbacks // by calling Initialize ourselves. - var playerActorType = world.Type == WorldType.Editor ? EditorPlayerActorType : PlayerActorType; - PlayerActor = new Actor(world, playerActorType, new TypeDictionary { new OwnerInit(this) }); + var playerActorType = world.Type == WorldType.Editor ? SystemActors.EditorPlayer : SystemActors.Player; + PlayerActor = new Actor(world, playerActorType.ToString(), new TypeDictionary { new OwnerInit(this) }); PlayerActor.Initialize(true); Shroud = PlayerActor.Trait(); diff --git a/OpenRA.Game/Primitives/ActorInfoDictionary.cs b/OpenRA.Game/Primitives/ActorInfoDictionary.cs new file mode 100644 index 0000000000..5fa7ba39ce --- /dev/null +++ b/OpenRA.Game/Primitives/ActorInfoDictionary.cs @@ -0,0 +1,48 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OpenRA +{ + public class ActorInfoDictionary : IReadOnlyDictionary + { + readonly Dictionary dict; + + public ActorInfoDictionary(IReadOnlyDictionary dict) + { + if (dict == null) + throw new ArgumentNullException(nameof(dict)); + + this.dict = new Dictionary(dict); + } + + public bool ContainsKey(string key) => dict.ContainsKey(key); + + public bool TryGetValue(string key, out ActorInfo value) => dict.TryGetValue(key, out value); + + public int Count => dict.Count; + + public ActorInfo this[string key] => dict[key]; + public ActorInfo this[SystemActors key] => dict[key.ToString().ToLowerInvariant()]; + + IEnumerable IReadOnlyDictionary.Keys => dict.Keys; + IEnumerable IReadOnlyDictionary.Values => dict.Values; + + public ICollection Keys => dict.Keys; + public ICollection Values => dict.Values; + + public IEnumerator> GetEnumerator() => dict.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => dict.GetEnumerator(); + } +} diff --git a/OpenRA.Game/Scripting/ScriptContext.cs b/OpenRA.Game/Scripting/ScriptContext.cs index 5d9ba4820b..d2bddcee1b 100644 --- a/OpenRA.Game/Scripting/ScriptContext.cs +++ b/OpenRA.Game/Scripting/ScriptContext.cs @@ -159,7 +159,7 @@ namespace OpenRA.Scripting var knownPlayerCommands = Game.ModData.ObjectCreator .GetTypesImplementing() .ToArray(); - PlayerCommands = FilterCommands(world.Map.Rules.Actors["player"], knownPlayerCommands); + PlayerCommands = FilterCommands(world.Map.Rules.Actors[SystemActors.Player], knownPlayerCommands); runtime.Globals["EngineDir"] = Platform.EngineDir; runtime.DoBuffer(File.Open(Path.Combine(Platform.EngineDir, "lua", "scriptwrapper.lua"), FileMode.Open, FileAccess.Read).ReadAllText(), "scriptwrapper.lua").Dispose(); diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index de55384d36..317038d48f 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -1209,7 +1209,7 @@ namespace OpenRA.Server // The null padding is needed to keep the player indexes in sync with world.Players on the clients // This will need to change if future code wants to use worldPlayers for other purposes var playerRandom = new MersenneTwister(LobbyInfo.GlobalSettings.RandomSeed); - foreach (var cmpi in Map.Rules.Actors["world"].TraitInfos()) + foreach (var cmpi in Map.Rules.Actors[SystemActors.World].TraitInfos()) cmpi.CreateServerPlayers(Map, LobbyInfo, worldPlayers, playerRandom); if (recorder != null) diff --git a/OpenRA.Game/Settings.cs b/OpenRA.Game/Settings.cs index 924c8bc6a2..d3e1e4ef0c 100644 --- a/OpenRA.Game/Settings.cs +++ b/OpenRA.Game/Settings.cs @@ -403,7 +403,7 @@ namespace OpenRA public static string SanitizedPlayerName(string dirty) { var forbiddenNames = new string[] { "Open", "Closed" }; - var botNames = OpenRA.Game.ModData.DefaultRules.Actors["player"].TraitInfos().Select(t => t.Name); + var botNames = OpenRA.Game.ModData.DefaultRules.Actors[SystemActors.Player].TraitInfos().Select(t => t.Name); var clean = SanitizedName(dirty); diff --git a/OpenRA.Game/Traits/DebugPauseState.cs b/OpenRA.Game/Traits/DebugPauseState.cs index c298fef6ad..eacda21501 100644 --- a/OpenRA.Game/Traits/DebugPauseState.cs +++ b/OpenRA.Game/Traits/DebugPauseState.cs @@ -11,6 +11,7 @@ namespace OpenRA.Traits { + [TraitLocation(SystemActors.World)] [Desc("Checks for pause related desyncs. Attach this to the world actor.")] public class DebugPauseStateInfo : TraitInfo { diff --git a/OpenRA.Game/Traits/LintAttributes.cs b/OpenRA.Game/Traits/LintAttributes.cs index 1e84d58785..baf6659e0f 100644 --- a/OpenRA.Game/Traits/LintAttributes.cs +++ b/OpenRA.Game/Traits/LintAttributes.cs @@ -105,4 +105,14 @@ namespace OpenRA.Traits PlayerPaletteReferenceSwitch = playerPaletteReferenceSwitch; } } + + [AttributeUsage(AttributeTargets.Class)] + public sealed class TraitLocationAttribute : Attribute + { + public readonly SystemActors SystemActors; + public TraitLocationAttribute(SystemActors systemActors) + { + SystemActors = systemActors; + } + } } diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index f9cb270e7b..797b35a20b 100644 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -22,6 +22,7 @@ namespace OpenRA.Traits void OnVisibilityChanged(FrozenActor frozen); } + [TraitLocation(SystemActors.Player)] [Desc("Required for FrozenUnderFog to work. Attach this to the player actor.")] public class FrozenActorLayerInfo : TraitInfo, Requires { diff --git a/OpenRA.Game/Traits/Player/PlayerColorPalette.cs b/OpenRA.Game/Traits/Player/PlayerColorPalette.cs index 56f7a37d5c..bd7eb9bf4d 100644 --- a/OpenRA.Game/Traits/Player/PlayerColorPalette.cs +++ b/OpenRA.Game/Traits/Player/PlayerColorPalette.cs @@ -14,7 +14,8 @@ using OpenRA.Primitives; namespace OpenRA.Traits { - [Desc("Add this to the Player actor definition.")] + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] + [Desc("Add this to the World actor definition.")] public class PlayerColorPaletteInfo : TraitInfo { [PaletteReference] diff --git a/OpenRA.Game/Traits/Player/Shroud.cs b/OpenRA.Game/Traits/Player/Shroud.cs index 7bc90c8d2d..720d0fdc97 100644 --- a/OpenRA.Game/Traits/Player/Shroud.cs +++ b/OpenRA.Game/Traits/Player/Shroud.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; namespace OpenRA.Traits { + [TraitLocation(SystemActors.Player | SystemActors.EditorPlayer)] [Desc("Required for shroud and fog visibility checks. Add this to the player actor.")] public class ShroudInfo : TraitInfo, ILobbyOptions { diff --git a/OpenRA.Game/Traits/World/DebugVisualizations.cs b/OpenRA.Game/Traits/World/DebugVisualizations.cs index 27f9cc47af..39e2949e79 100644 --- a/OpenRA.Game/Traits/World/DebugVisualizations.cs +++ b/OpenRA.Game/Traits/World/DebugVisualizations.cs @@ -11,6 +11,7 @@ namespace OpenRA.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Enables visualization commands. Attach this to the world actor.")] public class DebugVisualizationsInfo : TraitInfo { } diff --git a/OpenRA.Game/Traits/World/Faction.cs b/OpenRA.Game/Traits/World/Faction.cs index 930dc1546b..1acfa464d6 100644 --- a/OpenRA.Game/Traits/World/Faction.cs +++ b/OpenRA.Game/Traits/World/Faction.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; namespace OpenRA.Traits { [Desc("Attach this to the `World` actor.")] + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class FactionInfo : TraitInfo { [Desc("This is the name exposed to the players.")] diff --git a/OpenRA.Game/Traits/World/ScreenMap.cs b/OpenRA.Game/Traits/World/ScreenMap.cs index 87157533ba..66c7640aa7 100644 --- a/OpenRA.Game/Traits/World/ScreenMap.cs +++ b/OpenRA.Game/Traits/World/ScreenMap.cs @@ -30,6 +30,7 @@ namespace OpenRA.Traits public override string ToString() { return "{0}->{1}".F(Actor.Info.Name, Bounds.GetType().Name); } } + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class ScreenMapInfo : TraitInfo { [Desc("Size of partition bins (world pixels)")] diff --git a/OpenRA.Game/Traits/World/ScreenShaker.cs b/OpenRA.Game/Traits/World/ScreenShaker.cs index 2e216cb5c4..7cdda02bb8 100644 --- a/OpenRA.Game/Traits/World/ScreenShaker.cs +++ b/OpenRA.Game/Traits/World/ScreenShaker.cs @@ -16,6 +16,7 @@ using OpenRA.Graphics; namespace OpenRA.Traits { + [TraitLocation(SystemActors.World)] public class ScreenShakerInfo : TraitInfo { public readonly float2 MinMultiplier = new float2(-3, -3); diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 3fbc21609e..97a1fbcbd9 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -202,8 +202,8 @@ namespace OpenRA ModelCache = modData.ModelSequenceLoader.CacheModels(map, modData, map.Rules.ModelSequences); - var worldActorType = type == WorldType.Editor ? "EditorWorld" : "World"; - WorldActor = CreateActor(worldActorType, new TypeDictionary()); + var worldActorType = type == WorldType.Editor ? SystemActors.EditorWorld : SystemActors.World; + WorldActor = CreateActor(worldActorType.ToString(), new TypeDictionary()); ActorMap = WorldActor.Trait(); ScreenMap = WorldActor.Trait(); Selection = WorldActor.Trait(); diff --git a/OpenRA.Mods.Cnc/Traits/GpsWatcher.cs b/OpenRA.Mods.Cnc/Traits/GpsWatcher.cs index 9bb5b0c9ae..bc88920fa8 100644 --- a/OpenRA.Mods.Cnc/Traits/GpsWatcher.cs +++ b/OpenRA.Mods.Cnc/Traits/GpsWatcher.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Required for `GpsPower`. Attach this to the player actor.")] class GpsWatcherInfo : TraitInfo { diff --git a/OpenRA.Mods.Cnc/Traits/PaletteEffects/ChronoshiftPaletteEffect.cs b/OpenRA.Mods.Cnc/Traits/PaletteEffects/ChronoshiftPaletteEffect.cs index 07cccf4d4f..89526db5af 100644 --- a/OpenRA.Mods.Cnc/Traits/PaletteEffects/ChronoshiftPaletteEffect.cs +++ b/OpenRA.Mods.Cnc/Traits/PaletteEffects/ChronoshiftPaletteEffect.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Apply palette full screen rotations during chronoshifts. Add this to the world actor.")] public class ChronoshiftPaletteEffectInfo : TraitInfo { diff --git a/OpenRA.Mods.Cnc/Traits/PaletteEffects/LightPaletteRotator.cs b/OpenRA.Mods.Cnc/Traits/PaletteEffects/LightPaletteRotator.cs index 8bde0f8f2d..359fb72ac5 100644 --- a/OpenRA.Mods.Cnc/Traits/PaletteEffects/LightPaletteRotator.cs +++ b/OpenRA.Mods.Cnc/Traits/PaletteEffects/LightPaletteRotator.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Palette effect used for blinking \"animations\" on actors.")] class LightPaletteRotatorInfo : TraitInfo { diff --git a/OpenRA.Mods.Cnc/Traits/World/ShroudPalette.cs b/OpenRA.Mods.Cnc/Traits/World/ShroudPalette.cs index 911365f261..4f4ec12493 100644 --- a/OpenRA.Mods.Cnc/Traits/World/ShroudPalette.cs +++ b/OpenRA.Mods.Cnc/Traits/World/ShroudPalette.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Adds the hard-coded shroud palette to the game")] class ShroudPaletteInfo : TraitInfo { diff --git a/OpenRA.Mods.Cnc/Traits/World/TSShroudPalette.cs b/OpenRA.Mods.Cnc/Traits/World/TSShroudPalette.cs index 7afe4bf3c3..d88d06d5cf 100644 --- a/OpenRA.Mods.Cnc/Traits/World/TSShroudPalette.cs +++ b/OpenRA.Mods.Cnc/Traits/World/TSShroudPalette.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Adds the hard-coded shroud palette to the game")] class TSShroudPaletteInfo : TraitInfo { diff --git a/OpenRA.Mods.Cnc/UtilityCommands/RemapShpCommand.cs b/OpenRA.Mods.Cnc/UtilityCommands/RemapShpCommand.cs index 74cbf100f1..5788aa0b87 100644 --- a/OpenRA.Mods.Cnc/UtilityCommands/RemapShpCommand.cs +++ b/OpenRA.Mods.Cnc/UtilityCommands/RemapShpCommand.cs @@ -42,13 +42,13 @@ namespace OpenRA.Mods.Cnc.UtilityCommands var srcModData = new ModData(utility.Mods[srcMod], utility.Mods); Game.ModData = srcModData; - var srcPaletteInfo = srcModData.DefaultRules.Actors["player"].TraitInfo(); + var srcPaletteInfo = srcModData.DefaultRules.Actors[SystemActors.Player].TraitInfo(); var srcRemapIndex = srcPaletteInfo.RemapIndex; var destMod = args[2].Split(':')[0]; var destModData = new ModData(utility.Mods[destMod], utility.Mods); Game.ModData = destModData; - var destPaletteInfo = destModData.DefaultRules.Actors["player"].TraitInfo(); + var destPaletteInfo = destModData.DefaultRules.Actors[SystemActors.Player].TraitInfo(); var destRemapIndex = destPaletteInfo.RemapIndex; var shadowIndex = new int[] { }; diff --git a/OpenRA.Mods.Common/Commands/ChatCommands.cs b/OpenRA.Mods.Common/Commands/ChatCommands.cs index f5223a49ec..f5757c635e 100644 --- a/OpenRA.Mods.Common/Commands/ChatCommands.cs +++ b/OpenRA.Mods.Common/Commands/ChatCommands.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Commands { + [TraitLocation(SystemActors.World)] [Desc("Enables commands triggered by typing them into the chatbox. Attach this to the world actor.")] public class ChatCommandsInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Commands/DebugVisualizationCommands.cs b/OpenRA.Mods.Common/Commands/DebugVisualizationCommands.cs index 75ca1a67fd..3fd326a993 100644 --- a/OpenRA.Mods.Common/Commands/DebugVisualizationCommands.cs +++ b/OpenRA.Mods.Common/Commands/DebugVisualizationCommands.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Commands { + [TraitLocation(SystemActors.World)] [Desc("Enables visualization commands via the chatbox. Attach this to the world actor.")] public class DebugVisualizationCommandsInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Commands/DevCommands.cs b/OpenRA.Mods.Common/Commands/DevCommands.cs index ae1a0df4ed..a3225ad3e0 100644 --- a/OpenRA.Mods.Common/Commands/DevCommands.cs +++ b/OpenRA.Mods.Common/Commands/DevCommands.cs @@ -17,6 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Commands { + [TraitLocation(SystemActors.World)] [Desc("Enables developer cheats via the chatbox. Attach this to the world actor.")] public class DevCommandsInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Commands/HelpCommand.cs b/OpenRA.Mods.Common/Commands/HelpCommand.cs index a8470e8a6d..c3c7ef635d 100644 --- a/OpenRA.Mods.Common/Commands/HelpCommand.cs +++ b/OpenRA.Mods.Common/Commands/HelpCommand.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Commands { + [TraitLocation(SystemActors.World)] [Desc("Shows a list of available commands in the chatbox. Attach this to the world actor.")] public class HelpCommandInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Commands/PlayerCommands.cs b/OpenRA.Mods.Common/Commands/PlayerCommands.cs index 5eee30aceb..095b50cadd 100644 --- a/OpenRA.Mods.Common/Commands/PlayerCommands.cs +++ b/OpenRA.Mods.Common/Commands/PlayerCommands.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Commands { + [TraitLocation(SystemActors.World)] [Desc("Allows the player to pause or surrender the game via the chatbox. Attach this to the world actor.")] public class PlayerCommandsInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Lint/CheckLocomotorReferences.cs b/OpenRA.Mods.Common/Lint/CheckLocomotorReferences.cs index 45343cf8ca..e29e3729a0 100644 --- a/OpenRA.Mods.Common/Lint/CheckLocomotorReferences.cs +++ b/OpenRA.Mods.Common/Lint/CheckLocomotorReferences.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, ModData modData, Ruleset rules) { - var worldActor = rules.Actors["world"]; + var worldActor = rules.Actors[SystemActors.World]; var locomotorInfos = worldActor.TraitInfos().ToArray(); foreach (var li in locomotorInfos) foreach (var otherLocomotor in locomotorInfos) diff --git a/OpenRA.Mods.Common/Lint/CheckPlayers.cs b/OpenRA.Mods.Common/Lint/CheckPlayers.cs index 88836c4d7e..807696b7ee 100644 --- a/OpenRA.Mods.Common/Lint/CheckPlayers.cs +++ b/OpenRA.Mods.Common/Lint/CheckPlayers.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Lint if (!worldOwnerFound) emitError("Found no player owning the world."); - var worldActor = map.Rules.Actors["world"]; + var worldActor = map.Rules.Actors[SystemActors.World]; var factions = worldActor.TraitInfos().Select(f => f.InternalName).ToHashSet(); foreach (var player in players.Values) if (!string.IsNullOrWhiteSpace(player.Faction) && !factions.Contains(player.Faction)) diff --git a/OpenRA.Mods.Common/Lint/CheckSequences.cs b/OpenRA.Mods.Common/Lint/CheckSequences.cs index 86acb9c444..6185199994 100644 --- a/OpenRA.Mods.Common/Lint/CheckSequences.cs +++ b/OpenRA.Mods.Common/Lint/CheckSequences.cs @@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Lint void Run(Action emitError, Action emitWarning, Ruleset rules, SequenceProvider sequences) { - var factions = rules.Actors["world"].TraitInfos().Select(f => f.InternalName).ToArray(); + var factions = rules.Actors[SystemActors.World].TraitInfos().Select(f => f.InternalName).ToArray(); foreach (var actorInfo in rules.Actors) { // Actors may have 0 or 1 RenderSprites traits diff --git a/OpenRA.Mods.Common/Lint/CheckTraitLocation.cs b/OpenRA.Mods.Common/Lint/CheckTraitLocation.cs new file mode 100644 index 0000000000..faa2ad7fbb --- /dev/null +++ b/OpenRA.Mods.Common/Lint/CheckTraitLocation.cs @@ -0,0 +1,43 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Linq; +using DiscordRPC.Helper; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Lint +{ + public class CheckTraitLocation : ILintRulesPass + { + void ILintRulesPass.Run(Action emitError, Action emitWarning, ModData modData, Ruleset rules) + { + foreach (var actorInfo in rules.Actors) + { + foreach (var traitInfo in actorInfo.Value.TraitInfos()) + { + var traitLocation = traitInfo.GetType().GetCustomAttributes(true).FirstOrDefault(); + if (traitLocation == null) + continue; + + if (!Enum.TryParse(actorInfo.Key, true, out SystemActors systemActor) || !traitLocation.SystemActors.HasFlag(systemActor)) + { + // Remove the "Info" suffix + var traitName = traitInfo.GetType().Name; + traitName = traitName.Remove(traitName.Length - 4); + var locations = traitLocation.SystemActors.ToString().Replace(", ", " or "); + emitError("{0} does not belong on {1}. It is a system trait meant for {2}.".F(traitName, actorInfo.Key, locations)); + } + } + } + } + } +} diff --git a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs index d254c578ec..dd6f5d4c71 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs @@ -357,7 +357,7 @@ namespace OpenRA.Mods.Common.Server } var botType = parts[2]; - var botInfo = server.Map.Rules.Actors["player"].TraitInfos() + var botInfo = server.Map.Rules.Actors[SystemActors.Player].TraitInfos() .FirstOrDefault(b => b.Type == botType); if (botInfo == null) @@ -440,7 +440,7 @@ namespace OpenRA.Mods.Common.Server LoadMapSettings(server, server.LobbyInfo.GlobalSettings, server.Map.Rules); // Reset client states - var selectableFactions = server.Map.Rules.Actors["world"].TraitInfos() + var selectableFactions = server.Map.Rules.Actors[SystemActors.World].TraitInfos() .Where(f => f.Selectable) .Select(f => f.InternalName) .ToList(); @@ -457,7 +457,7 @@ namespace OpenRA.Mods.Common.Server // - Players who now lack a slot are made observers // - Bots who now lack a slot are dropped // - Bots who are not defined in the map rules are dropped - var botTypes = server.Map.Rules.Actors["player"].TraitInfos().Select(t => t.Type); + var botTypes = server.Map.Rules.Actors[SystemActors.Player].TraitInfos().Select(t => t.Type); var slots = server.LobbyInfo.Slots.Keys.ToArray(); var i = 0; foreach (var os in oldSlots) @@ -534,8 +534,8 @@ namespace OpenRA.Mods.Common.Server return true; } - var allOptions = server.Map.Rules.Actors["player"].TraitInfos() - .Concat(server.Map.Rules.Actors["world"].TraitInfos()) + var allOptions = server.Map.Rules.Actors[SystemActors.Player].TraitInfos() + .Concat(server.Map.Rules.Actors[SystemActors.World].TraitInfos()) .SelectMany(t => t.LobbyOptions(server.Map.Rules)); // Overwrite keys with duplicate ids @@ -775,7 +775,7 @@ namespace OpenRA.Mods.Common.Server if (server.LobbyInfo.Slots[targetClient.Slot].LockFaction) return true; - var factions = server.Map.Rules.Actors["world"].TraitInfos() + var factions = server.Map.Rules.Actors[SystemActors.World].TraitInfos() .Where(f => f.Selectable).Select(f => f.InternalName); if (!factions.Contains(parts[1])) @@ -1045,8 +1045,8 @@ namespace OpenRA.Mods.Common.Server { lock (server.LobbyInfo) { - var options = rules.Actors["player"].TraitInfos() - .Concat(rules.Actors["world"].TraitInfos()) + var options = rules.Actors[SystemActors.Player].TraitInfos() + .Concat(rules.Actors[SystemActors.World].TraitInfos()) .SelectMany(t => t.LobbyOptions(rules)); foreach (var o in options) @@ -1100,7 +1100,7 @@ namespace OpenRA.Mods.Common.Server static string MissionBriefingOrDefault(S server) { - var missionData = server.Map.Rules.Actors["world"].TraitInfoOrDefault(); + var missionData = server.Map.Rules.Actors[SystemActors.World].TraitInfoOrDefault(); if (missionData != null && !string.IsNullOrEmpty(missionData.Briefing)) return missionData.Briefing.Replace("\\n", "\n"); diff --git a/OpenRA.Mods.Common/ServerTraits/LobbySettingsNotification.cs b/OpenRA.Mods.Common/ServerTraits/LobbySettingsNotification.cs index 17cf1e8559..744009d037 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbySettingsNotification.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbySettingsNotification.cs @@ -25,8 +25,8 @@ namespace OpenRA.Mods.Common.Server var defaults = new Session.Global(); LobbyCommands.LoadMapSettings(server, defaults, server.Map.Rules); - var options = server.Map.Rules.Actors["player"].TraitInfos() - .Concat(server.Map.Rules.Actors["world"].TraitInfos()) + var options = server.Map.Rules.Actors[SystemActors.Player].TraitInfos() + .Concat(server.Map.Rules.Actors[SystemActors.World].TraitInfos()) .SelectMany(t => t.LobbyOptions(server.Map.Rules)) .ToDictionary(o => o.Id, o => o); diff --git a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs index 0196c3dbc9..9ff5149c2e 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs @@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits public void RulesetLoaded(Ruleset rules, ActorInfo ai) { - if (!rules.Actors["world"].HasTraitInfo()) + if (!rules.Actors[SystemActors.World].HasTraitInfo()) throw new YamlException("Bridge requires a tile-based terrain renderer."); if (string.IsNullOrEmpty(DemolishWeapon)) diff --git a/OpenRA.Mods.Common/Traits/Buildings/BuildingInfluence.cs b/OpenRA.Mods.Common/Traits/Buildings/BuildingInfluence.cs index 987afd5de0..97d5972df3 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/BuildingInfluence.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/BuildingInfluence.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("A dictionary of buildings placed on the map. Attach this to the world actor.")] public class BuildingInfluenceInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs b/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs index 2c49c379ca..c58f89cbee 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs @@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits public override void RulesetLoaded(Ruleset rules, ActorInfo ai) { - var locomotorInfos = rules.Actors["world"].TraitInfos(); + var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos(); LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor); if (LocomotorInfo == null) throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor)); diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index ff52f4b501..1b8a33270b 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits public override void RulesetLoaded(Ruleset rules, ActorInfo ai) { - var locomotorInfos = rules.Actors["world"].TraitInfos(); + var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos(); LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor); if (LocomotorInfo == null) throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor)); diff --git a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs index 2420ab36c9..1eccae6452 100644 --- a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs +++ b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Traits var map = init.World.Map; // Explore map-placed actors if the "Explore Map" option is enabled - var shroudInfo = init.World.Map.Rules.Actors["player"].TraitInfo(); + var shroudInfo = init.World.Map.Rules.Actors[SystemActors.Player].TraitInfo(); var exploredMap = init.World.LobbyInfo.GlobalSettings.OptionOrDefault("explored", shroudInfo.ExploredMapCheckboxEnabled); startsRevealed = exploredMap && init.Contains() && !init.Contains(); var buildingInfo = init.Self.Info.TraitInfoOrDefault(); diff --git a/OpenRA.Mods.Common/Traits/PaletteEffects/FlashPaletteEffect.cs b/OpenRA.Mods.Common/Traits/PaletteEffects/FlashPaletteEffect.cs index 7ddf17ca65..add5fe807f 100644 --- a/OpenRA.Mods.Common/Traits/PaletteEffects/FlashPaletteEffect.cs +++ b/OpenRA.Mods.Common/Traits/PaletteEffects/FlashPaletteEffect.cs @@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits { using GUtil = OpenRA.Graphics.Util; + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Used for bursted one-colored whole screen effects. Add this to the world actor.")] public class FlashPaletteEffectInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/PaletteEffects/MenuPaletteEffect.cs b/OpenRA.Mods.Common/Traits/PaletteEffects/MenuPaletteEffect.cs index 7323591413..d22435a80b 100644 --- a/OpenRA.Mods.Common/Traits/PaletteEffects/MenuPaletteEffect.cs +++ b/OpenRA.Mods.Common/Traits/PaletteEffects/MenuPaletteEffect.cs @@ -17,6 +17,7 @@ using OpenRA.Widgets; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Fades the world from/to black at the start/end of the game, and can (optionally) desaturate the world")] public class MenuPaletteEffectInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/PaletteEffects/RotationPaletteEffect.cs b/OpenRA.Mods.Common/Traits/PaletteEffects/RotationPaletteEffect.cs index 9776ff7955..1c5d799331 100644 --- a/OpenRA.Mods.Common/Traits/PaletteEffects/RotationPaletteEffect.cs +++ b/OpenRA.Mods.Common/Traits/PaletteEffects/RotationPaletteEffect.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Palette effect used for sprinkle \"animations\".")] class RotationPaletteEffectInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs b/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs index 094f69a482..d2ca5a743e 100644 --- a/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs +++ b/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs @@ -13,6 +13,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor to allow building repair by team mates.")] class AllyRepairInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs b/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs index efd64debe5..7c9658846b 100644 --- a/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs +++ b/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Plays an audio notification and shows a radar ping when a building is attacked.", "Attach this to the player actor.")] public class BaseAttackNotifierInfo : TraitInfo diff --git a/OpenRA.Mods.Common/Traits/Player/ClassicParallelProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ClassicParallelProductionQueue.cs index 3dd1eff09a..cab683a0dd 100644 --- a/OpenRA.Mods.Common/Traits/Player/ClassicParallelProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ClassicParallelProductionQueue.cs @@ -21,6 +21,7 @@ namespace OpenRA.Mods.Common.Traits "Will only work together with the Production: trait on the actor that actually does the production.", "You will also want to add PrimaryBuildings: to let the user choose where new units should exit.", "The production speed depends on the number of production buildings and units queued at the same time.")] + [TraitLocation(SystemActors.Player)] public class ClassicParallelProductionQueueInfo : ProductionQueueInfo, Requires, Requires { [Desc("If you build more actors of the same type,", "the same queue will get its build time lowered for every actor produced there.")] diff --git a/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs index b8e1ebf1e3..d0f47ae5af 100644 --- a/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor (not a building!) to define a new shared build queue.", "Will only work together with the Production: trait on the actor that actually does the production.", "You will also want to add PrimaryBuildings: to let the user choose where new units should exit.")] diff --git a/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs b/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs index 88773cc94f..6411412ba7 100644 --- a/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs +++ b/OpenRA.Mods.Common/Traits/Player/ConquestVictoryConditions.cs @@ -11,11 +11,11 @@ using System.Linq; using OpenRA.Network; -using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] public class ConquestVictoryConditionsInfo : TraitInfo, Requires { [Desc("Delay for the end game notification in milliseconds.")] diff --git a/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs b/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs index ad8806f4f5..18eb25a7a9 100644 --- a/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs +++ b/OpenRA.Mods.Common/Traits/Player/DeveloperMode.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor.")] public class DeveloperModeInfo : TraitInfo, ILobbyOptions { diff --git a/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs b/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs index afd6ffb896..3392c9b153 100644 --- a/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs +++ b/OpenRA.Mods.Common/Traits/Player/EnemyWatcher.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Tracks neutral and enemy actors' visibility and notifies the player.", "Attach this to the player actor. The actors to track need the 'AnnounceOnSeen' trait.")] class EnemyWatcherInfo : TraitInfo diff --git a/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs b/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs index fdfcfe9a4e..a8670cf544 100644 --- a/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs +++ b/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs @@ -11,11 +11,11 @@ using System.Collections.Generic; using System.Linq; -using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor.")] public class GrantConditionOnPrerequisiteManagerInfo : TraitInfo, Requires { diff --git a/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs b/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs index 40d9ce6b9b..60cea97677 100644 --- a/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs +++ b/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs @@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Traits { [Desc("Plays an audio notification and shows a radar ping when a harvester is attacked.", "Attach this to the player actor.")] + [TraitLocation(SystemActors.Player)] public class HarvesterAttackNotifierInfo : TraitInfo { [Desc("Minimum duration (in seconds) between notification events.")] diff --git a/OpenRA.Mods.Common/Traits/Player/MissionObjectives.cs b/OpenRA.Mods.Common/Traits/Player/MissionObjectives.cs index 4174354ee1..ebf2ced2df 100644 --- a/OpenRA.Mods.Common/Traits/Player/MissionObjectives.cs +++ b/OpenRA.Mods.Common/Traits/Player/MissionObjectives.cs @@ -35,6 +35,7 @@ namespace OpenRA.Mods.Common.Traits } } + [TraitLocation(SystemActors.Player)] public class MissionObjectivesInfo : TraitInfo { [Desc("Set this to true if multiple cooperative players have a distinct set of " + @@ -258,6 +259,7 @@ namespace OpenRA.Mods.Common.Traits } } + [TraitLocation(SystemActors.World)] [Desc("Provides game mode progress information for players.", "Goes on WorldActor - observers don't have a player it can live on.", "Current options for PanelName are 'SKIRMISH_STATS' and 'MISSION_OBJECTIVES'.")] @@ -271,6 +273,7 @@ namespace OpenRA.Mods.Common.Traits public override object Create(ActorInitializer init) { return new ObjectivesPanel(this); } } + [TraitLocation(SystemActors.World)] public class ObjectivesPanel : IObjectivesPanel { readonly ObjectivesPanelInfo info; diff --git a/OpenRA.Mods.Common/Traits/Player/PlaceBeacon.cs b/OpenRA.Mods.Common/Traits/Player/PlaceBeacon.cs index 44f57ed710..93129d185f 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlaceBeacon.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlaceBeacon.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("A beacon that is constructed from a circle sprite that is animated once and a moving arrow sprite.")] public class PlaceBeaconInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs index 469da35e74..4f2957e93b 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs @@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits // Allows third party mods to detect whether an actor was created by PlaceBuilding. public class PlaceBuildingInit : RuntimeFlagInit { } + [TraitLocation(SystemActors.Player)] [Desc("Allows the player to execute build orders.", " Attach this to the player actor.")] public class PlaceBuildingInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/Player/PlayerExperience.cs b/OpenRA.Mods.Common/Traits/Player/PlayerExperience.cs index f441692914..c75125fab2 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlayerExperience.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlayerExperience.cs @@ -13,6 +13,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("This trait can be used to track player experience based on units killed with the `GivesExperience` trait.", "It can also be used as a point score system in scripted maps, for example.", "Attach this to the player actor.")] diff --git a/OpenRA.Mods.Common/Traits/Player/PlayerRadarTerrain.cs b/OpenRA.Mods.Common/Traits/Player/PlayerRadarTerrain.cs index bc5241af7a..6ee7e72d39 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlayerRadarTerrain.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlayerRadarTerrain.cs @@ -11,11 +11,11 @@ using System; using OpenRA.Graphics; -using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] public class PlayerRadarTerrainInfo : TraitInfo, Requires { public override object Create(ActorInitializer init) diff --git a/OpenRA.Mods.Common/Traits/Player/PlayerResources.cs b/OpenRA.Mods.Common/Traits/Player/PlayerResources.cs index 17f897cd63..593841119a 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlayerResources.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlayerResources.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player | SystemActors.EditorPlayer)] public class PlayerResourcesInfo : TraitInfo, ILobbyOptions { [Desc("Descriptive label for the starting cash option in the lobby.")] diff --git a/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs b/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs index fcb2f45a28..3511280f27 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor to collect observer stats.")] public class PlayerStatisticsInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs b/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs index c7d836a36c..b5f6630156 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] public class ProvidesTechPrerequisiteInfo : TraitInfo, ITechTreePrerequisiteInfo { [Desc("Internal id for this tech level.")] diff --git a/OpenRA.Mods.Common/Traits/Player/ResourceStorageWarning.cs b/OpenRA.Mods.Common/Traits/Player/ResourceStorageWarning.cs index 3bf385b4ab..db2d03d3b3 100644 --- a/OpenRA.Mods.Common/Traits/Player/ResourceStorageWarning.cs +++ b/OpenRA.Mods.Common/Traits/Player/ResourceStorageWarning.cs @@ -13,6 +13,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Provides the player with an audible warning when their storage is nearing full.")] public class ResourceStorageWarningInfo : TraitInfo, Requires { diff --git a/OpenRA.Mods.Common/Traits/Player/TechTree.cs b/OpenRA.Mods.Common/Traits/Player/TechTree.cs index 4be7b3bfac..48e6da860e 100644 --- a/OpenRA.Mods.Common/Traits/Player/TechTree.cs +++ b/OpenRA.Mods.Common/Traits/Player/TechTree.cs @@ -17,6 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Manages build limits and pre-requisites.", " Attach this to the player actor.")] public class TechTreeInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/Player/TimeLimitManager.cs b/OpenRA.Mods.Common/Traits/Player/TimeLimitManager.cs index e42cdfd82c..d0ea76e51f 100644 --- a/OpenRA.Mods.Common/Traits/Player/TimeLimitManager.cs +++ b/OpenRA.Mods.Common/Traits/Player/TimeLimitManager.cs @@ -17,6 +17,7 @@ using OpenRA.Widgets; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("This trait allows setting a time limit on matches. Attach this to the World actor.")] public class TimeLimitManagerInfo : TraitInfo, ILobbyOptions, IRulesetLoaded { diff --git a/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs b/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs index 505d15d1ca..fb2bb9e099 100644 --- a/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs +++ b/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor.")] public class PowerManagerInfo : TraitInfo, Requires { diff --git a/OpenRA.Mods.Common/Traits/ProductionQueueFromSelection.cs b/OpenRA.Mods.Common/Traits/ProductionQueueFromSelection.cs index c9563d485f..dad59b0a35 100644 --- a/OpenRA.Mods.Common/Traits/ProductionQueueFromSelection.cs +++ b/OpenRA.Mods.Common/Traits/ProductionQueueFromSelection.cs @@ -17,6 +17,7 @@ using OpenRA.Widgets; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] class ProductionQueueFromSelectionInfo : TraitInfo { public string ProductionTabsWidget = null; diff --git a/OpenRA.Mods.Common/Traits/ProximityCapturable.cs b/OpenRA.Mods.Common/Traits/ProximityCapturable.cs index afdb8ceb47..82aa5fd3d9 100644 --- a/OpenRA.Mods.Common/Traits/ProximityCapturable.cs +++ b/OpenRA.Mods.Common/Traits/ProximityCapturable.cs @@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits public void RulesetLoaded(Ruleset rules, ActorInfo info) { - var pci = rules.Actors["player"].TraitInfoOrDefault(); + var pci = rules.Actors[SystemActors.Player].TraitInfoOrDefault(); if (pci == null) throw new YamlException("ProximityCapturable requires the `Player` actor to have the ProximityCaptor trait."); } diff --git a/OpenRA.Mods.Common/Traits/Render/CustomTerrainDebugOverlay.cs b/OpenRA.Mods.Common/Traits/Render/CustomTerrainDebugOverlay.cs index 813df37329..7974cc80a1 100644 --- a/OpenRA.Mods.Common/Traits/Render/CustomTerrainDebugOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/CustomTerrainDebugOverlay.cs @@ -17,6 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Displays custom terrain types.")] class CustomTerrainDebugOverlayInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs b/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs index a7ebe25e01..1b659d49e6 100644 --- a/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs +++ b/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs @@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits.Render // No queues available - check for classic production queues if (queue == null) - queue = rules.Actors["player"].TraitInfos().FirstOrDefault(q => ProductionType == q.Type); + queue = rules.Actors[SystemActors.Player].TraitInfos().FirstOrDefault(q => ProductionType == q.Type); if (queue == null) throw new YamlException("Can't find a queue with ProductionType '{0}'".F(ProductionType)); diff --git a/OpenRA.Mods.Common/Traits/Render/VeteranProductionIconOverlay.cs b/OpenRA.Mods.Common/Traits/Render/VeteranProductionIconOverlay.cs index a00f68e901..df4d67c84b 100644 --- a/OpenRA.Mods.Common/Traits/Render/VeteranProductionIconOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/VeteranProductionIconOverlay.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor. When attached, enables all actors possessing the ProducibleWithLevel ", "trait to have their production queue icons render with an overlay defined in this trait. ", "The icon change occurs when ProducibleWithLevel.Prerequisites are met.")] diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs index de0f4f6b31..d01da1ef60 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Attach this to the player actor.")] public class SupportPowerManagerInfo : TraitInfo, Requires, Requires { diff --git a/OpenRA.Mods.Common/Traits/TerrainLightSource.cs b/OpenRA.Mods.Common/Traits/TerrainLightSource.cs index 90a1119ab3..e976c7da3f 100644 --- a/OpenRA.Mods.Common/Traits/TerrainLightSource.cs +++ b/OpenRA.Mods.Common/Traits/TerrainLightSource.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Traits public void RulesetLoaded(Ruleset rules, ActorInfo ai) { - if (!rules.Actors["world"].HasTraitInfo()) + if (!rules.Actors[SystemActors.World].HasTraitInfo()) throw new YamlException("TerrainLightSource can only be used with the world TerrainLighting trait."); } diff --git a/OpenRA.Mods.Common/Traits/World/ActorMap.cs b/OpenRA.Mods.Common/Traits/World/ActorMap.cs index 11b61b0863..e830ba9c90 100644 --- a/OpenRA.Mods.Common/Traits/World/ActorMap.cs +++ b/OpenRA.Mods.Common/Traits/World/ActorMap.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class ActorMapInfo : TraitInfo { [Desc("Size of partition bins (cells)")] diff --git a/OpenRA.Mods.Common/Traits/World/ActorSpawnManager.cs b/OpenRA.Mods.Common/Traits/World/ActorSpawnManager.cs index 17a00d5908..0dbb3d0e69 100644 --- a/OpenRA.Mods.Common/Traits/World/ActorSpawnManager.cs +++ b/OpenRA.Mods.Common/Traits/World/ActorSpawnManager.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Controls the spawning of specified actor types. Attach this to the world actor.")] + [TraitLocation(SystemActors.World)] public class ActorSpawnManagerInfo : ConditionalTraitInfo, Requires { [Desc("Minimum number of actors.")] diff --git a/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs b/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs index 2c754afe38..2405d6ba93 100644 --- a/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs +++ b/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] public class CrateSpawnerInfo : TraitInfo, ILobbyOptions { [Desc("Descriptive label for the crates checkbox in the lobby.")] diff --git a/OpenRA.Mods.Common/Traits/World/CreateMapPlayers.cs b/OpenRA.Mods.Common/Traits/World/CreateMapPlayers.cs index c6d4e1304d..b337940aa6 100644 --- a/OpenRA.Mods.Common/Traits/World/CreateMapPlayers.cs +++ b/OpenRA.Mods.Common/Traits/World/CreateMapPlayers.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Attach this to the world actor.")] public class CreateMapPlayersInfo : TraitInfo, ICreatePlayersInfo { @@ -27,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits /// void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List players, MersenneTwister playerRandom) { - var worldInfo = map.Rules.Actors["world"]; + var worldInfo = map.Rules.Actors[SystemActors.World]; var factions = worldInfo.TraitInfos().ToArray(); var assignSpawnLocations = worldInfo.TraitInfoOrDefault(); var spawnState = assignSpawnLocations?.InitializeState(map, lobbyInfo); @@ -41,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits } // Create the regular playable players. - var bots = map.Rules.Actors["player"].TraitInfos().ToArray(); + var bots = map.Rules.Actors[SystemActors.Player].TraitInfos().ToArray(); foreach (var kv in lobbyInfo.Slots) { diff --git a/OpenRA.Mods.Common/Traits/World/DomainIndex.cs b/OpenRA.Mods.Common/Traits/World/DomainIndex.cs index 35c07ca98f..7c72697c42 100644 --- a/OpenRA.Mods.Common/Traits/World/DomainIndex.cs +++ b/OpenRA.Mods.Common/Traits/World/DomainIndex.cs @@ -17,6 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Identify untraversable regions of the map for faster pathfinding, especially with AI.", "This trait is required. Every mod needs it attached to the world actor.")] class DomainIndexInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Traits/World/EditorActionManager.cs b/OpenRA.Mods.Common/Traits/World/EditorActionManager.cs index 4bebd35f75..73843a0434 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorActionManager.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorActionManager.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.EditorWorld)] public class EditorActionManagerInfo : TraitInfo { } public class EditorActionManager : IWorldLoaded diff --git a/OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs index a24940090a..defe2af298 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs @@ -21,6 +21,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.EditorWorld)] [Desc("Required for the map editor to work. Attach this to the world actor.")] public class EditorActorLayerInfo : TraitInfo, ICreatePlayersInfo { diff --git a/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs index 7b7f36579d..3fd6f8720b 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs @@ -19,6 +19,7 @@ namespace OpenRA.Mods.Common.Traits { public enum EditorCursorType { None, Actor, TerrainTemplate, Resource } + [TraitLocation(SystemActors.EditorWorld)] [Desc("Required for the map editor to work. Attach this to the world actor.")] public class EditorCursorLayerInfo : TraitInfo, Requires, Requires { diff --git a/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs index b804fdd1cd..b985f6b663 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.EditorWorld)] [Desc("Required for the map editor to work. Attach this to the world actor.")] public class EditorResourceLayerInfo : TraitInfo, IResourceLayerInfo, IMapPreviewSignatureInfo { @@ -94,7 +95,7 @@ namespace OpenRA.Mods.Common.Traits if (w.Type != WorldType.Editor) return; - var playerResourcesInfo = w.Map.Rules.Actors["player"].TraitInfoOrDefault(); + var playerResourcesInfo = w.Map.Rules.Actors[SystemActors.Player].TraitInfoOrDefault(); resourceValues = playerResourcesInfo?.ResourceValues ?? new Dictionary(); foreach (var cell in Map.AllCells) diff --git a/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs index 2d5dfbefcc..816c786bd4 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.EditorWorld)] [Desc("Required for the map editor to work. Attach this to the world actor.")] public class EditorSelectionLayerInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs b/OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs index 7442b7b022..355c07153d 100644 --- a/OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs +++ b/OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] public class GameSaveViewportManagerInfo : TraitInfo { public override object Create(ActorInitializer init) { return new GameSaveViewportManager(); } diff --git a/OpenRA.Mods.Common/Traits/World/IndexedPalette.cs b/OpenRA.Mods.Common/Traits/World/IndexedPalette.cs index 29487c90d5..43ef7280fd 100644 --- a/OpenRA.Mods.Common/Traits/World/IndexedPalette.cs +++ b/OpenRA.Mods.Common/Traits/World/IndexedPalette.cs @@ -17,6 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Define a palette by swapping palette indices.")] public class IndexedPaletteInfo : TraitInfo, IRulesetLoaded { diff --git a/OpenRA.Mods.Common/Traits/World/LegacyBridgeLayer.cs b/OpenRA.Mods.Common/Traits/World/LegacyBridgeLayer.cs index 490bc1b30f..0c4203c89d 100644 --- a/OpenRA.Mods.Common/Traits/World/LegacyBridgeLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/LegacyBridgeLayer.cs @@ -19,6 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] class LegacyBridgeLayerInfo : TraitInfo { [ActorReference] diff --git a/OpenRA.Mods.Common/Traits/World/LoadWidgetAtGameStart.cs b/OpenRA.Mods.Common/Traits/World/LoadWidgetAtGameStart.cs index 1eac25e539..eb438e18cd 100644 --- a/OpenRA.Mods.Common/Traits/World/LoadWidgetAtGameStart.cs +++ b/OpenRA.Mods.Common/Traits/World/LoadWidgetAtGameStart.cs @@ -16,6 +16,7 @@ using OpenRA.Widgets; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class LoadWidgetAtGameStartInfo : TraitInfo { [Desc("The widget tree to open when a shellmap is loaded (i.e. the main menu).")] diff --git a/OpenRA.Mods.Common/Traits/World/LobbyPrerequisiteCheckbox.cs b/OpenRA.Mods.Common/Traits/World/LobbyPrerequisiteCheckbox.cs index b932624f0e..27ff90a02d 100644 --- a/OpenRA.Mods.Common/Traits/World/LobbyPrerequisiteCheckbox.cs +++ b/OpenRA.Mods.Common/Traits/World/LobbyPrerequisiteCheckbox.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.Player)] [Desc("Enables defined prerequisites at game start for all players if the checkbox is enabled.")] public class LobbyPrerequisiteCheckboxInfo : TraitInfo, ILobbyOptions, ITechTreePrerequisiteInfo { diff --git a/OpenRA.Mods.Common/Traits/World/Locomotor.cs b/OpenRA.Mods.Common/Traits/World/Locomotor.cs index db36c49a99..3036c5aa35 100644 --- a/OpenRA.Mods.Common/Traits/World/Locomotor.cs +++ b/OpenRA.Mods.Common/Traits/World/Locomotor.cs @@ -54,6 +54,7 @@ namespace OpenRA.Mods.Common.Traits public const byte ElevatedBridge = 4; } + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Used by Mobile. Attach these to the world actor. You can have multiple variants by adding @suffixes.")] public class LocomotorInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/MapBuildRadius.cs b/OpenRA.Mods.Common/Traits/World/MapBuildRadius.cs index 0352a842e8..a21b98c29f 100644 --- a/OpenRA.Mods.Common/Traits/World/MapBuildRadius.cs +++ b/OpenRA.Mods.Common/Traits/World/MapBuildRadius.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Controls the build radius checkboxes in the lobby options.")] public class MapBuildRadiusInfo : TraitInfo, ILobbyOptions { diff --git a/OpenRA.Mods.Common/Traits/World/MapCreeps.cs b/OpenRA.Mods.Common/Traits/World/MapCreeps.cs index 792339c44c..8d7d599e20 100644 --- a/OpenRA.Mods.Common/Traits/World/MapCreeps.cs +++ b/OpenRA.Mods.Common/Traits/World/MapCreeps.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Controls the 'Creeps' checkbox in the lobby options.")] + [TraitLocation(SystemActors.World)] public class MapCreepsInfo : TraitInfo, ILobbyOptions { [Desc("Descriptive label for the creeps checkbox in the lobby.")] diff --git a/OpenRA.Mods.Common/Traits/World/MapOptions.cs b/OpenRA.Mods.Common/Traits/World/MapOptions.cs index 51eb449e66..eca364b07c 100644 --- a/OpenRA.Mods.Common/Traits/World/MapOptions.cs +++ b/OpenRA.Mods.Common/Traits/World/MapOptions.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Controls the game speed, tech level, and short game lobby options.")] public class MapOptionsInfo : TraitInfo, ILobbyOptions, IRulesetLoaded { @@ -77,7 +78,7 @@ namespace OpenRA.Mods.Common.Traits yield return new LobbyBooleanOption("shortgame", ShortGameCheckboxLabel, ShortGameCheckboxDescription, ShortGameCheckboxVisible, ShortGameCheckboxDisplayOrder, ShortGameCheckboxEnabled, ShortGameCheckboxLocked); - var techLevels = rules.Actors["player"].TraitInfos() + var techLevels = rules.Actors[SystemActors.Player].TraitInfos() .ToDictionary(t => t.Id, t => t.Name); if (techLevels.Any()) diff --git a/OpenRA.Mods.Common/Traits/World/MapStartingLocations.cs b/OpenRA.Mods.Common/Traits/World/MapStartingLocations.cs index 3ba8085aa9..d5c66f3477 100644 --- a/OpenRA.Mods.Common/Traits/World/MapStartingLocations.cs +++ b/OpenRA.Mods.Common/Traits/World/MapStartingLocations.cs @@ -19,6 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Allows the map to have working spawnpoints. Also controls the 'Separate Team Spawns' checkbox in the lobby options.")] public class MapStartingLocationsInfo : TraitInfo, ILobbyOptions, IAssignSpawnPointsInfo { diff --git a/OpenRA.Mods.Common/Traits/World/MapStartingUnits.cs b/OpenRA.Mods.Common/Traits/World/MapStartingUnits.cs index 7297acc143..c4353fd5b6 100644 --- a/OpenRA.Mods.Common/Traits/World/MapStartingUnits.cs +++ b/OpenRA.Mods.Common/Traits/World/MapStartingUnits.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Used by SpawnStartingUnits. Attach these to the world actor. You can have multiple variants by adding @suffixes.")] public class StartingUnitsInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/MusicPlaylist.cs b/OpenRA.Mods.Common/Traits/World/MusicPlaylist.cs index 658a863297..5777789629 100644 --- a/OpenRA.Mods.Common/Traits/World/MusicPlaylist.cs +++ b/OpenRA.Mods.Common/Traits/World/MusicPlaylist.cs @@ -17,6 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Trait for music handling. Attach this to the world actor.")] public class MusicPlaylistInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs index 10eddbc842..4151687f9f 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Load VGA palette (.pal) registers.")] class PaletteFromFileInfo : TraitInfo, IProvidesCursorPaletteInfo { diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromGimpOrJascFile.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromGimpOrJascFile.cs index 4bb0bbc3a6..03222ca820 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromGimpOrJascFile.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromGimpOrJascFile.cs @@ -19,6 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Load a GIMP .gpl or JASC .pal palette file. Supports per-color alpha.")] class PaletteFromGimpOrJascFileInfo : TraitInfo, IProvidesCursorPaletteInfo { diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs index 8e09bf30d4..7c3a41abc0 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromPaletteWithAlpha.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Create a palette by applying alpha transparency to another palette.")] class PaletteFromPaletteWithAlphaInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs index 6db91ef6e1..36054fe6d4 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromPlayerPaletteWithAlpha.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Create player palettes by applying alpha transparency to another player palette.")] class PaletteFromPlayerPaletteWithAlphaInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromPng.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromPng.cs index b4171c5ed1..e34029bcc0 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromPng.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromPng.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Load a PNG and use its embedded palette.")] class PaletteFromPngInfo : TraitInfo, IProvidesCursorPaletteInfo { diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs index 73b713f699..85123b41b0 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromRGBA.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Creates a single color palette without any base palette file.")] class PaletteFromRGBAInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/PathFinder.cs b/OpenRA.Mods.Common/Traits/World/PathFinder.cs index b90cc5b8d7..ac4790ee4e 100644 --- a/OpenRA.Mods.Common/Traits/World/PathFinder.cs +++ b/OpenRA.Mods.Common/Traits/World/PathFinder.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Calculates routes for mobile units based on the A* search algorithm.", " Attach this to the world actor.")] public class PathFinderInfo : TraitInfo, Requires { diff --git a/OpenRA.Mods.Common/Traits/World/RadarPings.cs b/OpenRA.Mods.Common/Traits/World/RadarPings.cs index 66c5d5355f..a29311c9a3 100644 --- a/OpenRA.Mods.Common/Traits/World/RadarPings.cs +++ b/OpenRA.Mods.Common/Traits/World/RadarPings.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] public class RadarPingsInfo : TraitInfo { public readonly int FromRadius = 200; diff --git a/OpenRA.Mods.Common/Traits/World/ResourceClaimLayer.cs b/OpenRA.Mods.Common/Traits/World/ResourceClaimLayer.cs index cb1cd0387b..0545ebfe9d 100644 --- a/OpenRA.Mods.Common/Traits/World/ResourceClaimLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/ResourceClaimLayer.cs @@ -15,6 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Allows harvesters to coordinate their operations. Attach this to the world actor.")] public sealed class ResourceClaimLayerInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs b/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs index 06fc0a1077..ded908d5b2 100644 --- a/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/ResourceLayer.cs @@ -31,6 +31,7 @@ namespace OpenRA.Mods.Common.Traits } } + [TraitLocation(SystemActors.World)] [Desc("Attach this to the world actor.")] public class ResourceLayerInfo : TraitInfo, IResourceLayerInfo, Requires, IMapPreviewSignatureInfo { diff --git a/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs b/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs index ed61c038dd..02af13fe9f 100644 --- a/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs +++ b/OpenRA.Mods.Common/Traits/World/ResourceRenderer.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Visualizes the state of the `ResourceLayer`.", " Attach this to the world actor.")] public class ResourceRendererInfo : TraitInfo, Requires { diff --git a/OpenRA.Mods.Common/Traits/World/Selection.cs b/OpenRA.Mods.Common/Traits/World/Selection.cs index 29b95e886d..ed682ed358 100644 --- a/OpenRA.Mods.Common/Traits/World/Selection.cs +++ b/OpenRA.Mods.Common/Traits/World/Selection.cs @@ -22,6 +22,7 @@ namespace OpenRA.Mods.Common.Traits public override object Create(ActorInitializer init) { return new Selection(this); } } + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class Selection : ISelection, INotifyCreated, INotifyOwnerChanged, ITick, IGameSaveTraitData { public int Hash { get; private set; } diff --git a/OpenRA.Mods.Common/Traits/World/ShroudRenderer.cs b/OpenRA.Mods.Common/Traits/World/ShroudRenderer.cs index e39a6d4777..df1cc76e0c 100644 --- a/OpenRA.Mods.Common/Traits/World/ShroudRenderer.cs +++ b/OpenRA.Mods.Common/Traits/World/ShroudRenderer.cs @@ -19,6 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class ShroudRendererInfo : TraitInfo { public readonly string Sequence = "shroud"; diff --git a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs index c053a3d1c7..8d94be7a9d 100644 --- a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs @@ -25,6 +25,7 @@ namespace OpenRA.Mods.Common.Traits public int Depth; } + [TraitLocation(SystemActors.World)] [Desc("Attach this to the world actor.", "Order of the layers defines the Z sorting.")] public class SmudgeLayerInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/Traits/World/SpawnMapActors.cs b/OpenRA.Mods.Common/Traits/World/SpawnMapActors.cs index a73df3e63f..2197ceaf4f 100644 --- a/OpenRA.Mods.Common/Traits/World/SpawnMapActors.cs +++ b/OpenRA.Mods.Common/Traits/World/SpawnMapActors.cs @@ -16,6 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Spawns the initial units for each player upon game start.")] public class SpawnMapActorsInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs b/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs index e64ded166f..d01cead15b 100644 --- a/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs +++ b/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Spawn base actor at the spawnpoint and support units in an annulus around the base actor. Both are defined at MPStartUnits. Attach this to the world actor.")] public class SpawnStartingUnitsInfo : TraitInfo, Requires, ILobbyOptions { @@ -43,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits var startingUnits = new Dictionary(); // Duplicate classes are defined for different race variants - foreach (var t in rules.Actors["world"].TraitInfos()) + foreach (var t in rules.Actors[SystemActors.World].TraitInfos()) startingUnits[t.Class] = t.ClassName; if (startingUnits.Any()) @@ -75,7 +76,7 @@ namespace OpenRA.Mods.Common.Traits var spawnClass = p.PlayerReference.StartingUnitsClass ?? w.LobbyInfo.GlobalSettings .OptionOrDefault("startingunits", info.StartingUnitsClass); - var unitGroup = w.Map.Rules.Actors["world"].TraitInfos() + var unitGroup = w.Map.Rules.Actors[SystemActors.World].TraitInfos() .Where(g => g.Class == spawnClass && g.Factions != null && g.Factions.Contains(p.Faction.InternalName)) .RandomOrDefault(w.SharedRandom); diff --git a/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs b/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs index c6187b4f47..17f37326fc 100644 --- a/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs +++ b/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] class StartGameNotificationInfo : TraitInfo { [NotificationReference("Speech")] diff --git a/OpenRA.Mods.Common/Traits/World/TerrainGeometryOverlay.cs b/OpenRA.Mods.Common/Traits/World/TerrainGeometryOverlay.cs index 8610ca6377..b19fff00eb 100644 --- a/OpenRA.Mods.Common/Traits/World/TerrainGeometryOverlay.cs +++ b/OpenRA.Mods.Common/Traits/World/TerrainGeometryOverlay.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Renders a debug overlay showing the terrain cells. Attach this to the world actor.")] public class TerrainGeometryOverlayInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs b/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs index b4b655fda6..cbe279ff76 100644 --- a/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs +++ b/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs @@ -19,6 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class TerrainRendererInfo : TraitInfo, ITiledTerrainRendererInfo { bool ITiledTerrainRendererInfo.ValidateTileSprites(ITemplatedTerrainInfo terrainInfo, Action onError) diff --git a/OpenRA.Mods.Common/Traits/World/ValidateOrder.cs b/OpenRA.Mods.Common/Traits/World/ValidateOrder.cs index 0d1195c496..c7ce5a8030 100644 --- a/OpenRA.Mods.Common/Traits/World/ValidateOrder.cs +++ b/OpenRA.Mods.Common/Traits/World/ValidateOrder.cs @@ -14,6 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Used to detect exploits. Attach this to the world actor.")] public class ValidateOrderInfo : TraitInfo { } diff --git a/OpenRA.Mods.Common/Traits/World/WarheadDebugOverlay.cs b/OpenRA.Mods.Common/Traits/World/WarheadDebugOverlay.cs index 5e1e223315..b9643da4e2 100644 --- a/OpenRA.Mods.Common/Traits/World/WarheadDebugOverlay.cs +++ b/OpenRA.Mods.Common/Traits/World/WarheadDebugOverlay.cs @@ -17,6 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [TraitLocation(SystemActors.World)] [Desc("Part of the combat overlay from DeveloperMode. Attach this to the world actor.")] public class WarheadDebugOverlayInfo : TraitInfo { diff --git a/OpenRA.Mods.Common/UtilityCommands/CheckMissingSprites.cs b/OpenRA.Mods.Common/UtilityCommands/CheckMissingSprites.cs index 7a8eb251f7..f9ad97f723 100644 --- a/OpenRA.Mods.Common/UtilityCommands/CheckMissingSprites.cs +++ b/OpenRA.Mods.Common/UtilityCommands/CheckMissingSprites.cs @@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.UtilityCommands var terrainInfo = modData.DefaultTerrainInfo[kv.Key]; if (terrainInfo is ITemplatedTerrainInfo templatedTerrainInfo) - foreach (var r in modData.DefaultRules.Actors["world"].TraitInfos()) + foreach (var r in modData.DefaultRules.Actors[SystemActors.World].TraitInfos()) failed |= r.ValidateTileSprites(templatedTerrainInfo, Console.WriteLine); foreach (var image in kv.Value.Images) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoBriefingLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoBriefingLogic.cs index a856cec883..67ab63c024 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoBriefingLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoBriefingLogic.cs @@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var mapDescription = widget.Get("MAP_DESCRIPTION"); var mapFont = Game.Renderer.Fonts[mapDescription.Font]; - var missionData = world.Map.Rules.Actors["world"].TraitInfoOrDefault(); + var missionData = world.Map.Rules.Actors[SystemActors.World].TraitInfoOrDefault(); if (missionData != null) { var text = WidgetUtils.WrapText(missionData.Briefing.Replace("\\n", "\n"), mapDescription.Bounds.Width, mapFont); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs index c8e908ee36..f0e61ecfb3 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs @@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic // Can't use DeveloperMode.Enabled because there is a hardcoded hack to *always* // enable developer mode for singleplayer games, but we only want to show the button // if it has been explicitly enabled - var def = world.Map.Rules.Actors["player"].TraitInfo().CheckboxEnabled; + var def = world.Map.Rules.Actors[SystemActors.Player].TraitInfo().CheckboxEnabled; var developerEnabled = world.LobbyInfo.GlobalSettings.OptionOrDefault("cheats", def); if (lp != null && developerEnabled) { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs index ce1800ad54..88d1eb7f4d 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs @@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic // TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions if (world.Type == WorldType.Regular) { - var moi = world.Map.Rules.Actors["player"].TraitInfoOrDefault(); + var moi = world.Map.Rules.Actors[SystemActors.Player].TraitInfoOrDefault(); if (moi != null) { var faction = world.LocalPlayer?.Faction.InternalName; diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs index 57ab772a0c..0b8b733036 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs @@ -73,7 +73,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic // Can't use DeveloperMode.Enabled because there is a hardcoded hack to *always* // enable developer mode for singleplayer games, but we only want to show the button // if it has been explicitly enabled - var def = world.Map.Rules.Actors["player"].TraitInfo().CheckboxEnabled; + var def = world.Map.Rules.Actors[SystemActors.Player].TraitInfo().CheckboxEnabled; var enabled = world.LobbyInfo.GlobalSettings.OptionOrDefault("cheats", def); debug.IsVisible = () => enabled; debug.IsDisabled = () => disableSystemButtons; diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index 7b16da3bbb..5282fa43b4 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -158,7 +158,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic colorPreview = lobby.Get("COLOR_MANAGER"); colorPreview.Color = Game.Settings.Player.Color; - foreach (var f in modRules.Actors["world"].TraitInfos()) + foreach (var f in modRules.Actors[SystemActors.World].TraitInfos()) factions.Add(f.InternalName, new LobbyFaction { Selectable = f.Selectable, Name = f.Name, Side = f.Side, Description = f.Description }); var gameStarting = false; @@ -207,7 +207,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic slotsButton.OnMouseDown = _ => { - var botTypes = map.Rules.Actors["player"].TraitInfos().Select(t => t.Type); + var botTypes = map.Rules.Actors[SystemActors.Player].TraitInfos().Select(t => t.Type); var options = new Dictionary>(); var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin); @@ -539,7 +539,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (addBotOnMapLoad) { var slot = orderManager.LobbyInfo.FirstEmptyBotSlot(); - var bot = currentMap.Rules.Actors["player"].TraitInfos().Select(t => t.Type).FirstOrDefault(); + var bot = currentMap.Rules.Actors[SystemActors.Player].TraitInfos().Select(t => t.Type).FirstOrDefault(); var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin); if (slot != null && bot != null) orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot))); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs index cdd85b8556..96c4a28fec 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs @@ -78,8 +78,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic optionsContainer.RemoveChildren(); optionsContainer.Bounds.Height = 0; - var allOptions = mapPreview.Rules.Actors["player"].TraitInfos() - .Concat(mapPreview.Rules.Actors["world"].TraitInfos()) + var allOptions = mapPreview.Rules.Actors[SystemActors.Player].TraitInfos() + .Concat(mapPreview.Rules.Actors[SystemActors.World].TraitInfos()) .SelectMany(t => t.LobbyOptions(mapPreview.Rules)) .Where(o => o.IsVisible) .OrderBy(o => o.DisplayOrder) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs index b87d742de7..719c17a091 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs @@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var bots = new List(); if (slot.AllowBots) { - foreach (var b in map.Rules.Actors["player"].TraitInfos()) + foreach (var b in map.Rules.Actors[SystemActors.Player].TraitInfos()) { var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin); bots.Add(new SlotDropDownOption(b.Name, diff --git a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs index e4de8f6240..2b4d99ac7c 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs @@ -219,7 +219,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic new Thread(() => { - var mapDifficulty = preview.Rules.Actors["world"].TraitInfos() + var mapDifficulty = preview.Rules.Actors[SystemActors.World].TraitInfos() .FirstOrDefault(sld => sld.ID == "difficulty"); if (mapDifficulty != null) @@ -229,7 +229,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic difficultyDisabled = mapDifficulty.Locked; } - var missionData = preview.Rules.Actors["world"].TraitInfoOrDefault(); + var missionData = preview.Rules.Actors[SystemActors.World].TraitInfoOrDefault(); if (missionData != null) { briefingVideo = missionData.BriefingVideo; @@ -383,7 +383,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic orders.Add(Order.Command("option gamespeed {0}".F(gameSpeed))); orders.Add(Order.Command("state {0}".F(Session.ClientState.Ready))); - var missionData = selectedMap.Rules.Actors["world"].TraitInfoOrDefault(); + var missionData = selectedMap.Rules.Actors[SystemActors.World].TraitInfoOrDefault(); if (missionData != null && missionData.StartVideo != null && modData.DefaultFileSystem.Exists(missionData.StartVideo)) { var fsPlayer = fullscreenVideoPlayer.Get("PLAYER"); diff --git a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs index 3f54faf2cd..c457dd2043 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs @@ -671,7 +671,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var flag = item.Get("FLAG"); flag.GetImageCollection = () => "flags"; - var factionInfo = modData.DefaultRules.Actors["world"].TraitInfos(); + var factionInfo = modData.DefaultRules.Actors[SystemActors.World].TraitInfos(); flag.GetImageName = () => (factionInfo != null && factionInfo.Any(f => f.InternalName == o.FactionId)) ? o.FactionId : "Random"; playerList.AddChild(item); diff --git a/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs index 10a0fe92ff..85b8b3a8a1 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs @@ -473,7 +473,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (server.Clients.Any(c => c.IsSpectator)) teams.Add("Spectators", server.Clients.Where(c => c.IsSpectator)); - var factionInfo = modData.DefaultRules.Actors["world"].TraitInfos(); + var factionInfo = modData.DefaultRules.Actors[SystemActors.World].TraitInfos(); foreach (var kv in teams) { var group = kv.Key; diff --git a/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs b/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs index 621bca4cbd..b361bc56b9 100644 --- a/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs +++ b/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits { [Desc("Attach this to the world actor. Required for LaysTerrain to work.")] + [TraitLocation(SystemActors.World)] public class BuildableTerrainLayerInfo : TraitInfo, Requires { [Desc("Palette to render the layer sprites in.")] diff --git a/OpenRA.Mods.D2k/Traits/World/D2kResourceRenderer.cs b/OpenRA.Mods.D2k/Traits/World/D2kResourceRenderer.cs index 979e52da95..464ba13d9d 100644 --- a/OpenRA.Mods.D2k/Traits/World/D2kResourceRenderer.cs +++ b/OpenRA.Mods.D2k/Traits/World/D2kResourceRenderer.cs @@ -14,10 +14,12 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.Traits; +using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits { [Desc("Used to render spice with round borders.", "Attach this to the world actor")] + [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] public class D2kResourceRendererInfo : ResourceRendererInfo { public override object Create(ActorInitializer init) { return new D2kResourceRenderer(init.Self, this); }