Reorganize actor and smudge loading.

The actor and smudge definitions are now stored
as raw MiniYamlNodes in the map.  It is now the
responsibility of the consumers to parse these
into real objects.
This commit is contained in:
Paul Chote
2015-04-03 19:23:41 +01:00
parent ea679d4557
commit 4b1f541f34
14 changed files with 104 additions and 132 deletions

View File

@@ -26,12 +26,12 @@ namespace OpenRA.Editor
public void Apply(Surface surface)
{
if (surface.Map.Actors.Value.Any(a => a.Value.Location() == surface.GetBrushLocation()))
if (surface.Actors.Any(a => a.Value.Location() == surface.GetBrushLocation()))
return;
var owner = surface.NewActorOwner;
var id = NextActorName(surface);
surface.Map.Actors.Value[id] = new ActorReference(actorTemplate.Info.Name.ToLowerInvariant())
surface.Actors[id] = new ActorReference(actorTemplate.Info.Name.ToLowerInvariant())
{
new LocationInit(surface.GetBrushLocation()),
new OwnerInit(owner)
@@ -44,7 +44,7 @@ namespace OpenRA.Editor
for (;;)
{
var possible = "Actor{0}".F(id++);
if (!surface.Map.Actors.Value.ContainsKey(possible)) return possible;
if (!surface.Actors.ContainsKey(possible)) return possible;
}
}
}

View File

