Merge pull request #7875 from penev92/bleed_exposePlayerReferences
Add upgrade rules support for map PlayerReferences
This commit is contained in:
@@ -126,8 +126,11 @@ namespace OpenRA.Editor
|
|||||||
|
|
||||||
// upgrade maps that have no player definitions. editor doesnt care,
|
// upgrade maps that have no player definitions. editor doesnt care,
|
||||||
// but this breaks the game pretty badly.
|
// but this breaks the game pretty badly.
|
||||||
if (map.Players.Count == 0)
|
if (map.PlayerDefinitions.Count == 0)
|
||||||
map.MakeDefaultPlayers();
|
{
|
||||||
|
var players = new MapPlayers(map.Rules, map.GetSpawnPoints().Length);
|
||||||
|
map.PlayerDefinitions = players.ToMiniYaml();
|
||||||
|
}
|
||||||
|
|
||||||
PrepareMapResources(Game.ModData, map);
|
PrepareMapResources(Game.ModData, map);
|
||||||
|
|
||||||
@@ -315,7 +318,7 @@ namespace OpenRA.Editor
|
|||||||
void PopulateActorOwnerChooser()
|
void PopulateActorOwnerChooser()
|
||||||
{
|
{
|
||||||
actorOwnerChooser.Items.Clear();
|
actorOwnerChooser.Items.Clear();
|
||||||
actorOwnerChooser.Items.AddRange(surface1.Map.Players.Values.ToArray());
|
actorOwnerChooser.Items.AddRange(new MapPlayers(surface1.Map.PlayerDefinitions).Players.Values.ToArray());
|
||||||
actorOwnerChooser.SelectedIndex = 0;
|
actorOwnerChooser.SelectedIndex = 0;
|
||||||
surface1.NewActorOwner = ((PlayerReference)actorOwnerChooser.SelectedItem).Name;
|
surface1.NewActorOwner = ((PlayerReference)actorOwnerChooser.SelectedItem).Name;
|
||||||
}
|
}
|
||||||
@@ -412,8 +415,9 @@ namespace OpenRA.Editor
|
|||||||
map.ResizeCordon((int)nmd.CordonLeft.Value, (int)nmd.CordonTop.Value,
|
map.ResizeCordon((int)nmd.CordonLeft.Value, (int)nmd.CordonTop.Value,
|
||||||
(int)nmd.CordonRight.Value, (int)nmd.CordonBottom.Value);
|
(int)nmd.CordonRight.Value, (int)nmd.CordonBottom.Value);
|
||||||
|
|
||||||
map.Players.Clear();
|
var players = new MapPlayers(map.Rules, map.GetSpawnPoints().Length);
|
||||||
map.MakeDefaultPlayers();
|
map.PlayerDefinitions = players.ToMiniYaml();
|
||||||
|
|
||||||
map.FixOpenAreas(Program.Rules);
|
map.FixOpenAreas(Program.Rules);
|
||||||
|
|
||||||
NewMap(map);
|
NewMap(map);
|
||||||
@@ -502,8 +506,8 @@ namespace OpenRA.Editor
|
|||||||
void SetupDefaultPlayers(object sender, EventArgs e)
|
void SetupDefaultPlayers(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
dirty = true;
|
dirty = true;
|
||||||
surface1.Map.Players.Clear();
|
var players = new MapPlayers(surface1.Map.Rules, surface1.Map.GetSpawnPoints().Length);
|
||||||
surface1.Map.MakeDefaultPlayers();
|
surface1.Map.PlayerDefinitions = players.ToMiniYaml();
|
||||||
|
|
||||||
surface1.Chunks.Clear();
|
surface1.Chunks.Clear();
|
||||||
surface1.Invalidate();
|
surface1.Invalidate();
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ namespace OpenRA.Editor
|
|||||||
|
|
||||||
ColorPalette GetPaletteForPlayerInner(string name)
|
ColorPalette GetPaletteForPlayerInner(string name)
|
||||||
{
|
{
|
||||||
var pr = Map.Players[name];
|
var pr = new MapPlayers(Map.PlayerDefinitions).Players[name];
|
||||||
var pcpi = Program.Rules.Actors["player"].Traits.Get<PlayerColorPaletteInfo>();
|
var pcpi = Program.Rules.Actors["player"].Traits.Get<PlayerColorPaletteInfo>();
|
||||||
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp);
|
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp);
|
||||||
return new ImmutablePalette(PlayerPalette, remap).AsSystemPalette();
|
return new ImmutablePalette(PlayerPalette, remap).AsSystemPalette();
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
@@ -224,12 +223,9 @@ namespace OpenRA
|
|||||||
|
|
||||||
[FieldLoader.Ignore] public Lazy<Dictionary<string, ActorReference>> Actors;
|
[FieldLoader.Ignore] public Lazy<Dictionary<string, ActorReference>> Actors;
|
||||||
|
|
||||||
public int PlayerCount { get { return Players.Count(p => p.Value.Playable); } }
|
|
||||||
|
|
||||||
public Rectangle Bounds;
|
public Rectangle Bounds;
|
||||||
|
|
||||||
// Yaml map data
|
// Yaml map data
|
||||||
[FieldLoader.Ignore] public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
|
|
||||||
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
|
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
|
||||||
|
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> RuleDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore] public List<MiniYamlNode> RuleDefinitions = new List<MiniYamlNode>();
|
||||||
@@ -239,6 +235,7 @@ namespace OpenRA
|
|||||||
[FieldLoader.Ignore] public List<MiniYamlNode> VoiceDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore] public List<MiniYamlNode> VoiceDefinitions = new List<MiniYamlNode>();
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> NotificationDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore] public List<MiniYamlNode> NotificationDefinitions = new List<MiniYamlNode>();
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
|
||||||
|
[FieldLoader.Ignore] public List<MiniYamlNode> PlayerDefinitions = new List<MiniYamlNode>();
|
||||||
|
|
||||||
// Binary map data
|
// Binary map data
|
||||||
[FieldLoader.Ignore] public byte TileFormat = 2;
|
[FieldLoader.Ignore] public byte TileFormat = 2;
|
||||||
@@ -348,13 +345,6 @@ namespace OpenRA
|
|||||||
Visibility = MapVisibility.MissionSelector;
|
Visibility = MapVisibility.MissionSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load players
|
|
||||||
foreach (var my in nd["Players"].ToDictionary().Values)
|
|
||||||
{
|
|
||||||
var player = new PlayerReference(my);
|
|
||||||
Players.Add(player.Name, player);
|
|
||||||
}
|
|
||||||
|
|
||||||
Actors = Exts.Lazy(() =>
|
Actors = Exts.Lazy(() =>
|
||||||
{
|
{
|
||||||
var ret = new Dictionary<string, ActorReference>();
|
var ret = new Dictionary<string, ActorReference>();
|
||||||
@@ -387,10 +377,11 @@ namespace OpenRA
|
|||||||
VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices");
|
VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices");
|
||||||
NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
|
NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
|
||||||
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
|
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
|
||||||
|
PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players");
|
||||||
|
|
||||||
MapTiles = Exts.Lazy(() => LoadMapTiles());
|
MapTiles = Exts.Lazy(LoadMapTiles);
|
||||||
MapResources = Exts.Lazy(() => LoadResourceTiles());
|
MapResources = Exts.Lazy(LoadResourceTiles);
|
||||||
MapHeight = Exts.Lazy(() => LoadMapHeight());
|
MapHeight = Exts.Lazy(LoadMapHeight);
|
||||||
|
|
||||||
TileShape = Game.ModData.Manifest.TileShape;
|
TileShape = Game.ModData.Manifest.TileShape;
|
||||||
SubCellOffsets = Game.ModData.Manifest.SubCellOffsets;
|
SubCellOffsets = Game.ModData.Manifest.SubCellOffsets;
|
||||||
@@ -496,8 +487,7 @@ namespace OpenRA
|
|||||||
|
|
||||||
root.Add(new MiniYamlNode("Options", FieldSaver.SaveDifferences(Options, new MapOptions())));
|
root.Add(new MiniYamlNode("Options", FieldSaver.SaveDifferences(Options, new MapOptions())));
|
||||||
|
|
||||||
root.Add(new MiniYamlNode("Players", null,
|
root.Add(new MiniYamlNode("Players", null, PlayerDefinitions));
|
||||||
Players.Select(p => new MiniYamlNode("PlayerReference@{0}".F(p.Key), FieldSaver.SaveDifferences(p.Value, new PlayerReference()))).ToList()));
|
|
||||||
|
|
||||||
root.Add(new MiniYamlNode("Actors", null,
|
root.Add(new MiniYamlNode("Actors", null,
|
||||||
Actors.Value.Select(x => new MiniYamlNode(x.Key, x.Value.Save())).ToList()));
|
Actors.Value.Select(x => new MiniYamlNode(x.Key, x.Value.Save())).ToList()));
|
||||||
@@ -768,45 +758,6 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MakeDefaultPlayers()
|
|
||||||
{
|
|
||||||
var firstRace = Rules.Actors["world"].Traits
|
|
||||||
.WithInterface<CountryInfo>().First(c => c.Selectable).Race;
|
|
||||||
|
|
||||||
if (!Players.ContainsKey("Neutral"))
|
|
||||||
Players.Add("Neutral", new PlayerReference
|
|
||||||
{
|
|
||||||
Name = "Neutral",
|
|
||||||
Race = firstRace,
|
|
||||||
OwnsWorld = true,
|
|
||||||
NonCombatant = true
|
|
||||||
});
|
|
||||||
|
|
||||||
var numSpawns = GetSpawnPoints().Length;
|
|
||||||
for (var index = 0; index < numSpawns; index++)
|
|
||||||
{
|
|
||||||
if (Players.ContainsKey("Multi{0}".F(index)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var p = new PlayerReference
|
|
||||||
{
|
|
||||||
Name = "Multi{0}".F(index),
|
|
||||||
Race = "Random",
|
|
||||||
Playable = true,
|
|
||||||
Enemies = new[] { "Creeps" }
|
|
||||||
};
|
|
||||||
Players.Add(p.Name, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
Players.Add("Creeps", new PlayerReference
|
|
||||||
{
|
|
||||||
Name = "Creeps",
|
|
||||||
Race = firstRace,
|
|
||||||
NonCombatant = true,
|
|
||||||
Enemies = Players.Where(p => p.Value.Playable).Select(p => p.Key).ToArray()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FixOpenAreas(Ruleset rules)
|
public void FixOpenAreas(Ruleset rules)
|
||||||
{
|
{
|
||||||
var r = new Random();
|
var r = new Random();
|
||||||
|
|||||||
75
OpenRA.Game/Map/MapPlayers.cs
Normal file
75
OpenRA.Game/Map/MapPlayers.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 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. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public class MapPlayers
|
||||||
|
{
|
||||||
|
public readonly Dictionary<string, PlayerReference> Players;
|
||||||
|
|
||||||
|
public MapPlayers() : this(new List<MiniYamlNode>()) { }
|
||||||
|
|
||||||
|
public MapPlayers(IEnumerable<MiniYamlNode> playerDefinitions)
|
||||||
|
{
|
||||||
|
Players = playerDefinitions.Select(pr => new PlayerReference(new MiniYaml(pr.Key, pr.Value.Nodes)))
|
||||||
|
.ToDictionary(player => player.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapPlayers(Ruleset rules, int playerCount)
|
||||||
|
{
|
||||||
|
var firstRace = rules.Actors["world"].Traits
|
||||||
|
.WithInterface<CountryInfo>().First(c => c.Selectable).Race;
|
||||||
|
|
||||||
|
Players = new Dictionary<string, PlayerReference>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"Neutral", new PlayerReference
|
||||||
|
{
|
||||||
|
Name = "Neutral",
|
||||||
|
Race = firstRace,
|
||||||
|
OwnsWorld = true,
|
||||||
|
NonCombatant = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Creeps", new PlayerReference
|
||||||
|
{
|
||||||
|
Name = "Creeps",
|
||||||
|
Race = firstRace,
|
||||||
|
NonCombatant = true,
|
||||||
|
Enemies = Exts.MakeArray(playerCount, i => "Multi{0}".F(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var index = 0; index < playerCount; index++)
|
||||||
|
{
|
||||||
|
var p = new PlayerReference
|
||||||
|
{
|
||||||
|
Name = "Multi{0}".F(index),
|
||||||
|
Race = "Random",
|
||||||
|
Playable = true,
|
||||||
|
Enemies = new[] { "Creeps" }
|
||||||
|
};
|
||||||
|
Players.Add(p.Name, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MiniYamlNode> ToMiniYaml()
|
||||||
|
{
|
||||||
|
return Players.Select(p => new MiniYamlNode("PlayerReference@{0}".F(p.Key),
|
||||||
|
FieldSaver.SaveDifferences(p.Value, new PlayerReference()))).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,6 +67,7 @@ namespace OpenRA
|
|||||||
public Map Map { get; private set; }
|
public Map Map { get; private set; }
|
||||||
public MapStatus Status { get; private set; }
|
public MapStatus Status { get; private set; }
|
||||||
public MapClassification Class { get; private set; }
|
public MapClassification Class { get; private set; }
|
||||||
|
public bool SuitableForInitialMap { get; private set; }
|
||||||
|
|
||||||
public MapRuleStatus RuleStatus { get; private set; }
|
public MapRuleStatus RuleStatus { get; private set; }
|
||||||
|
|
||||||
@@ -117,12 +118,36 @@ namespace OpenRA
|
|||||||
Type = m.Type;
|
Type = m.Type;
|
||||||
Type = m.Type;
|
Type = m.Type;
|
||||||
Author = m.Author;
|
Author = m.Author;
|
||||||
PlayerCount = m.Players.Count(x => x.Value.Playable);
|
|
||||||
Bounds = m.Bounds;
|
Bounds = m.Bounds;
|
||||||
SpawnPoints = m.GetSpawnPoints();
|
SpawnPoints = m.GetSpawnPoints();
|
||||||
CustomPreview = m.CustomPreview;
|
CustomPreview = m.CustomPreview;
|
||||||
Status = MapStatus.Available;
|
Status = MapStatus.Available;
|
||||||
Class = classification;
|
Class = classification;
|
||||||
|
|
||||||
|
var players = new MapPlayers(m.PlayerDefinitions).Players;
|
||||||
|
PlayerCount = players.Count(x => x.Value.Playable);
|
||||||
|
|
||||||
|
SuitableForInitialMap = EvaluateUserFriendliness(players);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EvaluateUserFriendliness(Dictionary<string, PlayerReference> players)
|
||||||
|
{
|
||||||
|
if (Status != MapStatus.Available || !Map.Visibility.HasFlag(MapVisibility.Lobby))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Other map types may have confusing settings or gameplay
|
||||||
|
if (Type != "Conquest")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Maps with bots disabled confuse new players
|
||||||
|
if (players.Any(x => !x.Value.AllowBots))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Large maps expose unfortunate performance problems
|
||||||
|
if (Bounds.Width > 128 || Bounds.Height > 128)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml)
|
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml)
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
<Compile Include="LogProxy.cs" />
|
<Compile Include="LogProxy.cs" />
|
||||||
<Compile Include="FileFormats\IdxReader.cs" />
|
<Compile Include="FileFormats\IdxReader.cs" />
|
||||||
<Compile Include="FileSystem\BagFile.cs" />
|
<Compile Include="FileSystem\BagFile.cs" />
|
||||||
|
<Compile Include="Map\MapPlayers.cs" />
|
||||||
<Compile Include="MPos.cs" />
|
<Compile Include="MPos.cs" />
|
||||||
<Compile Include="GameRules\Warhead.cs" />
|
<Compile Include="GameRules\Warhead.cs" />
|
||||||
<Compile Include="Graphics\QuadRenderer.cs" />
|
<Compile Include="Graphics\QuadRenderer.cs" />
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ namespace OpenRA.Server
|
|||||||
|
|
||||||
public ServerSettings Settings;
|
public ServerSettings Settings;
|
||||||
public ModData ModData;
|
public ModData ModData;
|
||||||
|
|
||||||
|
// Managed by LobbyCommands
|
||||||
public Map Map;
|
public Map Map;
|
||||||
|
public MapPlayers MapPlayers;
|
||||||
XTimer gameTimeout;
|
XTimer gameTimeout;
|
||||||
|
|
||||||
public static void SyncClientToPlayerReference(Session.Client c, PlayerReference pr)
|
public static void SyncClientToPlayerReference(Session.Client c, PlayerReference pr)
|
||||||
@@ -304,7 +307,7 @@ namespace OpenRA.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (client.Slot != null)
|
if (client.Slot != null)
|
||||||
SyncClientToPlayerReference(client, Map.Players[client.Slot]);
|
SyncClientToPlayerReference(client, MapPlayers.Players[client.Slot]);
|
||||||
else
|
else
|
||||||
client.Color = HSLColor.FromRGB(255, 255, 255);
|
client.Color = HSLColor.FromRGB(255, 255, 255);
|
||||||
|
|
||||||
|
|||||||
@@ -233,27 +233,7 @@ namespace OpenRA.Widgets
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(initialUid) || Game.ModData.MapCache[initialUid].Status != MapStatus.Available)
|
if (string.IsNullOrEmpty(initialUid) || Game.ModData.MapCache[initialUid].Status != MapStatus.Available)
|
||||||
{
|
{
|
||||||
Func<MapPreview, bool> isIdealMap = m =>
|
var selected = Game.ModData.MapCache.Where(x => x.SuitableForInitialMap).RandomOrDefault(Game.CosmeticRandom) ??
|
||||||
{
|
|
||||||
if (m.Status != MapStatus.Available || !m.Map.Visibility.HasFlag(MapVisibility.Lobby))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Other map types may have confusing settings or gameplay
|
|
||||||
if (m.Type != "Conquest")
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Maps with bots disabled confuse new players
|
|
||||||
if (m.Map.Players.Any(s => !s.Value.AllowBots))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Large maps expose unfortunate performance problems
|
|
||||||
if (m.Bounds.Width > 128 || m.Bounds.Height > 128)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var selected = Game.ModData.MapCache.Where(m => isIdealMap(m)).RandomOrDefault(Game.CosmeticRandom) ??
|
|
||||||
Game.ModData.MapCache.First(m => m.Status == MapStatus.Available && m.Map.Visibility.HasFlag(MapVisibility.Lobby));
|
Game.ModData.MapCache.First(m => m.Status == MapStatus.Available && m.Map.Visibility.HasFlag(MapVisibility.Lobby));
|
||||||
return selected.Uid;
|
return selected.Uid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,19 +18,21 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
{
|
{
|
||||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||||
{
|
{
|
||||||
var playerNames = map.Players.Values.Select(p => p.Name);
|
var players = new MapPlayers(map.PlayerDefinitions).Players;
|
||||||
foreach (var player in map.Players)
|
|
||||||
|
var playerNames = players.Values.Select(p => p.Name);
|
||||||
|
foreach (var player in players)
|
||||||
foreach (var ally in player.Value.Allies)
|
foreach (var ally in player.Value.Allies)
|
||||||
if (!playerNames.Contains(ally))
|
if (!playerNames.Contains(ally))
|
||||||
emitError("Allies contains player {0} that is not in list.".F(ally));
|
emitError("Allies contains player {0} that is not in list.".F(ally));
|
||||||
|
|
||||||
foreach (var player in map.Players)
|
foreach (var player in players)
|
||||||
foreach (var enemy in player.Value.Enemies)
|
foreach (var enemy in player.Value.Enemies)
|
||||||
if (!playerNames.Contains(enemy))
|
if (!playerNames.Contains(enemy))
|
||||||
emitError("Enemies contains player {0} that is not in list.".F(enemy));
|
emitError("Enemies contains player {0} that is not in list.".F(enemy));
|
||||||
|
|
||||||
var races = map.Rules.Actors["world"].Traits.WithInterface<CountryInfo>().Select(c => c.Race);
|
var races = map.Rules.Actors["world"].Traits.WithInterface<CountryInfo>().Select(c => c.Race);
|
||||||
foreach (var player in map.Players)
|
foreach (var player in players)
|
||||||
if (!string.IsNullOrWhiteSpace(player.Value.Race) && player.Value.Race != "Random" && !races.Contains(player.Value.Race))
|
if (!string.IsNullOrWhiteSpace(player.Value.Race) && player.Value.Race != "Random" && !races.Contains(player.Value.Race))
|
||||||
emitError("Invalid race {0} chosen for player {1}.".F(player.Value.Race, player.Value.Name));
|
emitError("Invalid race {0} chosen for player {1}.".F(player.Value.Race, player.Value.Name));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,8 +175,7 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapPlayerColors = server.Map.Players.Values
|
var mapPlayerColors = server.MapPlayers.Players.Values.Select(p => p.ColorRamp.RGB);
|
||||||
.Select(p => p.ColorRamp.RGB);
|
|
||||||
|
|
||||||
if (!ValidateColorAgainstForbidden(askedColor, mapPlayerColors, out forbiddenColor))
|
if (!ValidateColorAgainstForbidden(askedColor, mapPlayerColors, out forbiddenColor))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
client.Slot = s;
|
client.Slot = s;
|
||||||
S.SyncClientToPlayerReference(client, server.Map.Players[s]);
|
S.SyncClientToPlayerReference(client, server.MapPlayers.Players[s]);
|
||||||
server.SyncLobbyClients();
|
server.SyncLobbyClients();
|
||||||
CheckAutoStart(server);
|
CheckAutoStart(server);
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
bot.Bot = botType;
|
bot.Bot = botType;
|
||||||
}
|
}
|
||||||
|
|
||||||
S.SyncClientToPlayerReference(bot, server.Map.Players[parts[0]]);
|
S.SyncClientToPlayerReference(bot, server.MapPlayers.Players[parts[0]]);
|
||||||
server.SyncLobbyClients();
|
server.SyncLobbyClients();
|
||||||
server.SyncLobbySlots();
|
server.SyncLobbySlots();
|
||||||
return true;
|
return true;
|
||||||
@@ -346,9 +346,9 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
if (c.Slot != null)
|
if (c.Slot != null)
|
||||||
{
|
{
|
||||||
// Remove Bot from slot if slot forbids bots
|
// Remove Bot from slot if slot forbids bots
|
||||||
if (c.Bot != null && !server.Map.Players[c.Slot].AllowBots)
|
if (c.Bot != null && !server.MapPlayers.Players[c.Slot].AllowBots)
|
||||||
server.LobbyInfo.Clients.Remove(c);
|
server.LobbyInfo.Clients.Remove(c);
|
||||||
S.SyncClientToPlayerReference(c, server.Map.Players[c.Slot]);
|
S.SyncClientToPlayerReference(c, server.MapPlayers.Players[c.Slot]);
|
||||||
}
|
}
|
||||||
else if (c.Bot != null)
|
else if (c.Bot != null)
|
||||||
server.LobbyInfo.Clients.Remove(c);
|
server.LobbyInfo.Clients.Remove(c);
|
||||||
@@ -477,13 +477,13 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
|
|
||||||
var maxTeams = (server.LobbyInfo.Clients.Count(c => c.Slot != null) + 1) / 2;
|
var maxTeams = (server.LobbyInfo.Clients.Count(c => c.Slot != null) + 1) / 2;
|
||||||
teamCount = teamCount.Clamp(0, maxTeams);
|
teamCount = teamCount.Clamp(0, maxTeams);
|
||||||
var players = server.LobbyInfo.Slots
|
var clients = server.LobbyInfo.Slots
|
||||||
.Select(slot => server.LobbyInfo.ClientInSlot(slot.Key))
|
.Select(slot => server.LobbyInfo.ClientInSlot(slot.Key))
|
||||||
.Where(c => c != null && !server.LobbyInfo.Slots[c.Slot].LockTeam);
|
.Where(c => c != null && !server.LobbyInfo.Slots[c.Slot].LockTeam);
|
||||||
|
|
||||||
var assigned = 0;
|
var assigned = 0;
|
||||||
var playerCount = players.Count();
|
var clientCount = clients.Count();
|
||||||
foreach (var player in players)
|
foreach (var player in clients)
|
||||||
{
|
{
|
||||||
// Free for all
|
// Free for all
|
||||||
if (teamCount == 0)
|
if (teamCount == 0)
|
||||||
@@ -493,7 +493,7 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
else if (teamCount == 1)
|
else if (teamCount == 1)
|
||||||
player.Team = player.Bot == null ? 1 : 2;
|
player.Team = player.Bot == null ? 1 : 2;
|
||||||
else
|
else
|
||||||
player.Team = assigned++ * teamCount / playerCount + 1;
|
player.Team = assigned++ * teamCount / clientCount + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
server.SyncLobbyClients();
|
server.SyncLobbyClients();
|
||||||
@@ -897,7 +897,9 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
static void LoadMap(S server)
|
static void LoadMap(S server)
|
||||||
{
|
{
|
||||||
server.Map = server.ModData.MapCache[server.LobbyInfo.GlobalSettings.Map].Map;
|
server.Map = server.ModData.MapCache[server.LobbyInfo.GlobalSettings.Map].Map;
|
||||||
server.LobbyInfo.Slots = server.Map.Players
|
|
||||||
|
server.MapPlayers = new MapPlayers(server.Map.PlayerDefinitions);
|
||||||
|
server.LobbyInfo.Slots = server.MapPlayers.Players
|
||||||
.Select(p => MakeSlotFromPlayerReference(p.Value))
|
.Select(p => MakeSlotFromPlayerReference(p.Value))
|
||||||
.Where(s => s != null)
|
.Where(s => s != null)
|
||||||
.ToDictionary(s => s.PlayerReference, s => s);
|
.ToDictionary(s => s.PlayerReference, s => s);
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
public void CreatePlayers(World w)
|
public void CreatePlayers(World w)
|
||||||
{
|
{
|
||||||
// create the unplayable map players -- neutral, shellmap, scripted, etc.
|
var players = new MapPlayers(w.Map.PlayerDefinitions).Players;
|
||||||
foreach (var kv in w.Map.Players.Where(p => !p.Value.Playable))
|
|
||||||
|
// Create the unplayable map players -- neutral, shellmap, scripted, etc.
|
||||||
|
foreach (var kv in players.Where(p => !p.Value.Playable))
|
||||||
{
|
{
|
||||||
var player = new Player(w, null, null, kv.Value);
|
var player = new Player(w, null, null, kv.Value);
|
||||||
w.AddPlayer(player);
|
w.AddPlayer(player);
|
||||||
@@ -30,14 +32,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
w.WorldActor.Owner = player;
|
w.WorldActor.Owner = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the players which are bound through slots.
|
// Create the players which are bound through slots.
|
||||||
foreach (var kv in w.LobbyInfo.Slots)
|
foreach (var kv in w.LobbyInfo.Slots)
|
||||||
{
|
{
|
||||||
var client = w.LobbyInfo.ClientInSlot(kv.Key);
|
var client = w.LobbyInfo.ClientInSlot(kv.Key);
|
||||||
if (client == null)
|
if (client == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var player = new Player(w, client, kv.Value, w.Map.Players[kv.Value.PlayerReference]);
|
var player = new Player(w, client, kv.Value, players[kv.Value.PlayerReference]);
|
||||||
w.AddPlayer(player);
|
w.AddPlayer(player);
|
||||||
|
|
||||||
if (client.Index == Game.LocalClientId)
|
if (client.Index == Game.LocalClientId)
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
Ruleset rules;
|
Ruleset rules;
|
||||||
List<string> players = new List<string>();
|
List<string> players = new List<string>();
|
||||||
Action<string> errorHandler;
|
Action<string> errorHandler;
|
||||||
|
MapPlayers mapPlayers;
|
||||||
|
|
||||||
LegacyMapImporter(string filename, Ruleset rules, Action<string> errorHandler)
|
LegacyMapImporter(string filename, Ruleset rules, Action<string> errorHandler)
|
||||||
{
|
{
|
||||||
@@ -123,7 +124,6 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
{
|
{
|
||||||
var map = new LegacyMapImporter(filename, rules, errorHandler).map;
|
var map = new LegacyMapImporter(filename, rules, errorHandler).map;
|
||||||
map.RequiresMod = mod;
|
map.RequiresMod = mod;
|
||||||
map.MakeDefaultPlayers();
|
|
||||||
map.FixOpenAreas(rules);
|
map.FixOpenAreas(rules);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@@ -180,9 +180,6 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
LoadActors(file, "INFANTRY");
|
LoadActors(file, "INFANTRY");
|
||||||
LoadSmudges(file, "SMUDGE");
|
LoadSmudges(file, "SMUDGE");
|
||||||
|
|
||||||
foreach (var p in players)
|
|
||||||
LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert);
|
|
||||||
|
|
||||||
var wps = file.GetSection("Waypoints")
|
var wps = file.GetSection("Waypoints")
|
||||||
.Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0)
|
.Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0)
|
||||||
.Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key),
|
.Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key),
|
||||||
@@ -193,19 +190,29 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
{
|
{
|
||||||
if (kv.First <= 7)
|
if (kv.First <= 7)
|
||||||
{
|
{
|
||||||
var a = new ActorReference("mpspawn");
|
var a = new ActorReference("mpspawn")
|
||||||
a.Add(new LocationInit((CPos)kv.Second));
|
{
|
||||||
a.Add(new OwnerInit("Neutral"));
|
new LocationInit((CPos)kv.Second),
|
||||||
|
new OwnerInit("Neutral")
|
||||||
|
};
|
||||||
map.Actors.Value.Add("Actor" + map.Actors.Value.Count.ToString(), a);
|
map.Actors.Value.Add("Actor" + map.Actors.Value.Count.ToString(), a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var a = new ActorReference("waypoint");
|
var a = new ActorReference("waypoint")
|
||||||
a.Add(new LocationInit((CPos)kv.Second));
|
{
|
||||||
a.Add(new OwnerInit("Neutral"));
|
new LocationInit((CPos)kv.Second),
|
||||||
|
new OwnerInit("Neutral")
|
||||||
|
};
|
||||||
map.Actors.Value.Add("waypoint" + kv.First, a);
|
map.Actors.Value.Add("waypoint" + kv.First, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create default player definitions only if there are no players to import
|
||||||
|
mapPlayers = new MapPlayers(map.Rules, (players.Count == 0) ? map.GetSpawnPoints().Length : 0);
|
||||||
|
foreach (var p in players)
|
||||||
|
LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert);
|
||||||
|
map.PlayerDefinitions = mapPlayers.ToMiniYaml();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int2 LocationFromMapOffset(int offset, int mapSize)
|
static int2 LocationFromMapOffset(int offset, int mapSize)
|
||||||
@@ -505,7 +512,11 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map.Players.Add(section, pr);
|
// Overwrite default player definitions if needed
|
||||||
|
if (!mapPlayers.Players.ContainsKey(section))
|
||||||
|
mapPlayers.Players.Add(section, pr);
|
||||||
|
else
|
||||||
|
mapPlayers.Players[section] = pr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadVideos(IniFile file, string section)
|
void LoadVideos(IniFile file, string section)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
|
|
||||||
UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0);
|
UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0);
|
||||||
UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0);
|
UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0);
|
||||||
|
UpgradeRules.UpgradePlayers(engineDate, ref map.PlayerDefinitions, null, 0);
|
||||||
map.Save(args[1]);
|
map.Save(args[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
Console.WriteLine("\t" + map.Path);
|
Console.WriteLine("\t" + map.Path);
|
||||||
UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0);
|
UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0);
|
||||||
UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0);
|
UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0);
|
||||||
|
UpgradeRules.UpgradePlayers(engineDate, ref map.PlayerDefinitions, null, 0);
|
||||||
map.Save(map.Path);
|
map.Save(map.Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1339,5 +1339,11 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
UpgradeCursors(engineVersion, ref node.Value.Nodes, node, depth + 1);
|
UpgradeCursors(engineVersion, ref node.Value.Nodes, node, depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void UpgradePlayers(int engineVersion, ref List<MiniYamlNode> nodes, MiniYamlNode parent, int depth)
|
||||||
|
{
|
||||||
|
foreach (var node in nodes)
|
||||||
|
UpgradePlayers(engineVersion, ref node.Value.Nodes, node, depth + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,7 +297,8 @@ namespace OpenRA.Mods.D2k.UtilityCommands
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
map.RequiresMod = mod;
|
map.RequiresMod = mod;
|
||||||
map.MakeDefaultPlayers();
|
var players = new MapPlayers(map.Rules, map.GetSpawnPoints().Length);
|
||||||
|
map.PlayerDefinitions = players.ToMiniYaml();
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user