Reorganize PlayerReference loading to enable upgrade rules for them.

The PlayerReference definitions are now stored
as raw MiniYamlNodes in the map.
This commit is contained in:
penev92
2015-04-19 19:55:33 +03:00
parent fe8b3d91b1
commit 2402b56da7
17 changed files with 181 additions and 117 deletions

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;
@@ -218,12 +217,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>();
@@ -233,6 +229,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;
@@ -342,13 +339,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>();
@@ -381,10 +371,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;
@@ -490,8 +481,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()));
@@ -762,45 +752,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();

View 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();
}
}
}

View File

@@ -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)

View File

@@ -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" />

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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));
} }

View File

@@ -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))
{ {

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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]);
} }
} }

View File

@@ -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);
} }
} }

View File

@@ -1269,5 +1269,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);
}
} }
} }

View File

@@ -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;
} }