@@ -128,7 +128,7 @@ namespace OpenRA.Editor
// but this breaks the game pretty badly.
if (map.PlayerDefinitions.Count == 0)
{
var players = new MapPlayers(map.Rules, map.GetSpawnPoints().Length);
var players = new MapPlayers(map.Rules, map.SpawnPoints.Value.Length);
map.PlayerDefinitions = players.ToMiniYaml();
}
@@ -415,7 +415,7 @@ namespace OpenRA.Editor
map.ResizeCordon((int)nmd.CordonLeft.Value, (int)nmd.CordonTop.Value,
(int)nmd.CordonRight.Value, (int)nmd.CordonBottom.Value);
var players = new MapPlayers(map.Rules, map.GetSpawnPoints().Length);
var players = new MapPlayers(map.Rules, map.SpawnPoints.Value.Length);
map.PlayerDefinitions = players.ToMiniYaml();
map.FixOpenAreas(Program.Rules);
@@ -506,7 +506,7 @@ namespace OpenRA.Editor
void SetupDefaultPlayers(object sender, EventArgs e)
{
dirty = true;
var players = new MapPlayers(surface1.Map.Rules, surface1.Map.GetSpawnPoints().Length);
var players = new MapPlayers(surface1.Map.Rules, surface1.Map.SpawnPoints.Value.Length);
surface1.Map.PlayerDefinitions = players.ToMiniYaml();
surface1.Chunks.Clear();

View File

@@ -43,6 +43,7 @@ namespace OpenRA.Editor
class Surface : Control
{
public Map Map { get; private set; }
public Dictionary<string, ActorReference> Actors { get; private set; }
public TileSet TileSet { get; private set; }
public TileSetRenderer TileSetRenderer { get; private set; }
public IPalette Palette { get; private set; }
@@ -84,6 +85,9 @@ namespace OpenRA.Editor
public void Bind(Map m, TileSet ts, TileSetRenderer tsr, IPalette p, IPalette pp)
{
Map = m;
if (m != null)
Actors = m.ActorDefinitions.ToDictionary(n => n.Key, n => new ActorReference(n.Value.Value, n.Value.ToDictionary()));
TileSet = ts;
TileSetRenderer = tsr;
Palette = p;
@@ -132,7 +136,7 @@ namespace OpenRA.Editor
{
base.OnDoubleClick(e);
var x = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
var x = Actors.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
if (x.Key != null)
ActorDoubleClicked(x);
}
@@ -203,8 +207,8 @@ namespace OpenRA.Editor
currentTool = null;
var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == brushLocation);
if (key.Key != null) Map.Actors.Value.Remove(key.Key);
var key = Actors.FirstOrDefault(a => a.Value.Location() == brushLocation);
if (key.Key != null) Actors.Remove(key.Key);
if (Map.MapResources.Value[brushLocation].Type != 0)
{
@@ -456,7 +460,7 @@ namespace OpenRA.Editor
height * (TileSetRenderer.TileSize * Zoom));
}
foreach (var ar in Map.Actors.Value)
foreach (var ar in Actors)
{
if (actorTemplates.ContainsKey(ar.Value.Type))
DrawActor(e.Graphics, ar.Value.Location(), actorTemplates[ar.Value.Type],
@@ -466,7 +470,7 @@ namespace OpenRA.Editor
}
if (ShowActorNames)
foreach (var ar in Map.Actors.Value)
foreach (var ar in Actors)
if (!ar.Key.StartsWith("Actor")) // if it has a custom name
e.Graphics.DrawStringContrast(Font, ar.Key,
(int)(ar.Value.Location().X * TileSetRenderer.TileSize * Zoom + Offset.X),
@@ -500,7 +504,7 @@ namespace OpenRA.Editor
if (currentTool == null)
{
var x = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
var x = Actors.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
if (x.Key != null && actorTemplates.ContainsKey(x.Value.Type))
DrawActorBorder(e.Graphics, x.Value.Location(), actorTemplates[x.Value.Type]);
}

View File

@@ -221,13 +221,11 @@ namespace OpenRA
return videos;
}
[FieldLoader.Ignore] public Lazy<Dictionary<string, ActorReference>> Actors;
public Rectangle Bounds;
// Yaml map data
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
public Lazy<CPos[]> SpawnPoints;
// Yaml map data
[FieldLoader.Ignore] public List<MiniYamlNode> RuleDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> SequenceDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequenceDefinitions = new List<MiniYamlNode>();
@@ -237,6 +235,9 @@ namespace OpenRA
[FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> PlayerDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> ActorDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> SmudgeDefinitions = new List<MiniYamlNode>();
// Binary map data
[FieldLoader.Ignore] public byte TileFormat = 2;
@@ -294,8 +295,8 @@ namespace OpenRA
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size)),
MapTiles = makeMapTiles,
MapHeight = makeMapHeight,
Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()),
Smudges = Exts.Lazy(() => new List<SmudgeReference>())
SpawnPoints = Exts.Lazy(() => new CPos[0])
};
map.PostInit();
@@ -345,29 +346,17 @@ namespace OpenRA
Visibility = MapVisibility.MissionSelector;
}
Actors = Exts.Lazy(() =>
SpawnPoints = Exts.Lazy(() =>
{
var ret = new Dictionary<string, ActorReference>();
foreach (var kv in nd["Actors"].ToDictionary())
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()));
return ret;
});
// Smudges
Smudges = Exts.Lazy(() =>
{
var ret = new List<SmudgeReference>();
foreach (var name in nd["Smudges"].ToDictionary().Keys)
var spawns = new List<CPos>();
foreach (var kv in ActorDefinitions.Where(d => d.Value.Value == "mpspawn"))
{
var vals = name.Split(' ');
var loc = vals[1].Split(',');
ret.Add(new SmudgeReference(vals[0], new int2(
Exts.ParseIntegerInvariant(loc[0]),
Exts.ParseIntegerInvariant(loc[1])),
Exts.ParseIntegerInvariant(vals[2])));
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
spawns.Add(s.InitDict.Get<LocationInit>().Value(null));
}
return ret;
return spawns.ToArray();
});
RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules");
@@ -379,6 +368,9 @@ namespace OpenRA
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players");
ActorDefinitions = MiniYaml.NodesOrEmpty(yaml, "Actors");
SmudgeDefinitions = MiniYaml.NodesOrEmpty(yaml, "Smudges");
MapTiles = Exts.Lazy(LoadMapTiles);
MapResources = Exts.Lazy(LoadResourceTiles);
MapHeight = Exts.Lazy(LoadMapHeight);
@@ -448,14 +440,6 @@ namespace OpenRA
return rules.Value;
}
public CPos[] GetSpawnPoints()
{
return Actors.Value.Values
.Where(a => a.Type == "mpspawn")
.Select(a => (CPos)a.InitDict.Get<LocationInit>().Value(null))
.ToArray();
}
public void Save(string toPath)
{
MapFormat = 7;
@@ -489,10 +473,8 @@ namespace OpenRA
root.Add(new MiniYamlNode("Players", null, PlayerDefinitions));
root.Add(new MiniYamlNode("Actors", null,
Actors.Value.Select(x => new MiniYamlNode(x.Key, x.Value.Save())).ToList()));
root.Add(new MiniYamlNode("Smudges", MiniYaml.FromList<SmudgeReference>(Smudges.Value)));
root.Add(new MiniYamlNode("Actors", null, ActorDefinitions));
root.Add(new MiniYamlNode("Smudges", null, SmudgeDefinitions));
root.Add(new MiniYamlNode("Rules", null, RuleDefinitions));
root.Add(new MiniYamlNode("Sequences", null, SequenceDefinitions));
root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequenceDefinitions));

