Add a lint check for trait placement on hardcoded actor names.

This commit is contained in:
Matthias Mailänder
2021-04-11 14:30:00 +01:00
committed by reaperrr
parent 0d3c624bbc
commit 5a0bcc01a6
129 changed files with 266 additions and 67 deletions

View File

@@ -24,6 +24,15 @@ using OpenRA.Traits;
namespace OpenRA namespace OpenRA
{ {
[Flags]
public enum SystemActors
{
Player = 0,
EditorPlayer = 1,
World = 2,
EditorWorld = 4
}
public sealed class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable<Actor>, IDisposable public sealed class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable<Actor>, IDisposable
{ {
internal readonly struct SyncHash internal readonly struct SyncHash

View File

@@ -22,7 +22,7 @@ namespace OpenRA
{ {
public class Ruleset public class Ruleset
{ {
public readonly IReadOnlyDictionary<string, ActorInfo> Actors; public readonly ActorInfoDictionary Actors;
public readonly IReadOnlyDictionary<string, WeaponInfo> Weapons; public readonly IReadOnlyDictionary<string, WeaponInfo> Weapons;
public readonly IReadOnlyDictionary<string, SoundInfo> Voices; public readonly IReadOnlyDictionary<string, SoundInfo> Voices;
public readonly IReadOnlyDictionary<string, SoundInfo> Notifications; public readonly IReadOnlyDictionary<string, SoundInfo> Notifications;
@@ -41,7 +41,7 @@ namespace OpenRA
SequenceProvider sequences, SequenceProvider sequences,
IReadOnlyDictionary<string, MiniYamlNode> modelSequences) IReadOnlyDictionary<string, MiniYamlNode> modelSequences)
{ {
Actors = actors; Actors = new ActorInfoDictionary(actors);
Weapons = weapons; Weapons = weapons;
Voices = voices; Voices = voices;
Notifications = notifications; Notifications = notifications;

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Graphics
// Overwrite previous definitions if there are duplicates // Overwrite previous definitions if there are duplicates
var pals = new Dictionary<string, IProvidesCursorPaletteInfo>(); var pals = new Dictionary<string, IProvidesCursorPaletteInfo>();
foreach (var p in modData.DefaultRules.Actors["world"].TraitInfos<IProvidesCursorPaletteInfo>()) foreach (var p in modData.DefaultRules.Actors[SystemActors.World].TraitInfos<IProvidesCursorPaletteInfo>())
if (p.Palette != null) if (p.Palette != null)
pals[p.Palette] = p; pals[p.Palette] = p;

View File

@@ -708,7 +708,7 @@ namespace OpenRA
} }
// ResourceLayer is on world actor, which isn't caught above, so an extra check for it. // 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<IMapPreviewSignatureInfo>(); var worldimpsis = worldActorInfo.TraitInfos<IMapPreviewSignatureInfo>();
foreach (var worldimpsi in worldimpsis) foreach (var worldimpsi in worldimpsis)
worldimpsi.PopulateMapPreviewSignatureCells(this, worldActorInfo, null, positions); worldimpsi.PopulateMapPreviewSignatureCells(this, worldActorInfo, null, positions);

View File

@@ -30,7 +30,7 @@ namespace OpenRA
public MapPlayers(Ruleset rules, int playerCount) public MapPlayers(Ruleset rules, int playerCount)
{ {
var firstFaction = rules.Actors["world"].TraitInfos<FactionInfo>() var firstFaction = rules.Actors[SystemActors.World].TraitInfos<FactionInfo>()
.First(f => f.Selectable).InternalName; .First(f => f.Selectable).InternalName;
Players = new Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>

View File

@@ -37,9 +37,6 @@ namespace OpenRA
public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
{ {
public const string PlayerActorType = "Player";
public const string EditorPlayerActorType = "EditorPlayer";
struct StanceColors struct StanceColors
{ {
public Color Self; public Color Self;
@@ -129,13 +126,13 @@ namespace OpenRA
static FactionInfo ResolveFaction(World world, string factionName, MersenneTwister playerRandom, bool requireSelectable) static FactionInfo ResolveFaction(World world, string factionName, MersenneTwister playerRandom, bool requireSelectable)
{ {
var factionInfos = world.Map.Rules.Actors["world"].TraitInfos<FactionInfo>(); var factionInfos = world.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>();
return ResolveFaction(factionName, factionInfos, playerRandom, requireSelectable); return ResolveFaction(factionName, factionInfos, playerRandom, requireSelectable);
} }
static FactionInfo ResolveDisplayFaction(World world, string factionName) static FactionInfo ResolveDisplayFaction(World world, string factionName)
{ {
var factions = world.Map.Rules.Actors["world"].TraitInfos<FactionInfo>().ToArray(); var factions = world.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>().ToArray();
return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First(); return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First();
} }
@@ -165,7 +162,7 @@ namespace OpenRA
{ {
ClientIndex = client.Index; ClientIndex = client.Index;
Color = client.Color; Color = client.Color;
PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors["player"].TraitInfos<IBotInfo>()); PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>());
BotType = client.Bot; BotType = client.Bot;
Faction = ResolveFaction(world, client.Faction, playerRandom, !pr.LockFaction); Faction = ResolveFaction(world, client.Faction, playerRandom, !pr.LockFaction);
@@ -206,8 +203,8 @@ namespace OpenRA
// querying player traits in INotifyCreated.Created would crash. // querying player traits in INotifyCreated.Created would crash.
// Therefore assign the uninitialized actor and run the Created callbacks // Therefore assign the uninitialized actor and run the Created callbacks
// by calling Initialize ourselves. // by calling Initialize ourselves.
var playerActorType = world.Type == WorldType.Editor ? EditorPlayerActorType : PlayerActorType; var playerActorType = world.Type == WorldType.Editor ? SystemActors.EditorPlayer : SystemActors.Player;
PlayerActor = new Actor(world, playerActorType, new TypeDictionary { new OwnerInit(this) }); PlayerActor = new Actor(world, playerActorType.ToString(), new TypeDictionary { new OwnerInit(this) });
PlayerActor.Initialize(true); PlayerActor.Initialize(true);
Shroud = PlayerActor.Trait<Shroud>(); Shroud = PlayerActor.Trait<Shroud>();

View File

@@ -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<string, ActorInfo>
{
readonly Dictionary<string, ActorInfo> dict;
public ActorInfoDictionary(IReadOnlyDictionary<string, ActorInfo> dict)
{
if (dict == null)
throw new ArgumentNullException(nameof(dict));
this.dict = new Dictionary<string, ActorInfo>(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<string> IReadOnlyDictionary<string, ActorInfo>.Keys => dict.Keys;
IEnumerable<ActorInfo> IReadOnlyDictionary<string, ActorInfo>.Values => dict.Values;
public ICollection<string> Keys => dict.Keys;
public ICollection<ActorInfo> Values => dict.Values;
public IEnumerator<KeyValuePair<string, ActorInfo>> GetEnumerator() => dict.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => dict.GetEnumerator();
}
}

View File

@@ -159,7 +159,7 @@ namespace OpenRA.Scripting
var knownPlayerCommands = Game.ModData.ObjectCreator var knownPlayerCommands = Game.ModData.ObjectCreator
.GetTypesImplementing<ScriptPlayerProperties>() .GetTypesImplementing<ScriptPlayerProperties>()
.ToArray(); .ToArray();
PlayerCommands = FilterCommands(world.Map.Rules.Actors["player"], knownPlayerCommands); PlayerCommands = FilterCommands(world.Map.Rules.Actors[SystemActors.Player], knownPlayerCommands);
runtime.Globals["EngineDir"] = Platform.EngineDir; runtime.Globals["EngineDir"] = Platform.EngineDir;
runtime.DoBuffer(File.Open(Path.Combine(Platform.EngineDir, "lua", "scriptwrapper.lua"), FileMode.Open, FileAccess.Read).ReadAllText(), "scriptwrapper.lua").Dispose(); runtime.DoBuffer(File.Open(Path.Combine(Platform.EngineDir, "lua", "scriptwrapper.lua"), FileMode.Open, FileAccess.Read).ReadAllText(), "scriptwrapper.lua").Dispose();

View File

@@ -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 // 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 // This will need to change if future code wants to use worldPlayers for other purposes
var playerRandom = new MersenneTwister(LobbyInfo.GlobalSettings.RandomSeed); var playerRandom = new MersenneTwister(LobbyInfo.GlobalSettings.RandomSeed);
foreach (var cmpi in Map.Rules.Actors["world"].TraitInfos<ICreatePlayersInfo>()) foreach (var cmpi in Map.Rules.Actors[SystemActors.World].TraitInfos<ICreatePlayersInfo>())
cmpi.CreateServerPlayers(Map, LobbyInfo, worldPlayers, playerRandom); cmpi.CreateServerPlayers(Map, LobbyInfo, worldPlayers, playerRandom);
if (recorder != null) if (recorder != null)

View File

@@ -403,7 +403,7 @@ namespace OpenRA
public static string SanitizedPlayerName(string dirty) public static string SanitizedPlayerName(string dirty)
{ {
var forbiddenNames = new string[] { "Open", "Closed" }; var forbiddenNames = new string[] { "Open", "Closed" };
var botNames = OpenRA.Game.ModData.DefaultRules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name); var botNames = OpenRA.Game.ModData.DefaultRules.Actors[SystemActors.Player].TraitInfos<IBotInfo>().Select(t => t.Name);
var clean = SanitizedName(dirty); var clean = SanitizedName(dirty);

View File

@@ -11,6 +11,7 @@
namespace OpenRA.Traits namespace OpenRA.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("Checks for pause related desyncs. Attach this to the world actor.")] [Desc("Checks for pause related desyncs. Attach this to the world actor.")]
public class DebugPauseStateInfo : TraitInfo public class DebugPauseStateInfo : TraitInfo
{ {

View File

@@ -105,4 +105,14 @@ namespace OpenRA.Traits
PlayerPaletteReferenceSwitch = playerPaletteReferenceSwitch; PlayerPaletteReferenceSwitch = playerPaletteReferenceSwitch;
} }
} }
[AttributeUsage(AttributeTargets.Class)]
public sealed class TraitLocationAttribute : Attribute
{
public readonly SystemActors SystemActors;
public TraitLocationAttribute(SystemActors systemActors)
{
SystemActors = systemActors;
}
}
} }

View File

@@ -22,6 +22,7 @@ namespace OpenRA.Traits
void OnVisibilityChanged(FrozenActor frozen); void OnVisibilityChanged(FrozenActor frozen);
} }
[TraitLocation(SystemActors.Player)]
[Desc("Required for FrozenUnderFog to work. Attach this to the player actor.")] [Desc("Required for FrozenUnderFog to work. Attach this to the player actor.")]
public class FrozenActorLayerInfo : TraitInfo, Requires<ShroudInfo> public class FrozenActorLayerInfo : TraitInfo, Requires<ShroudInfo>
{ {

View File

@@ -14,7 +14,8 @@ using OpenRA.Primitives;
namespace OpenRA.Traits 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 public class PlayerColorPaletteInfo : TraitInfo
{ {
[PaletteReference] [PaletteReference]

View File

@@ -14,6 +14,7 @@ using System.Collections.Generic;
namespace OpenRA.Traits namespace OpenRA.Traits
{ {
[TraitLocation(SystemActors.Player | SystemActors.EditorPlayer)]
[Desc("Required for shroud and fog visibility checks. Add this to the player actor.")] [Desc("Required for shroud and fog visibility checks. Add this to the player actor.")]
public class ShroudInfo : TraitInfo, ILobbyOptions public class ShroudInfo : TraitInfo, ILobbyOptions
{ {

View File

@@ -11,6 +11,7 @@
namespace OpenRA.Traits namespace OpenRA.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Enables visualization commands. Attach this to the world actor.")] [Desc("Enables visualization commands. Attach this to the world actor.")]
public class DebugVisualizationsInfo : TraitInfo<DebugVisualizations> { } public class DebugVisualizationsInfo : TraitInfo<DebugVisualizations> { }

View File

@@ -14,6 +14,7 @@ using System.Collections.Generic;
namespace OpenRA.Traits namespace OpenRA.Traits
{ {
[Desc("Attach this to the `World` actor.")] [Desc("Attach this to the `World` actor.")]
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class FactionInfo : TraitInfo<Faction> public class FactionInfo : TraitInfo<Faction>
{ {
[Desc("This is the name exposed to the players.")] [Desc("This is the name exposed to the players.")]

View File

@@ -30,6 +30,7 @@ namespace OpenRA.Traits
public override string ToString() { return "{0}->{1}".F(Actor.Info.Name, Bounds.GetType().Name); } public override string ToString() { return "{0}->{1}".F(Actor.Info.Name, Bounds.GetType().Name); }
} }
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class ScreenMapInfo : TraitInfo public class ScreenMapInfo : TraitInfo
{ {
[Desc("Size of partition bins (world pixels)")] [Desc("Size of partition bins (world pixels)")]

View File

@@ -16,6 +16,7 @@ using OpenRA.Graphics;
namespace OpenRA.Traits namespace OpenRA.Traits
{ {
[TraitLocation(SystemActors.World)]
public class ScreenShakerInfo : TraitInfo public class ScreenShakerInfo : TraitInfo
{ {
public readonly float2 MinMultiplier = new float2(-3, -3); public readonly float2 MinMultiplier = new float2(-3, -3);

View File

@@ -202,8 +202,8 @@ namespace OpenRA
ModelCache = modData.ModelSequenceLoader.CacheModels(map, modData, map.Rules.ModelSequences); ModelCache = modData.ModelSequenceLoader.CacheModels(map, modData, map.Rules.ModelSequences);
var worldActorType = type == WorldType.Editor ? "EditorWorld" : "World"; var worldActorType = type == WorldType.Editor ? SystemActors.EditorWorld : SystemActors.World;
WorldActor = CreateActor(worldActorType, new TypeDictionary()); WorldActor = CreateActor(worldActorType.ToString(), new TypeDictionary());
ActorMap = WorldActor.Trait<IActorMap>(); ActorMap = WorldActor.Trait<IActorMap>();
ScreenMap = WorldActor.Trait<ScreenMap>(); ScreenMap = WorldActor.Trait<ScreenMap>();
Selection = WorldActor.Trait<ISelection>(); Selection = WorldActor.Trait<ISelection>();

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits namespace OpenRA.Mods.Cnc.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Required for `GpsPower`. Attach this to the player actor.")] [Desc("Required for `GpsPower`. Attach this to the player actor.")]
class GpsWatcherInfo : TraitInfo class GpsWatcherInfo : TraitInfo
{ {

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.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.")] [Desc("Apply palette full screen rotations during chronoshifts. Add this to the world actor.")]
public class ChronoshiftPaletteEffectInfo : TraitInfo public class ChronoshiftPaletteEffectInfo : TraitInfo
{ {

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits namespace OpenRA.Mods.Cnc.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Palette effect used for blinking \"animations\" on actors.")] [Desc("Palette effect used for blinking \"animations\" on actors.")]
class LightPaletteRotatorInfo : TraitInfo class LightPaletteRotatorInfo : TraitInfo
{ {

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits namespace OpenRA.Mods.Cnc.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Adds the hard-coded shroud palette to the game")] [Desc("Adds the hard-coded shroud palette to the game")]
class ShroudPaletteInfo : TraitInfo class ShroudPaletteInfo : TraitInfo
{ {

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits namespace OpenRA.Mods.Cnc.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Adds the hard-coded shroud palette to the game")] [Desc("Adds the hard-coded shroud palette to the game")]
class TSShroudPaletteInfo : TraitInfo class TSShroudPaletteInfo : TraitInfo
{ {

View File

@@ -42,13 +42,13 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
var srcModData = new ModData(utility.Mods[srcMod], utility.Mods); var srcModData = new ModData(utility.Mods[srcMod], utility.Mods);
Game.ModData = srcModData; Game.ModData = srcModData;
var srcPaletteInfo = srcModData.DefaultRules.Actors["player"].TraitInfo<PlayerColorPaletteInfo>(); var srcPaletteInfo = srcModData.DefaultRules.Actors[SystemActors.Player].TraitInfo<PlayerColorPaletteInfo>();
var srcRemapIndex = srcPaletteInfo.RemapIndex; var srcRemapIndex = srcPaletteInfo.RemapIndex;
var destMod = args[2].Split(':')[0]; var destMod = args[2].Split(':')[0];
var destModData = new ModData(utility.Mods[destMod], utility.Mods); var destModData = new ModData(utility.Mods[destMod], utility.Mods);
Game.ModData = destModData; Game.ModData = destModData;
var destPaletteInfo = destModData.DefaultRules.Actors["player"].TraitInfo<PlayerColorPaletteInfo>(); var destPaletteInfo = destModData.DefaultRules.Actors[SystemActors.Player].TraitInfo<PlayerColorPaletteInfo>();
var destRemapIndex = destPaletteInfo.RemapIndex; var destRemapIndex = destPaletteInfo.RemapIndex;
var shadowIndex = new int[] { }; var shadowIndex = new int[] { };

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands namespace OpenRA.Mods.Common.Commands
{ {
[TraitLocation(SystemActors.World)]
[Desc("Enables commands triggered by typing them into the chatbox. Attach this to the world actor.")] [Desc("Enables commands triggered by typing them into the chatbox. Attach this to the world actor.")]
public class ChatCommandsInfo : TraitInfo<ChatCommands> { } public class ChatCommandsInfo : TraitInfo<ChatCommands> { }

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands namespace OpenRA.Mods.Common.Commands
{ {
[TraitLocation(SystemActors.World)]
[Desc("Enables visualization commands via the chatbox. Attach this to the world actor.")] [Desc("Enables visualization commands via the chatbox. Attach this to the world actor.")]
public class DebugVisualizationCommandsInfo : TraitInfo<DebugVisualizationCommands> { } public class DebugVisualizationCommandsInfo : TraitInfo<DebugVisualizationCommands> { }

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands namespace OpenRA.Mods.Common.Commands
{ {
[TraitLocation(SystemActors.World)]
[Desc("Enables developer cheats via the chatbox. Attach this to the world actor.")] [Desc("Enables developer cheats via the chatbox. Attach this to the world actor.")]
public class DevCommandsInfo : TraitInfo<DevCommands> { } public class DevCommandsInfo : TraitInfo<DevCommands> { }

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands namespace OpenRA.Mods.Common.Commands
{ {
[TraitLocation(SystemActors.World)]
[Desc("Shows a list of available commands in the chatbox. Attach this to the world actor.")] [Desc("Shows a list of available commands in the chatbox. Attach this to the world actor.")]
public class HelpCommandInfo : TraitInfo<HelpCommand> { } public class HelpCommandInfo : TraitInfo<HelpCommand> { }

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands 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.")] [Desc("Allows the player to pause or surrender the game via the chatbox. Attach this to the world actor.")]
public class PlayerCommandsInfo : TraitInfo<PlayerCommands> { } public class PlayerCommandsInfo : TraitInfo<PlayerCommands> { }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Lint
{ {
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules) public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
{ {
var worldActor = rules.Actors["world"]; var worldActor = rules.Actors[SystemActors.World];
var locomotorInfos = worldActor.TraitInfos<LocomotorInfo>().ToArray(); var locomotorInfos = worldActor.TraitInfos<LocomotorInfo>().ToArray();
foreach (var li in locomotorInfos) foreach (var li in locomotorInfos)
foreach (var otherLocomotor in locomotorInfos) foreach (var otherLocomotor in locomotorInfos)

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Lint
if (!worldOwnerFound) if (!worldOwnerFound)
emitError("Found no player owning the world."); emitError("Found no player owning the world.");
var worldActor = map.Rules.Actors["world"]; var worldActor = map.Rules.Actors[SystemActors.World];
var factions = worldActor.TraitInfos<FactionInfo>().Select(f => f.InternalName).ToHashSet(); var factions = worldActor.TraitInfos<FactionInfo>().Select(f => f.InternalName).ToHashSet();
foreach (var player in players.Values) foreach (var player in players.Values)
if (!string.IsNullOrWhiteSpace(player.Faction) && !factions.Contains(player.Faction)) if (!string.IsNullOrWhiteSpace(player.Faction) && !factions.Contains(player.Faction))

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Lint
void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules, SequenceProvider sequences) void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules, SequenceProvider sequences)
{ {
var factions = rules.Actors["world"].TraitInfos<FactionInfo>().Select(f => f.InternalName).ToArray(); var factions = rules.Actors[SystemActors.World].TraitInfos<FactionInfo>().Select(f => f.InternalName).ToArray();
foreach (var actorInfo in rules.Actors) foreach (var actorInfo in rules.Actors)
{ {
// Actors may have 0 or 1 RenderSprites traits // Actors may have 0 or 1 RenderSprites traits

View File

@@ -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<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
{
foreach (var actorInfo in rules.Actors)
{
foreach (var traitInfo in actorInfo.Value.TraitInfos<TraitInfo>())
{
var traitLocation = traitInfo.GetType().GetCustomAttributes<TraitLocationAttribute>(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));
}
}
}
}
}
}

View File

@@ -357,7 +357,7 @@ namespace OpenRA.Mods.Common.Server
} }
var botType = parts[2]; var botType = parts[2];
var botInfo = server.Map.Rules.Actors["player"].TraitInfos<IBotInfo>() var botInfo = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>()
.FirstOrDefault(b => b.Type == botType); .FirstOrDefault(b => b.Type == botType);
if (botInfo == null) if (botInfo == null)
@@ -440,7 +440,7 @@ namespace OpenRA.Mods.Common.Server
LoadMapSettings(server, server.LobbyInfo.GlobalSettings, server.Map.Rules); LoadMapSettings(server, server.LobbyInfo.GlobalSettings, server.Map.Rules);
// Reset client states // Reset client states
var selectableFactions = server.Map.Rules.Actors["world"].TraitInfos<FactionInfo>() var selectableFactions = server.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>()
.Where(f => f.Selectable) .Where(f => f.Selectable)
.Select(f => f.InternalName) .Select(f => f.InternalName)
.ToList(); .ToList();
@@ -457,7 +457,7 @@ namespace OpenRA.Mods.Common.Server
// - Players who now lack a slot are made observers // - Players who now lack a slot are made observers
// - Bots who now lack a slot are dropped // - Bots who now lack a slot are dropped
// - Bots who are not defined in the map rules are dropped // - Bots who are not defined in the map rules are dropped
var botTypes = server.Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Type); var botTypes = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>().Select(t => t.Type);
var slots = server.LobbyInfo.Slots.Keys.ToArray(); var slots = server.LobbyInfo.Slots.Keys.ToArray();
var i = 0; var i = 0;
foreach (var os in oldSlots) foreach (var os in oldSlots)
@@ -534,8 +534,8 @@ namespace OpenRA.Mods.Common.Server
return true; return true;
} }
var allOptions = server.Map.Rules.Actors["player"].TraitInfos<ILobbyOptions>() var allOptions = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<ILobbyOptions>()
.Concat(server.Map.Rules.Actors["world"].TraitInfos<ILobbyOptions>()) .Concat(server.Map.Rules.Actors[SystemActors.World].TraitInfos<ILobbyOptions>())
.SelectMany(t => t.LobbyOptions(server.Map.Rules)); .SelectMany(t => t.LobbyOptions(server.Map.Rules));
// Overwrite keys with duplicate ids // Overwrite keys with duplicate ids
@@ -775,7 +775,7 @@ namespace OpenRA.Mods.Common.Server
if (server.LobbyInfo.Slots[targetClient.Slot].LockFaction) if (server.LobbyInfo.Slots[targetClient.Slot].LockFaction)
return true; return true;
var factions = server.Map.Rules.Actors["world"].TraitInfos<FactionInfo>() var factions = server.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>()
.Where(f => f.Selectable).Select(f => f.InternalName); .Where(f => f.Selectable).Select(f => f.InternalName);
if (!factions.Contains(parts[1])) if (!factions.Contains(parts[1]))
@@ -1045,8 +1045,8 @@ namespace OpenRA.Mods.Common.Server
{ {
lock (server.LobbyInfo) lock (server.LobbyInfo)
{ {
var options = rules.Actors["player"].TraitInfos<ILobbyOptions>() var options = rules.Actors[SystemActors.Player].TraitInfos<ILobbyOptions>()
.Concat(rules.Actors["world"].TraitInfos<ILobbyOptions>()) .Concat(rules.Actors[SystemActors.World].TraitInfos<ILobbyOptions>())
.SelectMany(t => t.LobbyOptions(rules)); .SelectMany(t => t.LobbyOptions(rules));
foreach (var o in options) foreach (var o in options)
@@ -1100,7 +1100,7 @@ namespace OpenRA.Mods.Common.Server
static string MissionBriefingOrDefault(S server) static string MissionBriefingOrDefault(S server)
{ {
var missionData = server.Map.Rules.Actors["world"].TraitInfoOrDefault<MissionDataInfo>(); var missionData = server.Map.Rules.Actors[SystemActors.World].TraitInfoOrDefault<MissionDataInfo>();
if (missionData != null && !string.IsNullOrEmpty(missionData.Briefing)) if (missionData != null && !string.IsNullOrEmpty(missionData.Briefing))
return missionData.Briefing.Replace("\\n", "\n"); return missionData.Briefing.Replace("\\n", "\n");

View File

@@ -25,8 +25,8 @@ namespace OpenRA.Mods.Common.Server
var defaults = new Session.Global(); var defaults = new Session.Global();
LobbyCommands.LoadMapSettings(server, defaults, server.Map.Rules); LobbyCommands.LoadMapSettings(server, defaults, server.Map.Rules);
var options = server.Map.Rules.Actors["player"].TraitInfos<ILobbyOptions>() var options = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<ILobbyOptions>()
.Concat(server.Map.Rules.Actors["world"].TraitInfos<ILobbyOptions>()) .Concat(server.Map.Rules.Actors[SystemActors.World].TraitInfos<ILobbyOptions>())
.SelectMany(t => t.LobbyOptions(server.Map.Rules)) .SelectMany(t => t.LobbyOptions(server.Map.Rules))
.ToDictionary(o => o.Id, o => o); .ToDictionary(o => o.Id, o => o);

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
public void RulesetLoaded(Ruleset rules, ActorInfo ai) public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{ {
if (!rules.Actors["world"].HasTraitInfo<ITiledTerrainRendererInfo>()) if (!rules.Actors[SystemActors.World].HasTraitInfo<ITiledTerrainRendererInfo>())
throw new YamlException("Bridge requires a tile-based terrain renderer."); throw new YamlException("Bridge requires a tile-based terrain renderer.");
if (string.IsNullOrEmpty(DemolishWeapon)) if (string.IsNullOrEmpty(DemolishWeapon))

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("A dictionary of buildings placed on the map. Attach this to the world actor.")] [Desc("A dictionary of buildings placed on the map. Attach this to the world actor.")]
public class BuildingInfluenceInfo : TraitInfo public class BuildingInfluenceInfo : TraitInfo
{ {

View File

@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits
public override void RulesetLoaded(Ruleset rules, ActorInfo ai) public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
{ {
var locomotorInfos = rules.Actors["world"].TraitInfos<LocomotorInfo>(); var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>();
LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor); LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor);
if (LocomotorInfo == null) if (LocomotorInfo == null)
throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor)); throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor));

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits
public override void RulesetLoaded(Ruleset rules, ActorInfo ai) public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
{ {
var locomotorInfos = rules.Actors["world"].TraitInfos<LocomotorInfo>(); var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>();
LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor); LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor);
if (LocomotorInfo == null) if (LocomotorInfo == null)
throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor)); throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor));

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Traits
var map = init.World.Map; var map = init.World.Map;
// Explore map-placed actors if the "Explore Map" option is enabled // Explore map-placed actors if the "Explore Map" option is enabled
var shroudInfo = init.World.Map.Rules.Actors["player"].TraitInfo<ShroudInfo>(); var shroudInfo = init.World.Map.Rules.Actors[SystemActors.Player].TraitInfo<ShroudInfo>();
var exploredMap = init.World.LobbyInfo.GlobalSettings.OptionOrDefault("explored", shroudInfo.ExploredMapCheckboxEnabled); var exploredMap = init.World.LobbyInfo.GlobalSettings.OptionOrDefault("explored", shroudInfo.ExploredMapCheckboxEnabled);
startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>() && !init.Contains<HiddenUnderFogInit>(); startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>() && !init.Contains<HiddenUnderFogInit>();
var buildingInfo = init.Self.Info.TraitInfoOrDefault<BuildingInfo>(); var buildingInfo = init.Self.Info.TraitInfoOrDefault<BuildingInfo>();

View File

@@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
using GUtil = OpenRA.Graphics.Util; 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.")] [Desc("Used for bursted one-colored whole screen effects. Add this to the world actor.")]
public class FlashPaletteEffectInfo : TraitInfo public class FlashPaletteEffectInfo : TraitInfo
{ {

View File

@@ -17,6 +17,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits 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")] [Desc("Fades the world from/to black at the start/end of the game, and can (optionally) desaturate the world")]
public class MenuPaletteEffectInfo : TraitInfo public class MenuPaletteEffectInfo : TraitInfo
{ {

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Palette effect used for sprinkle \"animations\".")] [Desc("Palette effect used for sprinkle \"animations\".")]
class RotationPaletteEffectInfo : TraitInfo class RotationPaletteEffectInfo : TraitInfo
{ {

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor to allow building repair by team mates.")] [Desc("Attach this to the player actor to allow building repair by team mates.")]
class AllyRepairInfo : TraitInfo<AllyRepair> { } class AllyRepairInfo : TraitInfo<AllyRepair> { }

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Plays an audio notification and shows a radar ping when a building is attacked.", [Desc("Plays an audio notification and shows a radar ping when a building is attacked.",
"Attach this to the player actor.")] "Attach this to the player actor.")]
public class BaseAttackNotifierInfo : TraitInfo public class BaseAttackNotifierInfo : TraitInfo

View File

@@ -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.", "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.", "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.")] "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<TechTreeInfo>, Requires<PlayerResourcesInfo> public class ClassicParallelProductionQueueInfo : ProductionQueueInfo, Requires<TechTreeInfo>, Requires<PlayerResourcesInfo>
{ {
[Desc("If you build more actors of the same type,", "the same queue will get its build time lowered for every actor produced there.")] [Desc("If you build more actors of the same type,", "the same queue will get its build time lowered for every actor produced there.")]

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.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.", [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.", "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.")] "You will also want to add PrimaryBuildings: to let the user choose where new units should exit.")]

View File

@@ -11,11 +11,11 @@
using System.Linq; using System.Linq;
using OpenRA.Network; using OpenRA.Network;
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
public class ConquestVictoryConditionsInfo : TraitInfo, Requires<MissionObjectivesInfo> public class ConquestVictoryConditionsInfo : TraitInfo, Requires<MissionObjectivesInfo>
{ {
[Desc("Delay for the end game notification in milliseconds.")] [Desc("Delay for the end game notification in milliseconds.")]

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")] [Desc("Attach this to the player actor.")]
public class DeveloperModeInfo : TraitInfo, ILobbyOptions public class DeveloperModeInfo : TraitInfo, ILobbyOptions
{ {

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Tracks neutral and enemy actors' visibility and notifies the 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.")] "Attach this to the player actor. The actors to track need the 'AnnounceOnSeen' trait.")]
class EnemyWatcherInfo : TraitInfo class EnemyWatcherInfo : TraitInfo

View File

@@ -11,11 +11,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")] [Desc("Attach this to the player actor.")]
public class GrantConditionOnPrerequisiteManagerInfo : TraitInfo, Requires<TechTreeInfo> public class GrantConditionOnPrerequisiteManagerInfo : TraitInfo, Requires<TechTreeInfo>
{ {

View File

@@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
[Desc("Plays an audio notification and shows a radar ping when a harvester is attacked.", [Desc("Plays an audio notification and shows a radar ping when a harvester is attacked.",
"Attach this to the player actor.")] "Attach this to the player actor.")]
[TraitLocation(SystemActors.Player)]
public class HarvesterAttackNotifierInfo : TraitInfo public class HarvesterAttackNotifierInfo : TraitInfo
{ {
[Desc("Minimum duration (in seconds) between notification events.")] [Desc("Minimum duration (in seconds) between notification events.")]

View File

@@ -35,6 +35,7 @@ namespace OpenRA.Mods.Common.Traits
} }
} }
[TraitLocation(SystemActors.Player)]
public class MissionObjectivesInfo : TraitInfo public class MissionObjectivesInfo : TraitInfo
{ {
[Desc("Set this to true if multiple cooperative players have a distinct set of " + [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.", [Desc("Provides game mode progress information for players.",
"Goes on WorldActor - observers don't have a player it can live on.", "Goes on WorldActor - observers don't have a player it can live on.",
"Current options for PanelName are 'SKIRMISH_STATS' and 'MISSION_OBJECTIVES'.")] "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); } public override object Create(ActorInitializer init) { return new ObjectivesPanel(this); }
} }
[TraitLocation(SystemActors.World)]
public class ObjectivesPanel : IObjectivesPanel public class ObjectivesPanel : IObjectivesPanel
{ {
readonly ObjectivesPanelInfo info; readonly ObjectivesPanelInfo info;

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.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.")] [Desc("A beacon that is constructed from a circle sprite that is animated once and a moving arrow sprite.")]
public class PlaceBeaconInfo : TraitInfo public class PlaceBeaconInfo : TraitInfo
{ {

View File

@@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits
// Allows third party mods to detect whether an actor was created by PlaceBuilding. // Allows third party mods to detect whether an actor was created by PlaceBuilding.
public class PlaceBuildingInit : RuntimeFlagInit { } public class PlaceBuildingInit : RuntimeFlagInit { }
[TraitLocation(SystemActors.Player)]
[Desc("Allows the player to execute build orders.", " Attach this to the player actor.")] [Desc("Allows the player to execute build orders.", " Attach this to the player actor.")]
public class PlaceBuildingInfo : TraitInfo public class PlaceBuildingInfo : TraitInfo
{ {

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.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.", [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.", "It can also be used as a point score system in scripted maps, for example.",
"Attach this to the player actor.")] "Attach this to the player actor.")]

View File

@@ -11,11 +11,11 @@
using System; using System;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
public class PlayerRadarTerrainInfo : TraitInfo, Requires<ShroudInfo> public class PlayerRadarTerrainInfo : TraitInfo, Requires<ShroudInfo>
{ {
public override object Create(ActorInitializer init) public override object Create(ActorInitializer init)

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player | SystemActors.EditorPlayer)]
public class PlayerResourcesInfo : TraitInfo, ILobbyOptions public class PlayerResourcesInfo : TraitInfo, ILobbyOptions
{ {
[Desc("Descriptive label for the starting cash option in the lobby.")] [Desc("Descriptive label for the starting cash option in the lobby.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor to collect observer stats.")] [Desc("Attach this to the player actor to collect observer stats.")]
public class PlayerStatisticsInfo : TraitInfo public class PlayerStatisticsInfo : TraitInfo
{ {

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
public class ProvidesTechPrerequisiteInfo : TraitInfo, ITechTreePrerequisiteInfo public class ProvidesTechPrerequisiteInfo : TraitInfo, ITechTreePrerequisiteInfo
{ {
[Desc("Internal id for this tech level.")] [Desc("Internal id for this tech level.")]

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Provides the player with an audible warning when their storage is nearing full.")] [Desc("Provides the player with an audible warning when their storage is nearing full.")]
public class ResourceStorageWarningInfo : TraitInfo, Requires<PlayerResourcesInfo> public class ResourceStorageWarningInfo : TraitInfo, Requires<PlayerResourcesInfo>
{ {

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Manages build limits and pre-requisites.", " Attach this to the player actor.")] [Desc("Manages build limits and pre-requisites.", " Attach this to the player actor.")]
public class TechTreeInfo : TraitInfo public class TechTreeInfo : TraitInfo
{ {

View File

@@ -17,6 +17,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("This trait allows setting a time limit on matches. Attach this to the World actor.")] [Desc("This trait allows setting a time limit on matches. Attach this to the World actor.")]
public class TimeLimitManagerInfo : TraitInfo, ILobbyOptions, IRulesetLoaded public class TimeLimitManagerInfo : TraitInfo, ILobbyOptions, IRulesetLoaded
{ {

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")] [Desc("Attach this to the player actor.")]
public class PowerManagerInfo : TraitInfo, Requires<DeveloperModeInfo> public class PowerManagerInfo : TraitInfo, Requires<DeveloperModeInfo>
{ {

View File

@@ -17,6 +17,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
class ProductionQueueFromSelectionInfo : TraitInfo class ProductionQueueFromSelectionInfo : TraitInfo
{ {
public string ProductionTabsWidget = null; public string ProductionTabsWidget = null;

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits
public void RulesetLoaded(Ruleset rules, ActorInfo info) public void RulesetLoaded(Ruleset rules, ActorInfo info)
{ {
var pci = rules.Actors["player"].TraitInfoOrDefault<ProximityCaptorInfo>(); var pci = rules.Actors[SystemActors.Player].TraitInfoOrDefault<ProximityCaptorInfo>();
if (pci == null) if (pci == null)
throw new YamlException("ProximityCapturable requires the `Player` actor to have the ProximityCaptor trait."); throw new YamlException("ProximityCapturable requires the `Player` actor to have the ProximityCaptor trait.");
} }

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("Displays custom terrain types.")] [Desc("Displays custom terrain types.")]
class CustomTerrainDebugOverlayInfo : TraitInfo class CustomTerrainDebugOverlayInfo : TraitInfo
{ {

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits.Render
// No queues available - check for classic production queues // No queues available - check for classic production queues
if (queue == null) if (queue == null)
queue = rules.Actors["player"].TraitInfos<ProductionQueueInfo>().FirstOrDefault(q => ProductionType == q.Type); queue = rules.Actors[SystemActors.Player].TraitInfos<ProductionQueueInfo>().FirstOrDefault(q => ProductionType == q.Type);
if (queue == null) if (queue == null)
throw new YamlException("Can't find a queue with ProductionType '{0}'".F(ProductionType)); throw new YamlException("Can't find a queue with ProductionType '{0}'".F(ProductionType));

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render namespace OpenRA.Mods.Common.Traits.Render
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor. When attached, enables all actors possessing the ProducibleWithLevel ", [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. ", "trait to have their production queue icons render with an overlay defined in this trait. ",
"The icon change occurs when ProducibleWithLevel.Prerequisites are met.")] "The icon change occurs when ProducibleWithLevel.Prerequisites are met.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")] [Desc("Attach this to the player actor.")]
public class SupportPowerManagerInfo : TraitInfo, Requires<DeveloperModeInfo>, Requires<TechTreeInfo> public class SupportPowerManagerInfo : TraitInfo, Requires<DeveloperModeInfo>, Requires<TechTreeInfo>
{ {

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Traits
public void RulesetLoaded(Ruleset rules, ActorInfo ai) public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{ {
if (!rules.Actors["world"].HasTraitInfo<TerrainLightingInfo>()) if (!rules.Actors[SystemActors.World].HasTraitInfo<TerrainLightingInfo>())
throw new YamlException("TerrainLightSource can only be used with the world TerrainLighting trait."); throw new YamlException("TerrainLightSource can only be used with the world TerrainLighting trait.");
} }

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class ActorMapInfo : TraitInfo public class ActorMapInfo : TraitInfo
{ {
[Desc("Size of partition bins (cells)")] [Desc("Size of partition bins (cells)")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[Desc("Controls the spawning of specified actor types. Attach this to the world actor.")] [Desc("Controls the spawning of specified actor types. Attach this to the world actor.")]
[TraitLocation(SystemActors.World)]
public class ActorSpawnManagerInfo : ConditionalTraitInfo, Requires<MapCreepsInfo> public class ActorSpawnManagerInfo : ConditionalTraitInfo, Requires<MapCreepsInfo>
{ {
[Desc("Minimum number of actors.")] [Desc("Minimum number of actors.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
public class CrateSpawnerInfo : TraitInfo, ILobbyOptions public class CrateSpawnerInfo : TraitInfo, ILobbyOptions
{ {
[Desc("Descriptive label for the crates checkbox in the lobby.")] [Desc("Descriptive label for the crates checkbox in the lobby.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("Attach this to the world actor.")] [Desc("Attach this to the world actor.")]
public class CreateMapPlayersInfo : TraitInfo<CreateMapPlayers>, ICreatePlayersInfo public class CreateMapPlayersInfo : TraitInfo<CreateMapPlayers>, ICreatePlayersInfo
{ {
@@ -27,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
/// </summary> /// </summary>
void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List<GameInformation.Player> players, MersenneTwister playerRandom) void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List<GameInformation.Player> players, MersenneTwister playerRandom)
{ {
var worldInfo = map.Rules.Actors["world"]; var worldInfo = map.Rules.Actors[SystemActors.World];
var factions = worldInfo.TraitInfos<FactionInfo>().ToArray(); var factions = worldInfo.TraitInfos<FactionInfo>().ToArray();
var assignSpawnLocations = worldInfo.TraitInfoOrDefault<IAssignSpawnPointsInfo>(); var assignSpawnLocations = worldInfo.TraitInfoOrDefault<IAssignSpawnPointsInfo>();
var spawnState = assignSpawnLocations?.InitializeState(map, lobbyInfo); var spawnState = assignSpawnLocations?.InitializeState(map, lobbyInfo);
@@ -41,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits
} }
// Create the regular playable players. // Create the regular playable players.
var bots = map.Rules.Actors["player"].TraitInfos<IBotInfo>().ToArray(); var bots = map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>().ToArray();
foreach (var kv in lobbyInfo.Slots) foreach (var kv in lobbyInfo.Slots)
{ {

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("Identify untraversable regions of the map for faster pathfinding, especially with AI.", [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.")] "This trait is required. Every mod needs it attached to the world actor.")]
class DomainIndexInfo : TraitInfo<DomainIndex> { } class DomainIndexInfo : TraitInfo<DomainIndex> { }

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.EditorWorld)]
public class EditorActionManagerInfo : TraitInfo<EditorActionManager> { } public class EditorActionManagerInfo : TraitInfo<EditorActionManager> { }
public class EditorActionManager : IWorldLoaded public class EditorActionManager : IWorldLoaded

View File

@@ -21,6 +21,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")] [Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorActorLayerInfo : TraitInfo, ICreatePlayersInfo public class EditorActorLayerInfo : TraitInfo, ICreatePlayersInfo
{ {

View File

@@ -19,6 +19,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
public enum EditorCursorType { None, Actor, TerrainTemplate, Resource } public enum EditorCursorType { None, Actor, TerrainTemplate, Resource }
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")] [Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorCursorLayerInfo : TraitInfo, Requires<EditorActorLayerInfo>, Requires<ITiledTerrainRendererInfo> public class EditorCursorLayerInfo : TraitInfo, Requires<EditorActorLayerInfo>, Requires<ITiledTerrainRendererInfo>
{ {

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")] [Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorResourceLayerInfo : TraitInfo, IResourceLayerInfo, IMapPreviewSignatureInfo public class EditorResourceLayerInfo : TraitInfo, IResourceLayerInfo, IMapPreviewSignatureInfo
{ {
@@ -94,7 +95,7 @@ namespace OpenRA.Mods.Common.Traits
if (w.Type != WorldType.Editor) if (w.Type != WorldType.Editor)
return; return;
var playerResourcesInfo = w.Map.Rules.Actors["player"].TraitInfoOrDefault<PlayerResourcesInfo>(); var playerResourcesInfo = w.Map.Rules.Actors[SystemActors.Player].TraitInfoOrDefault<PlayerResourcesInfo>();
resourceValues = playerResourcesInfo?.ResourceValues ?? new Dictionary<string, int>(); resourceValues = playerResourcesInfo?.ResourceValues ?? new Dictionary<string, int>();
foreach (var cell in Map.AllCells) foreach (var cell in Map.AllCells)

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")] [Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorSelectionLayerInfo : TraitInfo public class EditorSelectionLayerInfo : TraitInfo
{ {

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
public class GameSaveViewportManagerInfo : TraitInfo public class GameSaveViewportManagerInfo : TraitInfo
{ {
public override object Create(ActorInitializer init) { return new GameSaveViewportManager(); } public override object Create(ActorInitializer init) { return new GameSaveViewportManager(); }

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common namespace OpenRA.Mods.Common
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Define a palette by swapping palette indices.")] [Desc("Define a palette by swapping palette indices.")]
public class IndexedPaletteInfo : TraitInfo, IRulesetLoaded public class IndexedPaletteInfo : TraitInfo, IRulesetLoaded
{ {

View File

@@ -19,6 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
class LegacyBridgeLayerInfo : TraitInfo class LegacyBridgeLayerInfo : TraitInfo
{ {
[ActorReference] [ActorReference]

View File

@@ -16,6 +16,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class LoadWidgetAtGameStartInfo : TraitInfo public class LoadWidgetAtGameStartInfo : TraitInfo
{ {
[Desc("The widget tree to open when a shellmap is loaded (i.e. the main menu).")] [Desc("The widget tree to open when a shellmap is loaded (i.e. the main menu).")]

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.Player)]
[Desc("Enables defined prerequisites at game start for all players if the checkbox is enabled.")] [Desc("Enables defined prerequisites at game start for all players if the checkbox is enabled.")]
public class LobbyPrerequisiteCheckboxInfo : TraitInfo, ILobbyOptions, ITechTreePrerequisiteInfo public class LobbyPrerequisiteCheckboxInfo : TraitInfo, ILobbyOptions, ITechTreePrerequisiteInfo
{ {

View File

@@ -54,6 +54,7 @@ namespace OpenRA.Mods.Common.Traits
public const byte ElevatedBridge = 4; 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.")] [Desc("Used by Mobile. Attach these to the world actor. You can have multiple variants by adding @suffixes.")]
public class LocomotorInfo : TraitInfo public class LocomotorInfo : TraitInfo
{ {

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("Controls the build radius checkboxes in the lobby options.")] [Desc("Controls the build radius checkboxes in the lobby options.")]
public class MapBuildRadiusInfo : TraitInfo, ILobbyOptions public class MapBuildRadiusInfo : TraitInfo, ILobbyOptions
{ {

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[Desc("Controls the 'Creeps' checkbox in the lobby options.")] [Desc("Controls the 'Creeps' checkbox in the lobby options.")]
[TraitLocation(SystemActors.World)]
public class MapCreepsInfo : TraitInfo, ILobbyOptions public class MapCreepsInfo : TraitInfo, ILobbyOptions
{ {
[Desc("Descriptive label for the creeps checkbox in the lobby.")] [Desc("Descriptive label for the creeps checkbox in the lobby.")]

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World)]
[Desc("Controls the game speed, tech level, and short game lobby options.")] [Desc("Controls the game speed, tech level, and short game lobby options.")]
public class MapOptionsInfo : TraitInfo, ILobbyOptions, IRulesetLoaded public class MapOptionsInfo : TraitInfo, ILobbyOptions, IRulesetLoaded
{ {
@@ -77,7 +78,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new LobbyBooleanOption("shortgame", ShortGameCheckboxLabel, ShortGameCheckboxDescription, yield return new LobbyBooleanOption("shortgame", ShortGameCheckboxLabel, ShortGameCheckboxDescription,
ShortGameCheckboxVisible, ShortGameCheckboxDisplayOrder, ShortGameCheckboxEnabled, ShortGameCheckboxLocked); ShortGameCheckboxVisible, ShortGameCheckboxDisplayOrder, ShortGameCheckboxEnabled, ShortGameCheckboxLocked);
var techLevels = rules.Actors["player"].TraitInfos<ProvidesTechPrerequisiteInfo>() var techLevels = rules.Actors[SystemActors.Player].TraitInfos<ProvidesTechPrerequisiteInfo>()
.ToDictionary(t => t.Id, t => t.Name); .ToDictionary(t => t.Id, t => t.Name);
if (techLevels.Any()) if (techLevels.Any())

View File

@@ -19,6 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.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.")] [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 public class MapStartingLocationsInfo : TraitInfo, ILobbyOptions, IAssignSpawnPointsInfo
{ {

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.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.")] [Desc("Used by SpawnStartingUnits. Attach these to the world actor. You can have multiple variants by adding @suffixes.")]
public class StartingUnitsInfo : TraitInfo<StartingUnits> public class StartingUnitsInfo : TraitInfo<StartingUnits>
{ {

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Trait for music handling. Attach this to the world actor.")] [Desc("Trait for music handling. Attach this to the world actor.")]
public class MusicPlaylistInfo : TraitInfo public class MusicPlaylistInfo : TraitInfo
{ {

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Load VGA palette (.pal) registers.")] [Desc("Load VGA palette (.pal) registers.")]
class PaletteFromFileInfo : TraitInfo, IProvidesCursorPaletteInfo class PaletteFromFileInfo : TraitInfo, IProvidesCursorPaletteInfo
{ {

View File

@@ -19,6 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.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.")] [Desc("Load a GIMP .gpl or JASC .pal palette file. Supports per-color alpha.")]
class PaletteFromGimpOrJascFileInfo : TraitInfo, IProvidesCursorPaletteInfo class PaletteFromGimpOrJascFileInfo : TraitInfo, IProvidesCursorPaletteInfo
{ {

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Create a palette by applying alpha transparency to another palette.")] [Desc("Create a palette by applying alpha transparency to another palette.")]
class PaletteFromPaletteWithAlphaInfo : TraitInfo class PaletteFromPaletteWithAlphaInfo : TraitInfo
{ {

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Create player palettes by applying alpha transparency to another player palette.")] [Desc("Create player palettes by applying alpha transparency to another player palette.")]
class PaletteFromPlayerPaletteWithAlphaInfo : TraitInfo class PaletteFromPlayerPaletteWithAlphaInfo : TraitInfo
{ {

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Load a PNG and use its embedded palette.")] [Desc("Load a PNG and use its embedded palette.")]
class PaletteFromPngInfo : TraitInfo, IProvidesCursorPaletteInfo class PaletteFromPngInfo : TraitInfo, IProvidesCursorPaletteInfo
{ {

Some files were not shown because too many files have changed in this diff Show More