Enable dedicated server lint checks.
This commit is contained in:
@@ -61,6 +61,7 @@ namespace OpenRA
|
||||
public readonly string tileset;
|
||||
public readonly string rules;
|
||||
public readonly string players_block;
|
||||
public readonly int mapformat;
|
||||
}
|
||||
|
||||
public class MapPreview : IDisposable, IReadOnlyFileSystem
|
||||
@@ -68,6 +69,7 @@ namespace OpenRA
|
||||
/// <summary>Wrapper that enables map data to be replaced in an atomic fashion</summary>
|
||||
class InnerData
|
||||
{
|
||||
public int MapFormat;
|
||||
public string Title;
|
||||
public string[] Categories;
|
||||
public string Author;
|
||||
@@ -168,6 +170,7 @@ namespace OpenRA
|
||||
|
||||
volatile InnerData innerData;
|
||||
|
||||
public int MapFormat => innerData.MapFormat;
|
||||
public string Title => innerData.Title;
|
||||
public string[] Categories => innerData.Categories;
|
||||
public string Author => innerData.Author;
|
||||
@@ -183,6 +186,7 @@ namespace OpenRA
|
||||
public MapVisibility Visibility => innerData.Visibility;
|
||||
|
||||
public MiniYaml RuleDefinitions => innerData.RuleDefinitions;
|
||||
public MiniYaml WeaponDefinitions => innerData.WeaponDefinitions;
|
||||
|
||||
public ActorInfo WorldActorInfo => innerData.WorldActorInfo;
|
||||
public ActorInfo PlayerActorInfo => innerData.PlayerActorInfo;
|
||||
@@ -234,6 +238,7 @@ namespace OpenRA
|
||||
Uid = uid;
|
||||
innerData = new InnerData
|
||||
{
|
||||
MapFormat = 0,
|
||||
Title = "Unknown Map",
|
||||
Categories = new[] { "Unknown" },
|
||||
Author = "Unknown Author",
|
||||
@@ -250,6 +255,53 @@ namespace OpenRA
|
||||
};
|
||||
}
|
||||
|
||||
// For linting purposes only!
|
||||
public MapPreview(Map map, ModData modData)
|
||||
{
|
||||
this.modData = modData;
|
||||
cache = modData.MapCache;
|
||||
|
||||
Uid = map.Uid;
|
||||
Package = map.Package;
|
||||
|
||||
var mapPlayers = new MapPlayers(map.PlayerDefinitions);
|
||||
var spawns = new List<CPos>();
|
||||
foreach (var kv in map.ActorDefinitions.Where(d => d.Value.Value == "mpspawn"))
|
||||
{
|
||||
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
|
||||
spawns.Add(s.Get<LocationInit>().Value);
|
||||
}
|
||||
|
||||
innerData = new InnerData
|
||||
{
|
||||
MapFormat = map.MapFormat,
|
||||
Title = map.Title,
|
||||
Categories = map.Categories,
|
||||
Author = map.Author,
|
||||
TileSet = map.Tileset,
|
||||
Players = mapPlayers,
|
||||
PlayerCount = mapPlayers.Players.Count(x => x.Value.Playable),
|
||||
SpawnPoints = spawns.ToArray(),
|
||||
GridType = map.Grid.Type,
|
||||
Bounds = map.Bounds,
|
||||
Preview = null,
|
||||
Status = MapStatus.Available,
|
||||
Class = MapClassification.Unknown,
|
||||
Visibility = map.Visibility,
|
||||
};
|
||||
|
||||
innerData.SetCustomRules(modData, this, new Dictionary<string, MiniYaml>()
|
||||
{
|
||||
{ "Rules", map.RuleDefinitions },
|
||||
{ "Weapons", map.WeaponDefinitions },
|
||||
{ "Voices", map.VoiceDefinitions },
|
||||
{ "Music", map.MusicDefinitions },
|
||||
{ "Notifications", map.NotificationDefinitions },
|
||||
{ "Sequences", map.SequenceDefinitions },
|
||||
{ "ModelSequences", map.ModelSequenceDefinitions }
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateFromMap(IReadOnlyPackage p, IReadOnlyPackage parent, MapClassification classification, string[] mapCompatibility, MapGridType gridType)
|
||||
{
|
||||
Dictionary<string, MiniYaml> yaml;
|
||||
@@ -297,6 +349,9 @@ namespace OpenRA
|
||||
if (yaml.TryGetValue("RequiresMod", out temp))
|
||||
requiresMod = temp.Value;
|
||||
|
||||
if (yaml.TryGetValue("MapFormat", out temp))
|
||||
newData.MapFormat = FieldLoader.GetValue<int>("MapFormat", temp.Value);
|
||||
|
||||
newData.Status = mapCompatibility == null || mapCompatibility.Contains(requiresMod) ?
|
||||
MapStatus.Available : MapStatus.Unavailable;
|
||||
|
||||
@@ -372,6 +427,7 @@ namespace OpenRA
|
||||
newData.PlayerCount = r.players;
|
||||
newData.Bounds = r.bounds;
|
||||
newData.TileSet = r.tileset;
|
||||
newData.MapFormat = r.mapformat;
|
||||
|
||||
var spawns = new CPos[r.spawnpoints.Length / 2];
|
||||
for (var j = 0; j < r.spawnpoints.Length; j += 2)
|
||||
|
||||
@@ -15,47 +15,46 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckActorReferences : ILintRulesPass
|
||||
public class CheckActorReferences : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
Action<string> emitError;
|
||||
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
this.emitError = emitError;
|
||||
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
foreach (var traitInfo in actorInfo.Value.TraitInfos<TraitInfo>())
|
||||
CheckTrait(actorInfo.Value, traitInfo, rules);
|
||||
CheckTrait(emitError, actorInfo.Value, traitInfo, rules);
|
||||
}
|
||||
|
||||
void CheckTrait(ActorInfo actorInfo, TraitInfo traitInfo, Ruleset rules)
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
foreach (var actorInfo in mapRules.Actors)
|
||||
foreach (var traitInfo in actorInfo.Value.TraitInfos<TraitInfo>())
|
||||
CheckTrait(emitError, actorInfo.Value, traitInfo, mapRules);
|
||||
}
|
||||
|
||||
void CheckTrait(Action<string> emitError, ActorInfo actorInfo, TraitInfo traitInfo, Ruleset rules)
|
||||
{
|
||||
var actualType = traitInfo.GetType();
|
||||
foreach (var field in actualType.GetFields())
|
||||
{
|
||||
if (field.HasAttribute<ActorReferenceAttribute>())
|
||||
CheckActorReference(actorInfo, traitInfo, field, rules.Actors,
|
||||
CheckActorReference(emitError, actorInfo, traitInfo, field, rules.Actors,
|
||||
field.GetCustomAttributes<ActorReferenceAttribute>(true)[0]);
|
||||
|
||||
if (field.HasAttribute<WeaponReferenceAttribute>())
|
||||
CheckWeaponReference(actorInfo, traitInfo, field, rules.Weapons,
|
||||
field.GetCustomAttributes<WeaponReferenceAttribute>(true)[0]);
|
||||
CheckWeaponReference(emitError, actorInfo, traitInfo, field, rules.Weapons);
|
||||
|
||||
if (field.HasAttribute<VoiceSetReferenceAttribute>())
|
||||
CheckVoiceReference(actorInfo, traitInfo, field, rules.Voices,
|
||||
field.GetCustomAttributes<VoiceSetReferenceAttribute>(true)[0]);
|
||||
CheckVoiceReference(emitError, actorInfo, traitInfo, field, rules.Voices);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckActorReference(ActorInfo actorInfo,
|
||||
TraitInfo traitInfo,
|
||||
FieldInfo fieldInfo,
|
||||
IReadOnlyDictionary<string, ActorInfo> dict,
|
||||
ActorReferenceAttribute attribute)
|
||||
void CheckActorReference(Action<string> emitError, ActorInfo actorInfo, TraitInfo traitInfo,
|
||||
FieldInfo fieldInfo, IReadOnlyDictionary<string, ActorInfo> dict, ActorReferenceAttribute attribute)
|
||||
{
|
||||
var values = LintExts.GetFieldValues(traitInfo, fieldInfo, emitError, attribute.DictionaryReference);
|
||||
foreach (var value in values)
|
||||
@@ -82,11 +81,8 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
void CheckWeaponReference(ActorInfo actorInfo,
|
||||
TraitInfo traitInfo,
|
||||
FieldInfo fieldInfo,
|
||||
IReadOnlyDictionary<string, WeaponInfo> dict,
|
||||
WeaponReferenceAttribute attribute)
|
||||
void CheckWeaponReference(Action<string> emitError, ActorInfo actorInfo, TraitInfo traitInfo,
|
||||
FieldInfo fieldInfo, IReadOnlyDictionary<string, WeaponInfo> dict)
|
||||
{
|
||||
var values = LintExts.GetFieldValues(traitInfo, fieldInfo, emitError);
|
||||
foreach (var value in values)
|
||||
@@ -100,11 +96,8 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
void CheckVoiceReference(ActorInfo actorInfo,
|
||||
TraitInfo traitInfo,
|
||||
FieldInfo fieldInfo,
|
||||
IReadOnlyDictionary<string, SoundInfo> dict,
|
||||
VoiceSetReferenceAttribute attribute)
|
||||
void CheckVoiceReference(Action<string> emitError, ActorInfo actorInfo, TraitInfo traitInfo,
|
||||
FieldInfo fieldInfo, IReadOnlyDictionary<string, SoundInfo> dict)
|
||||
{
|
||||
var values = LintExts.GetFieldValues(traitInfo, fieldInfo, emitError);
|
||||
foreach (var value in values)
|
||||
|
||||
@@ -11,12 +11,23 @@
|
||||
|
||||
using System;
|
||||
using OpenRA.Mods.Common.Projectiles;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckAngle : ILintRulesPass
|
||||
class CheckAngle : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var weaponInfo in rules.Weapons)
|
||||
{
|
||||
|
||||
@@ -12,13 +12,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckConditions : ILintRulesPass
|
||||
public class CheckConditions : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, emitWarning, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, emitWarning, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,12 +12,13 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckConflictingMouseBounds : ILintRulesPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,13 +12,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckCursors : ILintRulesPass
|
||||
class CheckCursors : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, modData, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, modData, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, ModData modData, Ruleset rules)
|
||||
{
|
||||
var fileSystem = modData.DefaultFileSystem;
|
||||
var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)));
|
||||
|
||||
@@ -12,13 +12,24 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckDefaultVisibility : ILintRulesPass
|
||||
class CheckDefaultVisibility : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,13 +12,24 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckHitShapes : ILintRulesPass
|
||||
class CheckHitShapes : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,13 +12,24 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckLocomotorReferences : ILintRulesPass
|
||||
public class CheckLocomotorReferences : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
var worldActor = rules.Actors[SystemActors.World];
|
||||
var locomotorInfos = worldActor.TraitInfos<LocomotorInfo>().ToArray();
|
||||
|
||||
@@ -11,24 +11,34 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckMapMetadata : ILintMapPass
|
||||
public class CheckMapMetadata : ILintMapPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
void ILintMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
if (map.MapFormat != Map.SupportedMapFormat)
|
||||
emitError("Map format {0} does not match the supported version {1}."
|
||||
.F(map.MapFormat, Map.SupportedMapFormat));
|
||||
Run(emitError, map.MapFormat, map.Author, map.Title, map.Categories);
|
||||
}
|
||||
|
||||
if (map.Author == null)
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, map.MapFormat, map.Author, map.Title, map.Categories);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, int mapFormat, string author, string title, string[] categories)
|
||||
{
|
||||
if (mapFormat != Map.SupportedMapFormat)
|
||||
emitError("Map format {0} does not match the supported version {1}.".F(mapFormat, Map.SupportedMapFormat));
|
||||
|
||||
if (author == null)
|
||||
emitError("Map does not define a valid author.");
|
||||
|
||||
if (map.Title == null)
|
||||
if (title == null)
|
||||
emitError("Map does not define a valid title.");
|
||||
|
||||
if (!map.Categories.Any())
|
||||
if (!categories.Any())
|
||||
emitError("Map does not define any categories.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,15 +11,25 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckNotifications : ILintRulesPass
|
||||
class CheckNotifications : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
52
OpenRA.Mods.Common/Lint/CheckOwners.cs
Normal file
52
OpenRA.Mods.Common/Lint/CheckOwners.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 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.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckOwners : ILintMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
var playerNames = new MapPlayers(map.PlayerDefinitions).Players.Values
|
||||
.Select(p => p.Name)
|
||||
.ToHashSet();
|
||||
|
||||
// Check for actors that require specific owners
|
||||
var actorsWithRequiredOwner = map.Rules.Actors
|
||||
.Where(a => a.Value.HasTraitInfo<RequiresSpecificOwnersInfo>())
|
||||
.ToDictionary(a => a.Key, a => a.Value.TraitInfo<RequiresSpecificOwnersInfo>());
|
||||
|
||||
foreach (var kv in map.ActorDefinitions)
|
||||
{
|
||||
var actorReference = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
|
||||
var ownerInit = actorReference.GetOrDefault<OwnerInit>();
|
||||
if (ownerInit == null)
|
||||
emitError("Actor {0} is not owned by any player.".F(kv.Key));
|
||||
else
|
||||
{
|
||||
var ownerName = ownerInit.InternalName;
|
||||
if (!playerNames.Contains(ownerName))
|
||||
emitError("Actor {0} is owned by unknown player {1}.".F(kv.Key, ownerName));
|
||||
|
||||
if (actorsWithRequiredOwner.TryGetValue(kv.Value.Value, out var info))
|
||||
if (!info.ValidOwnerNames.Contains(ownerName))
|
||||
emitError("Actor {0} owner {1} is not one of ValidOwnerNames: {2}".F(kv.Key, ownerName, info.ValidOwnerNames.JoinWith(", ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,18 +12,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckPalettes : ILintRulesPass
|
||||
class CheckPalettes : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
List<string> palettes = new List<string>();
|
||||
List<string> playerPalettes = new List<string>();
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
GetPalettes(emitError, rules);
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
var palettes = new List<string>();
|
||||
var playerPalettes = new List<string>();
|
||||
GetPalettes(emitError, rules, palettes, playerPalettes);
|
||||
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
@@ -111,7 +121,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
void GetPalettes(Action<string> emitError, Ruleset rules)
|
||||
void GetPalettes(Action<string> emitError, Ruleset rules, List<string> palettes, List<string> playerPalettes)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -13,21 +13,39 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckPlayers : ILintMapPass
|
||||
public class CheckPlayers : ILintMapPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
void ILintMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
var players = new MapPlayers(map.PlayerDefinitions).Players;
|
||||
if (players.Count > 64)
|
||||
var players = new MapPlayers(map.PlayerDefinitions);
|
||||
var spawns = new List<CPos>();
|
||||
foreach (var kv in map.ActorDefinitions.Where(d => d.Value.Value == "mpspawn"))
|
||||
{
|
||||
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
|
||||
spawns.Add(s.Get<LocationInit>().Value);
|
||||
}
|
||||
|
||||
Run(emitError, emitWarning, players, map.Visibility, map.Rules.Actors[SystemActors.World], spawns.ToArray());
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, emitWarning, map.Players, map.Visibility, map.WorldActorInfo, map.SpawnPoints);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Action<string> emitWarning, MapPlayers players, MapVisibility visibility, ActorInfo worldActorInfo, CPos[] spawnPoints)
|
||||
{
|
||||
if (players.Players.Count > 64)
|
||||
emitError("Defining more than 64 players is not allowed.");
|
||||
|
||||
var worldOwnerFound = false;
|
||||
var playerNames = players.Values.Select(p => p.Name).ToHashSet();
|
||||
foreach (var player in players.Values)
|
||||
var playerNames = players.Players.Values.Select(p => p.Name).ToHashSet();
|
||||
foreach (var player in players.Players.Values)
|
||||
{
|
||||
foreach (var ally in player.Allies)
|
||||
if (!playerNames.Contains(ally))
|
||||
@@ -46,7 +64,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
if (player.Playable)
|
||||
emitError("The player {0} owning the world can't be playable.".F(player.Name));
|
||||
}
|
||||
else if (map.Visibility == MapVisibility.MissionSelector && player.Playable && !player.LockFaction)
|
||||
else if (visibility == MapVisibility.MissionSelector && player.Playable && !player.LockFaction)
|
||||
{
|
||||
// Missions must lock the faction of the player to force the server to override the default Random faction
|
||||
emitError("The player {0} must specify LockFaction: True.".F(player.Name));
|
||||
@@ -56,51 +74,20 @@ namespace OpenRA.Mods.Common.Lint
|
||||
if (!worldOwnerFound)
|
||||
emitError("Found no player owning the world.");
|
||||
|
||||
var worldActor = map.Rules.Actors[SystemActors.World];
|
||||
var factions = worldActor.TraitInfos<FactionInfo>().Select(f => f.InternalName).ToHashSet();
|
||||
foreach (var player in players.Values)
|
||||
var factions = worldActorInfo.TraitInfos<FactionInfo>().Select(f => f.InternalName).ToHashSet();
|
||||
foreach (var player in players.Players.Values)
|
||||
if (!string.IsNullOrWhiteSpace(player.Faction) && !factions.Contains(player.Faction))
|
||||
emitError("Invalid faction {0} chosen for player {1}.".F(player.Faction, player.Name));
|
||||
|
||||
if (worldActor.HasTraitInfo<MapStartingLocationsInfo>())
|
||||
if (worldActorInfo.HasTraitInfo<MapStartingLocationsInfo>())
|
||||
{
|
||||
var playerCount = players.Count(p => p.Value.Playable);
|
||||
var spawns = new List<CPos>();
|
||||
foreach (var kv in map.ActorDefinitions.Where(d => d.Value.Value == "mpspawn"))
|
||||
{
|
||||
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
|
||||
spawns.Add(s.Get<LocationInit>().Value);
|
||||
}
|
||||
var playerCount = players.Players.Count(p => p.Value.Playable);
|
||||
if (playerCount > spawnPoints.Length)
|
||||
emitError("The map allows {0} possible players, but defines only {1} spawn points".F(playerCount, spawnPoints.Length));
|
||||
|
||||
if (playerCount > spawns.Count)
|
||||
emitError("The map allows {0} possible players, but defines only {1} spawn points".F(playerCount, spawns.Count));
|
||||
|
||||
if (spawns.Distinct().Count() != spawns.Count)
|
||||
if (spawnPoints.Distinct().Count() != spawnPoints.Length)
|
||||
emitError("Duplicate spawn point locations detected.");
|
||||
}
|
||||
|
||||
// Check for actors that require specific owners
|
||||
var actorsWithRequiredOwner = map.Rules.Actors
|
||||
.Where(a => a.Value.HasTraitInfo<RequiresSpecificOwnersInfo>())
|
||||
.ToDictionary(a => a.Key, a => a.Value.TraitInfo<RequiresSpecificOwnersInfo>());
|
||||
|
||||
foreach (var kv in map.ActorDefinitions)
|
||||
{
|
||||
var actorReference = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
|
||||
var ownerInit = actorReference.GetOrDefault<OwnerInit>();
|
||||
if (ownerInit == null)
|
||||
emitError("Actor {0} is not owned by any player.".F(kv.Key));
|
||||
else
|
||||
{
|
||||
var ownerName = ownerInit.InternalName;
|
||||
if (!playerNames.Contains(ownerName))
|
||||
emitError("Actor {0} is owned by unknown player {1}.".F(kv.Key, ownerName));
|
||||
|
||||
if (actorsWithRequiredOwner.TryGetValue(kv.Value.Value, out var info))
|
||||
if (!info.ValidOwnerNames.Contains(ownerName))
|
||||
emitError("Actor {0} owner {1} is not one of ValidOwnerNames: {2}".F(kv.Key, ownerName, info.ValidOwnerNames.JoinWith(", ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,23 @@
|
||||
|
||||
using System;
|
||||
using OpenRA.Mods.Common.Projectiles;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckRangeLimit : ILintRulesPass
|
||||
class CheckRangeLimit : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var weaponInfo in rules.Weapons)
|
||||
{
|
||||
|
||||
@@ -12,13 +12,24 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckRevealFootprint : ILintRulesPass
|
||||
class CheckRevealFootprint : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,12 +12,23 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits.Render;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckSpriteBodies : ILintRulesPass
|
||||
class CheckSpriteBodies : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,12 +12,23 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckTooltips : ILintRulesPass
|
||||
class CheckTooltips : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -11,12 +11,23 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckTraitPrerequisites : ILintRulesPass
|
||||
public class CheckTraitPrerequisites : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, emitWarning, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, emitWarning, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,11 +12,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckUnknownTraitFields : ILintPass, ILintMapPass
|
||||
class CheckUnknownTraitFields : ILintPass, ILintMapPass, ILintServerMapPass
|
||||
{
|
||||
void ILintPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData)
|
||||
{
|
||||
foreach (var f in modData.Manifest.Rules)
|
||||
CheckActors(MiniYaml.FromStream(modData.DefaultFileSystem.Open(f), f), emitError, modData);
|
||||
}
|
||||
|
||||
void ILintMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
CheckMapYaml(emitError, modData, map, map.RuleDefinitions);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
CheckMapYaml(emitError, modData, map, map.RuleDefinitions);
|
||||
}
|
||||
|
||||
string NormalizeName(string key)
|
||||
{
|
||||
var name = key.Split('@')[0];
|
||||
@@ -64,23 +82,17 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
void ILintPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData)
|
||||
void CheckMapYaml(Action<string> emitError, ModData modData, IReadOnlyFileSystem fileSystem, MiniYaml ruleDefinitions)
|
||||
{
|
||||
foreach (var f in modData.Manifest.Rules)
|
||||
CheckActors(MiniYaml.FromStream(modData.DefaultFileSystem.Open(f), f), emitError, modData);
|
||||
}
|
||||
if (ruleDefinitions == null)
|
||||
return;
|
||||
|
||||
void ILintMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
if (map.RuleDefinitions != null && map.RuleDefinitions.Value != null)
|
||||
{
|
||||
var mapFiles = FieldLoader.GetValue<string[]>("value", map.RuleDefinitions.Value);
|
||||
var mapFiles = FieldLoader.GetValue<string[]>("value", ruleDefinitions.Value);
|
||||
foreach (var f in mapFiles)
|
||||
CheckActors(MiniYaml.FromStream(map.Open(f), f), emitError, modData);
|
||||
CheckActors(MiniYaml.FromStream(fileSystem.Open(f), f), emitError, modData);
|
||||
|
||||
if (map.RuleDefinitions.Nodes.Any())
|
||||
CheckActors(map.RuleDefinitions.Nodes, emitError, modData);
|
||||
}
|
||||
if (ruleDefinitions.Nodes.Any())
|
||||
CheckActors(ruleDefinitions.Nodes, emitError, modData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckUnknownWeaponFields : ILintPass, ILintMapPass
|
||||
class CheckUnknownWeaponFields : ILintPass, ILintMapPass, ILintServerMapPass
|
||||
{
|
||||
void ILintPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData)
|
||||
{
|
||||
foreach (var f in modData.Manifest.Weapons)
|
||||
CheckWeapons(MiniYaml.FromStream(modData.DefaultFileSystem.Open(f), f), emitError, emitWarning, modData);
|
||||
}
|
||||
|
||||
void ILintMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
CheckMapYaml(emitError, emitWarning, modData, map, map.WeaponDefinitions);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
CheckMapYaml(emitError, emitWarning, modData, map, map.WeaponDefinitions);
|
||||
}
|
||||
|
||||
string NormalizeName(string key)
|
||||
{
|
||||
var name = key.Split('@')[0];
|
||||
@@ -81,23 +99,17 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
void ILintPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData)
|
||||
void CheckMapYaml(Action<string> emitError, Action<string> emitWarning, ModData modData, IReadOnlyFileSystem fileSystem, MiniYaml weaponDefinitions)
|
||||
{
|
||||
foreach (var f in modData.Manifest.Weapons)
|
||||
CheckWeapons(MiniYaml.FromStream(modData.DefaultFileSystem.Open(f), f), emitError, emitWarning, modData);
|
||||
}
|
||||
if (weaponDefinitions == null)
|
||||
return;
|
||||
|
||||
void ILintMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
if (map.WeaponDefinitions != null && map.WeaponDefinitions.Value != null)
|
||||
{
|
||||
var mapFiles = FieldLoader.GetValue<string[]>("value", map.WeaponDefinitions.Value);
|
||||
var mapFiles = FieldLoader.GetValue<string[]>("value", weaponDefinitions.Value);
|
||||
foreach (var f in mapFiles)
|
||||
CheckWeapons(MiniYaml.FromStream(map.Open(f), f), emitError, emitWarning, modData);
|
||||
CheckWeapons(MiniYaml.FromStream(fileSystem.Open(f), f), emitError, emitWarning, modData);
|
||||
|
||||
if (map.WeaponDefinitions.Nodes.Any())
|
||||
CheckWeapons(map.WeaponDefinitions.Nodes, emitError, emitWarning, modData);
|
||||
}
|
||||
if (weaponDefinitions.Nodes.Any())
|
||||
CheckWeapons(weaponDefinitions.Nodes, emitError, emitWarning, modData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,24 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckVoiceReferences : ILintRulesPass
|
||||
public class CheckVoiceReferences : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
|
||||
@@ -12,12 +12,23 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class LintBuildablePrerequisites : ILintRulesPass
|
||||
class LintBuildablePrerequisites : ILintRulesPass, ILintServerMapPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
|
||||
{
|
||||
Run(emitError, rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
Run(emitError, mapRules);
|
||||
}
|
||||
|
||||
void Run(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
var providedPrereqs = rules.Actors.SelectMany(a => a.Value.TraitInfos<ITechTreePrerequisiteInfo>().SelectMany(p => p.Prerequisites(a.Value)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user