View File

@@ -119,7 +119,7 @@ namespace OpenRA
Type = m.Type;
Author = m.Author;
Bounds = m.Bounds;
SpawnPoints = m.GetSpawnPoints();
SpawnPoints = m.SpawnPoints.Value;
CustomPreview = m.CustomPreview;
Status = MapStatus.Available;
Class = classification;

View File

@@ -1,31 +0,0 @@
#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
namespace OpenRA
{
public struct SmudgeReference
{
public readonly string Type;
public readonly int2 Location;
public readonly int Depth;
public SmudgeReference(string type, int2 location, int depth)
{
Type = type;
Location = location;
Depth = depth;
}
public override string ToString()
{
return "{0} {1},{2} {3}".F(Type, Location.X, Location.Y, Depth);
}
}
}

View File

@@ -249,7 +249,6 @@
<Compile Include="FileSystem\ZipFile.cs" />
<Compile Include="FileSystem\BigFile.cs" />
<Compile Include="Map\PlayerReference.cs" />
<Compile Include="Map\SmudgeReference.cs" />
<Compile Include="Map\TileReference.cs" />
<Compile Include="Map\TileSet.cs" />
<Compile Include="FieldLoader.cs" />

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
var actorTypes = map.Actors.Value.Values.Select(a => a.Type);
var actorTypes = map.ActorDefinitions.Select(a => a.Value.Value);
foreach (var actor in actorTypes)
if (!map.Rules.Actors.Keys.Contains(actor.ToLowerInvariant()))
emitError("Actor {0} is not defined by any rule.".F(actor));

View File

@@ -789,7 +789,7 @@ namespace OpenRA.Mods.Common.Server
int spawnPoint;
if (!Exts.TryParseIntegerInvariant(parts[1], out spawnPoint)
|| spawnPoint < 0 || spawnPoint > server.Map.GetSpawnPoints().Length)
|| spawnPoint < 0 || spawnPoint > server.Map.SpawnPoints.Value.Length)
{
Log.Write("server", "Invalid spawn point: {0}", parts[1]);
return true;

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
public void WorldLoaded(World world, WorldRenderer wr)
{
var spawns = world.Map.GetSpawnPoints();
var spawns = world.Map.SpawnPoints.Value;
var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0 && c.Slot != null)
.Select(c => spawns[c.SpawnPoint - 1]).ToList();
var available = spawns.Except(taken).ToList();

View File

@@ -72,16 +72,27 @@ namespace OpenRA.Mods.Common.Traits
}
// Add map smudges
foreach (var s in w.Map.Smudges.Value.Where(s => smudges.ContainsKey(s.Type)))
foreach (var s in w.Map.SmudgeDefinitions)
{
var name = s.Key;
var vals = name.Split(' ');
var type = vals[0];
if (!smudges.ContainsKey(type))
continue;
var loc = vals[1].Split(',');
var cell = new CPos(Exts.ParseIntegerInvariant(loc[0]), Exts.ParseIntegerInvariant(loc[1]));
var depth = Exts.ParseIntegerInvariant(vals[2]);
var smudge = new Smudge
{
Type = s.Type,
Depth = s.Depth,
Sprite = smudges[s.Type][s.Depth]
Type = type,
Depth = depth,
Sprite = smudges[type][depth]
};
tiles.Add((CPos)s.Location, smudge);
tiles.Add(cell, smudge);
}
}

View File

@@ -25,17 +25,19 @@ namespace OpenRA.Mods.Common.Traits
public void WorldLoaded(World world, WorldRenderer wr)
{
foreach (var actorReference in world.Map.Actors.Value)
foreach (var kv in world.Map.ActorDefinitions)
{
var actorReference = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
// if there is no real player associated, dont spawn it.
var ownerName = actorReference.Value.InitDict.Get<OwnerInit>().PlayerName;
var ownerName = actorReference.InitDict.Get<OwnerInit>().PlayerName;
if (!world.Players.Any(p => p.InternalName == ownerName))
continue;
var initDict = actorReference.Value.InitDict;
var initDict = actorReference.InitDict;
initDict.Add(new SkipMakeAnimsInit());
var actor = world.CreateActor(actorReference.Value.Type, initDict);
Actors[actorReference.Key] = actor;
var actor = world.CreateActor(actorReference.Type, initDict);
Actors[kv.Key] = actor;
LastMapActorID = actor.ActorID;
}
}

View File

@@ -150,8 +150,6 @@ namespace OpenRA.Mods.Common.UtilityCommands
map.MapSize = new int2(mapSize, mapSize);
map.Bounds = Rectangle.FromLTRB(offsetX, offsetY, offsetX + width, offsetY + height);
map.Smudges = Exts.Lazy(() => new List<SmudgeReference>());
map.Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>());
map.MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(TileShape.Rectangle, size));
map.MapTiles = Exts.Lazy(() => new CellLayer<TerrainTile>(TileShape.Rectangle, size));
@@ -190,26 +188,28 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
if (kv.First <= 7)
{
var a = new ActorReference("mpspawn")
var ar = new ActorReference("mpspawn")
{
new LocationInit((CPos)kv.Second),
new OwnerInit("Neutral")
};
map.Actors.Value.Add("Actor" + map.Actors.Value.Count.ToString(), a);
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
}
else
{
var a = new ActorReference("waypoint")
var ar = new ActorReference("waypoint")
{
new LocationInit((CPos)kv.Second),
new OwnerInit("Neutral")
};
map.Actors.Value.Add("waypoint" + kv.First, a);
map.ActorDefinitions.Add(new MiniYamlNode("waypoint" + kv.First, ar.Save()));
}
}
// Create default player definitions only if there are no players to import
mapPlayers = new MapPlayers(map.Rules, (players.Count == 0) ? map.GetSpawnPoints().Length : 0);
mapPlayers = new MapPlayers(map.Rules, (players.Count == 0) ? map.SpawnPoints.Value.Length : 0);
foreach (var p in players)
LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert);
map.PlayerDefinitions = mapPlayers.ToMiniYaml();
@@ -295,12 +295,13 @@ namespace OpenRA.Mods.Common.UtilityCommands
if (o != 255 && overlayActorMapping.ContainsKey(redAlertOverlayNames[o]))
{
map.Actors.Value.Add("Actor" + actorCount++,
new ActorReference(overlayActorMapping[redAlertOverlayNames[o]])
{
new LocationInit(cell),
new OwnerInit("Neutral")
});
var ar = new ActorReference(overlayActorMapping[redAlertOverlayNames[o]])
{
new LocationInit(cell),
new OwnerInit("Neutral")
};
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
}
}
}
@@ -315,12 +316,13 @@ namespace OpenRA.Mods.Common.UtilityCommands
foreach (var kv in terrain)
{
var loc = Exts.ParseIntegerInvariant(kv.Key);
map.Actors.Value.Add("Actor" + actorCount++,
new ActorReference(kv.Value.ToLowerInvariant())
{
new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
new OwnerInit("Neutral")
});
var ar = new ActorReference(kv.Value.ToLowerInvariant())
{
new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
new OwnerInit("Neutral")
};
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
}
}
@@ -355,12 +357,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
map.MapResources.Value[cell] = new ResourceTile(res.First, res.Second);
if (overlayActorMapping.ContainsKey(kv.Value.ToLower()))
map.Actors.Value.Add("Actor" + actorCount++,
new ActorReference(overlayActorMapping[kv.Value.ToLower()])
{
new LocationInit(cell),
new OwnerInit("Neutral")
});
{
var ar = new ActorReference(overlayActorMapping[kv.Value.ToLower()])
{
new LocationInit(cell),
new OwnerInit("Neutral")
};
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
}
}
}
@@ -373,12 +378,13 @@ namespace OpenRA.Mods.Common.UtilityCommands
foreach (var kv in terrain)
{
var loc = Exts.ParseIntegerInvariant(kv.Key);
map.Actors.Value.Add("Actor" + actorCount++,
new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
{
new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
new OwnerInit("Neutral")
});
var ar = new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
{
new LocationInit(new CPos(loc % mapSize, loc / mapSize)),
new OwnerInit("Neutral")
};
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
}
}
@@ -420,7 +426,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
if (!rules.Actors.ContainsKey(parts[1].ToLowerInvariant()))
errorHandler("Ignoring unknown actor type: `{0}`".F(parts[1].ToLowerInvariant()));
else
map.Actors.Value.Add("Actor" + actorCount++, actor);
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, actor.Save()));
}
catch (Exception)
{
@@ -436,7 +442,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
// loc=type,loc,depth
var parts = s.Value.Split(',');
var loc = Exts.ParseIntegerInvariant(parts[1]);
map.Smudges.Value.Add(new SmudgeReference(parts[0].ToLowerInvariant(), new int2(loc % mapSize, loc / mapSize), Exts.ParseIntegerInvariant(parts[2])));
var key = "{0} {1},{2} {3}".F(parts[0].ToLowerInvariant(), loc % mapSize, loc / mapSize, Exts.ParseIntegerInvariant(parts[2]));
map.SmudgeDefinitions.Add(new MiniYamlNode(key, ""));
}
}

View File

@@ -297,7 +297,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands
return null;
map.RequiresMod = mod;
var players = new MapPlayers(map.Rules, map.GetSpawnPoints().Length);
var players = new MapPlayers(map.Rules, map.SpawnPoints.Value.Length);
map.PlayerDefinitions = players.ToMiniYaml();
return map;
@@ -314,8 +314,6 @@ namespace OpenRA.Mods.D2k.UtilityCommands
map.MapSize = new int2(mapSize.Width + 2 * MapCordonWidth, mapSize.Height + 2 * MapCordonWidth);
map.Bounds = new Rectangle(MapCordonWidth, MapCordonWidth, mapSize.Width, mapSize.Height);
map.Smudges = Exts.Lazy(() => new List<SmudgeReference>());
map.Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>());
map.MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(TileShape.Rectangle, new Size(map.MapSize.X, map.MapSize.Y)));
map.MapTiles = Exts.Lazy(() => new CellLayer<TerrainTile>(TileShape.Rectangle, new Size(map.MapSize.X, map.MapSize.Y)));
@@ -357,7 +355,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands
new LocationInit(locationOnMap),
new OwnerInit(kvp.Second)
};
map.Actors.Value.Add("Actor" + map.Actors.Value.Count, a);
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, a.Save()));
}
}
}