Merge pull request #5234 from pavlos256/startup

Improve startup speed
This commit is contained in:
Paul Chote
2014-05-17 23:50:45 +12:00
163 changed files with 1135 additions and 720 deletions

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -29,7 +29,7 @@ namespace OpenRA.Editor
currentMod = args.FirstOrDefault() ?? "ra";
toolStripComboBox1.Items.AddRange(Mod.AllMods.Keys.ToArray());
toolStripComboBox1.Items.AddRange(ModMetadata.AllMods.Keys.ToArray());
toolStripComboBox1.SelectedIndexChanged += (_, e) =>
{
@@ -48,7 +48,7 @@ namespace OpenRA.Editor
Game.modData = new ModData(currentMod);
GlobalFileSystem.LoadFromManifest(Game.modData.Manifest);
Rules.LoadRules(Game.modData.Manifest, new Map());
Program.Rules = Game.modData.RulesetCache.LoadDefaultRules();
var mod = Game.modData.Manifest.Mod;
Text = "{0} Mod Version: {1} - OpenRA Editor".F(mod.Title, mod.Version);
@@ -69,7 +69,8 @@ namespace OpenRA.Editor
void OnMapChanged()
{
MakeDirty();
miniMapBox.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
var tileSet = Program.Rules.TileSets[surface1.Map.Tileset];
miniMapBox.Image = Minimap.RenderMapPreview(tileSet, surface1.Map, true);
cashToolStripStatusLabel.Text = CalculateTotalResource().ToString();
}
@@ -84,7 +85,7 @@ namespace OpenRA.Editor
var objSaved = kv.Value.Save();
// TODO: make this work properly
foreach (var init in Rules.Info[kv.Value.Type].GetInitKeys())
foreach (var init in Program.Rules.Actors[kv.Value.Type].GetInitKeys())
apd.AddRow(init.First,
apd.MakeEditorControl(init.Second,
() => objSaved.NodesDict.ContainsKey(init.First) ? objSaved.NodesDict[init.First].Value : null,
@@ -120,7 +121,7 @@ namespace OpenRA.Editor
if (map.Players.Count == 0)
map.MakeDefaultPlayers();
PrepareMapResources(Game.modData.Manifest, map);
PrepareMapResources(Game.modData, map);
// Calculate total net worth of resources in cash
cashToolStripStatusLabel.Text = CalculateTotalResource().ToString();
@@ -135,17 +136,18 @@ namespace OpenRA.Editor
resourcePalette.Controls.Clear();
loadedMapName = null;
PrepareMapResources(Game.modData.Manifest, map);
PrepareMapResources(Game.modData, map);
MakeDirty();
}
// this code is insanely stupid, and mostly my fault -- chrisf
void PrepareMapResources(Manifest manifest, Map map)
void PrepareMapResources(ModData modData, Map map)
{
Rules.LoadRules(manifest, map);
tileset = Rules.TileSets[map.Tileset];
tilesetRenderer = new TileSetRenderer(tileset, manifest.TileSize);
Program.Rules = map.Rules;
tileset = Program.Rules.TileSets[map.Tileset];
tilesetRenderer = new TileSetRenderer(tileset, modData.Manifest.TileSize);
var shadowIndex = new int[] { 3, 4 };
var palette = new Palette(GlobalFileSystem.Open(tileset.Palette), shadowIndex);
@@ -208,11 +210,11 @@ namespace OpenRA.Editor
var actorTemplates = new List<ActorTemplate>();
foreach (var a in Rules.Info.Keys)
foreach (var a in Program.Rules.Actors.Keys)
{
try
{
var info = Rules.Info[a];
var info = Program.Rules.Actors[a];
if (!info.Traits.Contains<RenderSimpleInfo>()) continue;
var etf = info.Traits.GetOrDefault<EditorTilesetFilterInfo>();
@@ -253,7 +255,7 @@ namespace OpenRA.Editor
var resourceTemplates = new List<ResourceTemplate>();
foreach (var a in Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>())
foreach (var a in Program.Rules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>())
{
try
{
@@ -286,7 +288,7 @@ namespace OpenRA.Editor
p.ResumeLayout();
}
miniMapBox.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
miniMapBox.Image = Minimap.RenderMapPreview(tileset, surface1.Map, true);
propertiesToolStripMenuItem.Enabled = true;
toolStripMenuItemProperties.Enabled = true;
@@ -388,12 +390,12 @@ namespace OpenRA.Editor
using (var nmd = new NewMapDialog())
{
nmd.TheaterBox.Items.Clear();
nmd.TheaterBox.Items.AddRange(Rules.TileSets.Select(a => a.Value.Id).ToArray());
nmd.TheaterBox.Items.AddRange(Program.Rules.TileSets.Select(a => a.Value.Id).ToArray());
nmd.TheaterBox.SelectedIndex = 0;
if (DialogResult.OK == nmd.ShowDialog())
{
var tileset = OpenRA.Rules.TileSets[nmd.TheaterBox.SelectedItem as string];
var tileset = Program.Rules.TileSets[nmd.TheaterBox.SelectedItem as string];
var map = Map.FromTileset(tileset);
map.Resize((int)nmd.MapWidth.Value, (int)nmd.MapHeight.Value);
@@ -402,7 +404,7 @@ namespace OpenRA.Editor
map.Players.Clear();
map.MakeDefaultPlayers();
map.FixOpenAreas();
map.FixOpenAreas(Program.Rules);
NewMap(map);
}
@@ -485,7 +487,7 @@ namespace OpenRA.Editor
void FixOpenAreas(object sender, EventArgs e)
{
dirty = true;
surface1.Map.FixOpenAreas();
surface1.Map.FixOpenAreas(Program.Rules);
surface1.Chunks.Clear();
surface1.Invalidate();
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -75,7 +75,8 @@ namespace OpenRA.Editor
try
{
MiniMapBox.Image = Minimap.AddStaticResources(map, Minimap.TerrainBitmap(map, true));
var tileset = Program.Rules.TileSets[map.Tileset];
MiniMapBox.Image = Minimap.RenderMapPreview(tileset, map, true);
}
catch (Exception ed)
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -19,9 +19,13 @@ namespace OpenRA.Editor
{
static class Program
{
public static Ruleset Rules;
[STAThread]
static void Main(string[] args)
{
Log.AddChannel("perf", null);
Application.CurrentCulture = CultureInfo.InvariantCulture;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -379,7 +379,7 @@ namespace OpenRA.Editor
ColorPalette GetPaletteForPlayerInner(string name)
{
var pr = Map.Players[name];
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
var pcpi = Program.Rules.Actors["player"].Traits.Get<PlayerColorPaletteInfo>();
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp);
return new Palette(PlayerPalette, remap).AsSystemPalette();
}

View File

@@ -69,10 +69,10 @@ namespace OpenRA
if (name != null)
{
if (!Rules.Info.ContainsKey(name.ToLowerInvariant()))
if (!world.Map.Rules.Actors.ContainsKey(name.ToLowerInvariant()))
throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant()));
Info = Rules.Info[name.ToLowerInvariant()];
Info = world.Map.Rules.Actors[name.ToLowerInvariant()];
foreach (var trait in Info.TraitsInConstructOrder())
AddTrait(trait.Create(init));
}

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Effects
public MoveFlash(WPos pos, World world)
{
this.pos = pos;
anim = new Animation("moveflsh");
anim = new Animation(world, "moveflsh");
anim.PlayThen("idle", () => world.AddFrameEndTask(w => w.Remove(this)));
}

View File

@@ -117,6 +117,8 @@ namespace OpenRA
}, parent, id);
}
// Note: These delayed actions should only be used by widgets or disposing objects
// - things that depend on a particular world should be queuing them on the worldactor.
static ActionQueue delayedActions = new ActionQueue();
public static void RunAfterTick(Action a) { delayedActions.Add(a); }
public static void RunAfterDelay(int delay, Action a) { delayedActions.Add(a, delay); }
@@ -151,8 +153,11 @@ namespace OpenRA
using (new PerfSample("render_widgets"))
{
Ui.Draw();
if (modData != null && modData.CursorProvider != null)
{
var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default";
CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame);
modData.CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame);
}
}
using (new PerfSample("render_flip"))
@@ -248,11 +253,12 @@ namespace OpenRA
BeforeGameStart();
Map map;
using (new PerfTimer("PrepareMap"))
map = modData.PrepareMap(mapUID);
using (new PerfTimer("NewWorld"))
{
orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap);
orderManager.world = new World(map, orderManager, isShellmap);
orderManager.world.Timestep = Timestep;
}
worldRenderer = new WorldRenderer(orderManager.world);
@@ -354,7 +360,7 @@ namespace OpenRA
}
Console.WriteLine("Available mods:");
foreach (var mod in Mod.AllMods)
foreach (var mod in ModMetadata.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null));
@@ -379,7 +385,7 @@ namespace OpenRA
orderManager.Dispose();
// Fall back to default if the mod doesn't exist
if (!Mod.AllMods.ContainsKey(mod))
if (!ModMetadata.AllMods.ContainsKey(mod))
mod = new GameSettings().Mod;
Console.WriteLine("Loading mod: {0}", mod);

View File

@@ -1,56 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 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;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
namespace OpenRA
{
public static class Rules
{
public static Dictionary<string, ActorInfo> Info;
public static Dictionary<string, WeaponInfo> Weapons;
public static Dictionary<string, SoundInfo> Voices;
public static Dictionary<string, SoundInfo> Notifications;
public static Dictionary<string, MusicInfo> Music;
public static Dictionary<string, string> Movies;
public static Dictionary<string, TileSet> TileSets;
public static void LoadRules(Manifest m, Map map)
{
// Added support to extend the list of rules (add it to m.LocalRules)
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new SoundInfo(k.Value));
Notifications = LoadYamlRules(m.Notifications, map.Notifications, (k, _) => new SoundInfo(k.Value));
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
TileSets = new Dictionary<string, TileSet>();
foreach (var file in m.TileSets)
{
var t = new TileSet(file);
TileSets.Add(t.Id,t);
}
}
static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
{
var y = files.Select(MiniYaml.FromFile).Aggregate(dict, MiniYaml.MergeLiberal);
var yy = y.ToDictionary(x => x.Key, x => x.Value);
return y.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => f(kv, yy), "LoadYamlRules", null, null);
}
public static IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
}
}

View File

@@ -0,0 +1,52 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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;
using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules;
using OpenRA.Graphics;
namespace OpenRA
{
public class Ruleset
{
public readonly IReadOnlyDictionary<string, ActorInfo> Actors;
public readonly IReadOnlyDictionary<string, WeaponInfo> Weapons;
public readonly IReadOnlyDictionary<string, SoundInfo> Voices;
public readonly IReadOnlyDictionary<string, SoundInfo> Notifications;
public readonly IReadOnlyDictionary<string, MusicInfo> Music;
public readonly IReadOnlyDictionary<string, string> Movies;
public readonly IReadOnlyDictionary<string, TileSet> TileSets;
public readonly IReadOnlyDictionary<string, SequenceProvider> Sequences;
public Ruleset(
IDictionary<string, ActorInfo> actors,
IDictionary<string, WeaponInfo> weapons,
IDictionary<string, SoundInfo> voices,
IDictionary<string, SoundInfo> notifications,
IDictionary<string, MusicInfo> music,
IDictionary<string, string> movies,
IDictionary<string, TileSet> tileSets,
IDictionary<string, SequenceProvider> sequences)
{
Actors = new ReadOnlyDictionary<string, ActorInfo>(actors);
Weapons = new ReadOnlyDictionary<string, WeaponInfo>(weapons);
Voices = new ReadOnlyDictionary<string, SoundInfo>(voices);
Notifications = new ReadOnlyDictionary<string, SoundInfo>(notifications);
Music = new ReadOnlyDictionary<string, MusicInfo>(music);
Movies = new ReadOnlyDictionary<string, string>(movies);
TileSets = new ReadOnlyDictionary<string, TileSet>(tileSets);
Sequences = new ReadOnlyDictionary<string, SequenceProvider>(sequences);
}
public IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
}
}

View File

@@ -0,0 +1,142 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Support;
namespace OpenRA
{
public class RulesetCache
{
readonly ModData modData;
readonly Dictionary<string, ActorInfo> actorCache = new Dictionary<string, ActorInfo>();
readonly Dictionary<string, WeaponInfo> weaponCache = new Dictionary<string, WeaponInfo>();
readonly Dictionary<string, SoundInfo> voiceCache = new Dictionary<string, SoundInfo>();
readonly Dictionary<string, SoundInfo> notificationCache = new Dictionary<string, SoundInfo>();
readonly Dictionary<string, MusicInfo> musicCache = new Dictionary<string, MusicInfo>();
readonly Dictionary<string, string> movieCache = new Dictionary<string, string>();
readonly Dictionary<string, TileSet> tileSetCache = new Dictionary<string, TileSet>();
readonly Dictionary<string, SequenceCache> sequenceCaches = new Dictionary<string, SequenceCache>();
public event EventHandler LoadingProgress;
void RaiseProgress()
{
if (LoadingProgress != null)
LoadingProgress(this, new EventArgs());
}
public RulesetCache(ModData modData)
{
this.modData = modData;
}
public Ruleset LoadDefaultRules()
{
return LoadMapRules(new Map());
}
public Ruleset LoadMapRules(Map map)
{
var m = modData.Manifest;
Dictionary<string, ActorInfo> actors;
Dictionary<string, WeaponInfo> weapons;
Dictionary<string, SoundInfo> voices;
Dictionary<string, SoundInfo> notifications;
Dictionary<string, MusicInfo> music;
Dictionary<string, string> movies;
Dictionary<string, TileSet> tileSets;
using (new PerfTimer("Actors"))
actors = LoadYamlRules(actorCache, m.Rules, map.RuleDefinitions, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
using (new PerfTimer("Weapons"))
weapons = LoadYamlRules(weaponCache, m.Weapons, map.WeaponDefinitions, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
using (new PerfTimer("Voices"))
voices = LoadYamlRules(voiceCache, m.Voices, map.VoiceDefinitions, (k, _) => new SoundInfo(k.Value));
using (new PerfTimer("Notifications"))
notifications = LoadYamlRules(notificationCache, m.Notifications, map.NotificationDefinitions, (k, _) => new SoundInfo(k.Value));
using (new PerfTimer("Music"))
music = LoadYamlRules(musicCache, m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
using (new PerfTimer("Movies"))
movies = LoadYamlRules(movieCache, m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
using (new PerfTimer("TileSets"))
tileSets = LoadTileSets(tileSetCache, sequenceCaches, m.TileSets);
var sequences = sequenceCaches.ToDictionary(kvp => kvp.Key, kvp => new SequenceProvider(kvp.Value, map));
return new Ruleset(actors, weapons, voices, notifications, music, movies, tileSets, sequences);
}
Dictionary<string, T> LoadYamlRules<T>(
Dictionary<string, T> itemCache,
string[] files, List<MiniYamlNode> nodes,
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
{
RaiseProgress();
var inputKey = string.Concat(string.Join("|", files), "|", nodes.WriteToString());
var mergedNodes = files
.Select(s => MiniYaml.FromFile(s))
.Aggregate(nodes, MiniYaml.MergeLiberal);
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> wrap = (wkv, wyy) =>
{
var key = inputKey + wkv.Value.ToLines(wkv.Key).JoinWith("|");
T t;
if (itemCache.TryGetValue(key, out t))
return t;
t = f(wkv, wyy);
itemCache.Add(key, t);
RaiseProgress();
return t;
};
var yy = mergedNodes.ToDictionary(x => x.Key, x => x.Value);
var itemSet = mergedNodes.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null);
RaiseProgress();
return itemSet;
}
Dictionary<string, TileSet> LoadTileSets(Dictionary<string, TileSet> itemCache, Dictionary<string, SequenceCache> sequenceCaches, string[] files)
{
var items = new Dictionary<string, TileSet>();
foreach (var file in files)
{
TileSet t;
if (itemCache.TryGetValue(file, out t))
items.Add(t.Id, t);
else
{
t = new TileSet(modData, file);
itemCache.Add(file, t);
// every time we load a tile set, we create a sequence cache for it
var sc = new SequenceCache(modData, t);
sequenceCaches.Add(t.Id, sc);
items.Add(t.Id, t);
}
}
return items;
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -19,7 +19,7 @@ namespace OpenRA.Graphics
public bool IsDecoration = false;
public Func<bool> Paused;
Func<int> facingFunc;
readonly Func<int> facingFunc;
int frame = 0;
bool backwards = false;
@@ -28,11 +28,17 @@ namespace OpenRA.Graphics
public string Name { get { return name; } }
public Animation(string name)
: this(name, () => 0) {}
readonly SequenceProvider sequenceProvider;
public Animation(string name, Func<int> facingFunc)
public Animation(World world, string name)
: this(world, name, () => 0) { }
public Animation(World world, string name, Func<int> facingFunc)
: this(world.Map.SequenceProvider, name, facingFunc) { }
public Animation(SequenceProvider sequenceProvider, string name, Func<int> facingFunc)
{
this.sequenceProvider = sequenceProvider;
this.name = name.ToLowerInvariant();
this.tickFunc = () => {};
this.facingFunc = facingFunc;
@@ -66,7 +72,7 @@ namespace OpenRA.Graphics
{
backwards = false;
tickAlways = false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = 0;
tickFunc = () =>
{
@@ -81,7 +87,7 @@ namespace OpenRA.Graphics
if (!HasSequence(sequenceName))
return false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame %= CurrentSequence.Length;
return true;
}
@@ -90,7 +96,7 @@ namespace OpenRA.Graphics
{
backwards = false;
tickAlways = false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = 0;
tickFunc = () =>
{
@@ -114,7 +120,7 @@ namespace OpenRA.Graphics
{
backwards = false;
tickAlways = true;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = func();
tickFunc = () => frame = func();
}
@@ -128,7 +134,7 @@ namespace OpenRA.Graphics
Tick(40); // tick one frame
}
public bool HasSequence(string seq) { return SequenceProvider.HasSequence(name, seq); }
public bool HasSequence(string seq) { return sequenceProvider.HasSequence(name, seq); }
public void Tick(int t)
{
@@ -159,7 +165,7 @@ namespace OpenRA.Graphics
public Sequence GetSequence(string sequenceName)
{
return SequenceProvider.GetSequence(name, sequenceName);
return sequenceProvider.GetSequence(name, sequenceName);
}
}
}

View File

@@ -16,23 +16,16 @@ using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public static class CursorProvider
public class CursorProvider
{
static HardwarePalette palette;
static Dictionary<string, CursorSequence> cursors;
static Cache<string, PaletteReference> palettes;
HardwarePalette palette;
Dictionary<string, CursorSequence> cursors;
Cache<string, PaletteReference> palettes;
static PaletteReference CreatePaletteReference(string name)
public CursorProvider(ModData modData)
{
var pal = palette.GetPalette(name);
if (pal == null)
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
var sequenceFiles = modData.Manifest.Cursors;
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
}
public static void Initialize(string[] sequenceFiles)
{
cursors = new Dictionary<string, CursorSequence>();
palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
@@ -49,26 +42,35 @@ namespace OpenRA.Graphics
foreach (var p in sequences.NodesDict["Palettes"].Nodes)
palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed));
foreach (var s in sequences.NodesDict["Cursors"].Nodes)
LoadSequencesForCursor(s.Key, s.Value);
LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
palette.Initialize();
}
static void LoadSequencesForCursor(string cursorSrc, MiniYaml cursor)
PaletteReference CreatePaletteReference(string name)
{
Game.modData.LoadScreen.Display();
var pal = palette.GetPalette(name);
if (pal == null)
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
foreach (var sequence in cursor.Nodes)
cursors.Add(sequence.Key, new CursorSequence(cursorSrc, cursor.Value, sequence.Value));
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
}
public static bool HasCursorSequence(string cursor)
void LoadSequencesForCursor(SpriteLoader loader, string cursorSrc, MiniYaml cursor)
{
foreach (var sequence in cursor.Nodes)
cursors.Add(sequence.Key, new CursorSequence(loader, cursorSrc, cursor.Value, sequence.Value));
}
public bool HasCursorSequence(string cursor)
{
return cursors.ContainsKey(cursor);
}
public static void DrawCursor(Renderer renderer, string cursorName, int2 lastMousePos, int cursorFrame)
public void DrawCursor(Renderer renderer, string cursorName, int2 lastMousePos, int cursorFrame)
{
var cursorSequence = GetCursorSequence(cursorName);
var cursorSprite = cursorSequence.GetSprite(cursorFrame);
@@ -80,13 +82,12 @@ namespace OpenRA.Graphics
cursorSprite.size);
}
public static CursorSequence GetCursorSequence(string cursor)
public CursorSequence GetCursorSequence(string cursor)
{
try { return cursors[cursor]; }
catch (KeyNotFoundException)
{
throw new InvalidOperationException(
"Cursor does not have a sequence `{0}`".F(cursor));
throw new InvalidOperationException("Cursor does not have a sequence `{0}`".F(cursor));
}
}
}

View File

@@ -25,9 +25,9 @@ namespace OpenRA.Graphics
Sprite[] sprites;
public CursorSequence(string cursorSrc, string palette, MiniYaml info)
public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info)
{
sprites = Game.modData.SpriteLoader.LoadAllSprites(cursorSrc);
sprites = loader.LoadAllSprites(cursorSrc);
var d = info.NodesDict;
start = Exts.ParseIntegerInvariant(d["start"].Value);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -19,14 +19,8 @@ namespace OpenRA.Graphics
{
public class Minimap
{
public static Bitmap TerrainBitmap(Map map)
public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
{
return TerrainBitmap(map, false);
}
public static Bitmap TerrainBitmap(Map map, bool actualSize)
{
var tileset = Rules.TileSets[map.Tileset];
var width = map.Bounds.Width;
var height = map.Bounds.Height;
@@ -61,10 +55,9 @@ namespace OpenRA.Graphics
// Add the static resources defined in the map; if the map lives
// in a world use AddCustomTerrain instead
public static Bitmap AddStaticResources(Map map, Bitmap terrainBitmap)
static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap)
{
Bitmap terrain = new Bitmap(terrainBitmap);
var tileset = Rules.TileSets[map.Tileset];
var bitmapData = terrain.LockBits(terrain.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
@@ -81,7 +74,7 @@ namespace OpenRA.Graphics
if (map.MapResources.Value[mapX, mapY].Type == 0)
continue;
var res = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()
var res = resourceRules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type)
.Select(t => t.TerrainType).FirstOrDefault();
if (res == null)
@@ -185,10 +178,15 @@ namespace OpenRA.Graphics
return bitmap;
}
public static Bitmap RenderMapPreview(Map map, bool actualSize)
public static Bitmap RenderMapPreview(TileSet tileset, Map map, bool actualSize)
{
Bitmap terrain = TerrainBitmap(map, actualSize);
return AddStaticResources(map, terrain);
return RenderMapPreview(tileset, map, map.Rules, actualSize);
}
public static Bitmap RenderMapPreview(TileSet tileset, Map map, Ruleset resourceRules, bool actualSize)
{
Bitmap terrain = TerrainBitmap(tileset, map, actualSize);
return AddStaticResources(tileset, map, resourceRules, terrain);
}
}
}

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Graphics
public readonly int ShadowZOffset;
public readonly int[] Frames;
public Sequence(string unit, string name, MiniYaml info)
public Sequence(SpriteLoader loader, string unit, string name, MiniYaml info)
{
var srcOverride = info.Value;
Name = name;
@@ -50,7 +50,7 @@ namespace OpenRA.Graphics
// Apply offset to each sprite in the sequence
// Different sequences may apply different offsets to the same frame
sprites = Game.modData.SpriteLoader.LoadAllSprites(srcOverride ?? unit).Select(
sprites = loader.LoadAllSprites(srcOverride ?? unit).Select(
s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray();
if (!d.ContainsKey("Length"))

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -13,69 +13,101 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public static class SequenceProvider
public class SequenceProvider
{
static Dictionary<string, Dictionary<string, Sequence>> units;
readonly Lazy<IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>> sequences;
public readonly SpriteLoader SpriteLoader;
public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes)
public SequenceProvider(SequenceCache cache, Map map)
{
units = new Dictionary<string, Dictionary<string, Sequence>>();
this.sequences = Exts.Lazy(() => cache.LoadSequences(map));
this.SpriteLoader = cache.SpriteLoader;
}
var sequences = sequenceFiles
public Sequence GetSequence(string unitName, string sequenceName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
Sequence seq;
if (!unitSeq.Value.TryGetValue(sequenceName, out seq))
throw new InvalidOperationException("Unit `{0}` does not have a sequence named `{1}`".F(unitName, sequenceName));
return seq;
}
public bool HasSequence(string unitName, string sequenceName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
return unitSeq.Value.ContainsKey(sequenceName);
}
public IEnumerable<string> Sequences(string unitName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
return unitSeq.Value.Keys;
}
}
public class SequenceCache
{
readonly ModData modData;
readonly Lazy<SpriteLoader> spriteLoader;
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
public SequenceCache(ModData modData, TileSet tileSet)
{
this.modData = modData;
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
}
public IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> LoadSequences(Map map)
{
using (new Support.PerfTimer("LoadSequences"))
return Load(map.SequenceDefinitions);
}
IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes)
{
var sequenceFiles = modData.Manifest.Sequences;
var nodes = sequenceFiles
.Select(s => MiniYaml.FromFile(s))
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
foreach (var s in sequences)
LoadSequencesForUnit(s.Key, s.Value);
}
var items = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
foreach (var node in nodes)
{
var key = node.Value.ToLines(node.Key).JoinWith("|");
static void LoadSequencesForUnit(string unit, MiniYaml sequences)
{
Game.modData.LoadScreen.Display();
try
{
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
units.Add(unit, seq);
}
catch (FileNotFoundException)
{
// Do nothing; we can crash later if we actually wanted art
}
}
public static Sequence GetSequence(string unitName, string sequenceName)
{
try { return units[unitName][sequenceName]; }
catch (KeyNotFoundException)
{
if (units.ContainsKey(unitName))
throw new InvalidOperationException(
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
Lazy<IReadOnlyDictionary<string, Sequence>> t;
if (sequenceCache.TryGetValue(key, out t))
items.Add(node.Key, t);
else
throw new InvalidOperationException(
"Unit `{0}` does not have all sequences defined.".F(unitName));
}
}
public static bool HasSequence(string unit, string seq)
{
if (!units.ContainsKey(unit))
throw new InvalidOperationException(
"Unit `{0}` does not have sequence `{1}` defined.".F(unit, seq));
return units[unit].ContainsKey(seq);
t = Exts.Lazy(() => (IReadOnlyDictionary<string, Sequence>)new ReadOnlyDictionary<string, Sequence>(
node.Value.NodesDict.ToDictionary(x => x.Key, x =>
new Sequence(spriteLoader.Value, node.Key, x.Key, x.Value))));
sequenceCache.Add(key, t);
items.Add(node.Key, t);
}
}
public static IEnumerable<string> Sequences(string unit)
{
if (!units.ContainsKey(unit))
throw new InvalidOperationException(
"Unit `{0}` does not have all sequences defined.".F(unit));
return units[unit].Keys;
return new ReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(items);
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -18,7 +18,7 @@ namespace OpenRA.Graphics
{
public class SpriteLoader
{
readonly SheetBuilder SheetBuilder;
public readonly SheetBuilder SheetBuilder;
readonly Cache<string, Sprite[]> sprites;
readonly string[] exts;

View File

@@ -19,7 +19,7 @@ namespace OpenRA
// Describes what is to be loaded in order to run a mod
public class Manifest
{
public readonly Mod Mod;
public readonly ModMetadata Mod;
public readonly string[]
Folders, MapFolders, Rules, ServerTraits,
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
@@ -38,7 +38,7 @@ namespace OpenRA
var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
Mod = FieldLoader.Load<Mod>(yaml["Metadata"]);
Mod = FieldLoader.Load<ModMetadata>(yaml["Metadata"]);
Mod.Id = mod;
// TODO: Use fieldloader

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using OpenRA.Primitives;
@@ -17,16 +18,24 @@ namespace OpenRA
public class ActorReference : IEnumerable
{
public string Type;
public TypeDictionary InitDict;
public TypeDictionary InitDict
{
get { return initDict.Value; }
}
Lazy<TypeDictionary> initDict;
public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { }
public ActorReference( string type, Dictionary<string, MiniYaml> inits )
{
Type = type;
InitDict = new TypeDictionary();
initDict = Exts.Lazy(() =>
{
var dict = new TypeDictionary();
foreach (var i in inits)
InitDict.Add( LoadInit( i.Key, i.Value ) );
dict.Add(LoadInit(i.Key, i.Value));
return dict;
});
}
static IActorInit LoadInit(string traitName, MiniYaml my)

View File

@@ -18,6 +18,7 @@ using System.Text;
using OpenRA.FileSystem;
using OpenRA.Network;
using OpenRA.Traits;
using OpenRA.Graphics;
namespace OpenRA
{
@@ -94,13 +95,13 @@ namespace OpenRA
[FieldLoader.Ignore] public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
[FieldLoader.Ignore] public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Sequences = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequences = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Weapons = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Voices = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Notifications = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Translations = new List<MiniYamlNode>();
[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>();
[FieldLoader.Ignore] public List<MiniYamlNode> WeaponDefinitions = 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> TranslationDefinitions = new List<MiniYamlNode>();
// Binary map data
[FieldLoader.Ignore] public byte TileFormat = 1;
@@ -110,6 +111,10 @@ namespace OpenRA
[FieldLoader.Ignore] public Lazy<TileReference<byte, byte>[,]> MapResources;
[FieldLoader.Ignore] public string[,] CustomTerrain;
[FieldLoader.Ignore] Lazy<Ruleset> rules;
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
public static Map FromTileset(TileSet tileset)
{
var tile = tileset.Templates.First();
@@ -128,6 +133,7 @@ namespace OpenRA
Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()),
Smudges = Exts.Lazy(() => new List<SmudgeReference>())
};
map.PostInit();
return map;
}
@@ -210,13 +216,13 @@ namespace OpenRA
return ret;
});
Rules = MiniYaml.NodesOrEmpty(yaml, "Rules");
Sequences = MiniYaml.NodesOrEmpty(yaml, "Sequences");
VoxelSequences = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
Weapons = MiniYaml.NodesOrEmpty(yaml, "Weapons");
Voices = MiniYaml.NodesOrEmpty(yaml, "Voices");
Notifications = MiniYaml.NodesOrEmpty(yaml, "Notifications");
Translations = MiniYaml.NodesOrEmpty(yaml, "Translations");
RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules");
SequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Sequences");
VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons");
VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices");
NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
CustomTerrain = new string[MapSize.X, MapSize.Y];
@@ -233,6 +239,18 @@ namespace OpenRA
if (Container.Exists("map.png"))
CustomPreview = new Bitmap(Container.GetContent("map.png"));
PostInit();
}
void PostInit()
{
rules = Exts.Lazy(() => Game.modData.RulesetCache.LoadMapRules(this));
}
public Ruleset PreloadRules()
{
return rules.Value;
}
public CPos[] GetSpawnPoints()
@@ -282,13 +300,13 @@ namespace OpenRA
);
root.Add(new MiniYamlNode("Smudges", MiniYaml.FromList<SmudgeReference>(Smudges.Value)));
root.Add(new MiniYamlNode("Rules", null, Rules));
root.Add(new MiniYamlNode("Sequences", null, Sequences));
root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequences));
root.Add(new MiniYamlNode("Weapons", null, Weapons));
root.Add(new MiniYamlNode("Voices", null, Voices));
root.Add(new MiniYamlNode("Notifications", null, Notifications));
root.Add(new MiniYamlNode("Translations", null, Translations));
root.Add(new MiniYamlNode("Rules", null, RuleDefinitions));
root.Add(new MiniYamlNode("Sequences", null, SequenceDefinitions));
root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequenceDefinitions));
root.Add(new MiniYamlNode("Weapons", null, WeaponDefinitions));
root.Add(new MiniYamlNode("Voices", null, VoiceDefinitions));
root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions));
root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions));
var entries = new Dictionary<string, byte[]>();
entries.Add("map.bin", SaveBinaryData());
@@ -452,7 +470,7 @@ namespace OpenRA
public void MakeDefaultPlayers()
{
var firstRace = OpenRA.Rules.Info["world"].Traits
var firstRace = Rules.Actors["world"].Traits
.WithInterface<CountryInfo>().First(c => c.Selectable).Race;
if (!Players.ContainsKey("Neutral"))
@@ -489,10 +507,10 @@ namespace OpenRA
});
}
public void FixOpenAreas()
public void FixOpenAreas(Ruleset rules)
{
var r = new Random();
var tileset = OpenRA.Rules.TileSets[Tileset];
var tileset = rules.TileSets[Tileset];
for (var j = Bounds.Top; j < Bounds.Bottom; j++)
{

14
OpenRA.Game/Map/MapCache.cs Executable file → Normal file
View File

@@ -27,30 +27,30 @@ namespace OpenRA
{
public static readonly MapPreview UnknownMap = new MapPreview(null, null);
readonly Cache<string, MapPreview> previews;
readonly Manifest manifest;
readonly ModData modData;
readonly SheetBuilder sheetBuilder;
Thread previewLoaderThread;
object syncRoot = new object();
Queue<MapPreview> generateMinimap = new Queue<MapPreview>();
public MapCache(Manifest m)
public MapCache(ModData modData)
{
manifest = m;
this.modData = modData;
previews = new Cache<string, MapPreview>(uid => new MapPreview(uid, this));
sheetBuilder = new SheetBuilder(SheetType.BGRA);
}
public void LoadMaps()
{
var paths = manifest.MapFolders.SelectMany(f => FindMapsIn(f));
var paths = modData.Manifest.MapFolders.SelectMany(f => FindMapsIn(f));
foreach (var path in paths)
{
try
{
using (new Support.PerfTimer(path))
{
var map = new Map(path, manifest.Mod.Id);
if (manifest.MapCompatibility.Contains(map.RequiresMod))
var map = new Map(path, modData.Manifest.Mod.Id);
if (modData.Manifest.MapCompatibility.Contains(map.RequiresMod))
previews[map.Uid].UpdateFromMap(map);
}
}
@@ -149,7 +149,7 @@ namespace OpenRA
// the next render cycle.
// (d) Any partially written bytes from the next minimap is in an
// unallocated area, and will be committed in the next cycle.
var bitmap = p.CustomPreview ?? Minimap.RenderMapPreview(p.Map, true);
var bitmap = p.CustomPreview ?? Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true);
p.Minimap = sheetBuilder.Add(bitmap);
lock (syncRoot)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -8,21 +8,23 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using OpenRA.Graphics;
namespace OpenRA
{
public class TerrainTypeInfo
{
public string Type;
public string[] TargetTypes = { };
public string[] AcceptsSmudgeType = { };
public bool IsWater = false; // TODO: Remove this
public Color Color;
public string CustomCursor;
public readonly string Type;
public readonly string[] TargetTypes = { };
public readonly string[] AcceptsSmudgeType = { };
public readonly bool IsWater = false; // TODO: Remove this
public readonly Color Color;
public readonly string CustomCursor;
public TerrainTypeInfo() { }
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
@@ -32,19 +34,26 @@ namespace OpenRA
public class TileTemplate
{
public ushort Id;
public string Image;
public int[] Frames;
public int2 Size;
public bool PickAny;
public string Category;
public readonly ushort Id;
public readonly string Image;
public readonly int[] Frames;
public readonly int2 Size;
public readonly bool PickAny;
public readonly string Category;
[FieldLoader.LoadUsing("LoadTiles")]
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
public readonly Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
public TileTemplate() { }
public TileTemplate(MiniYaml my) { FieldLoader.Load(this, my); }
public TileTemplate(ushort id, string image, int2 size)
{
this.Id = id;
this.Image = image;
this.Size = size;
}
static object LoadTiles(MiniYaml y)
{
return y.NodesDict["Tiles"].NodesDict.ToDictionary(
@@ -75,22 +84,20 @@ namespace OpenRA
public class TileSet
{
public string Name;
public string Id;
public int SheetSize = 512;
public string Palette;
public string PlayerPalette;
public string[] Extensions;
public int WaterPaletteRotationBase = 0x60;
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
public string[] EditorTemplateOrder;
public readonly string Name;
public readonly string Id;
public readonly int SheetSize = 512;
public readonly string Palette;
public readonly string PlayerPalette;
public readonly string[] Extensions;
public readonly int WaterPaletteRotationBase = 0x60;
public readonly Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
public readonly Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
public readonly string[] EditorTemplateOrder;
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "Extensions" };
public TileSet() { }
public TileSet(string filepath)
public TileSet(ModData modData, string filepath)
{
var yaml = MiniYaml.DictFromFile(filepath);
@@ -106,6 +113,14 @@ namespace OpenRA
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
}
public TileSet(string name, string id, string palette, string[] extensions)
{
this.Name = name;
this.Id = id;
this.Palette = palette;
this.Extensions = extensions;
}
public void Save(string filepath)
{
var root = new List<MiniYamlNode>();

45
OpenRA.Game/ModData.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -25,9 +25,12 @@ namespace OpenRA
public readonly WidgetLoader WidgetLoader;
public readonly MapCache MapCache;
public ILoadScreen LoadScreen = null;
public SheetBuilder SheetBuilder;
public SpriteLoader SpriteLoader;
public VoxelLoader VoxelLoader;
public readonly RulesetCache RulesetCache;
public CursorProvider CursorProvider { get; private set; }
Lazy<Ruleset> defaultRules;
public Ruleset DefaultRules { get { return defaultRules.Value; } }
public ModData(string mod)
{
@@ -38,12 +41,26 @@ namespace OpenRA
LoadScreen.Init(Manifest, Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value));
LoadScreen.Display();
WidgetLoader = new WidgetLoader(this);
MapCache = new MapCache(Manifest);
RulesetCache = new RulesetCache(this);
RulesetCache.LoadingProgress += HandleLoadingProgress;
MapCache = new MapCache(this);
// HACK: Mount only local folders so we have a half-working environment for the asset installer
GlobalFileSystem.UnmountAll();
foreach (var dir in Manifest.Folders)
GlobalFileSystem.Mount(dir);
defaultRules = Exts.Lazy(() => RulesetCache.LoadDefaultRules());
initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
}
// HACK: Only update the loading screen if we're in the main thread.
int initialThreadId;
void HandleLoadingProgress(object sender, EventArgs e)
{
if (LoadScreen != null && System.Threading.Thread.CurrentThread.ManagedThreadId == initialThreadId)
LoadScreen.Display();
}
public void InitializeLoaders()
@@ -52,10 +69,9 @@ namespace OpenRA
// horribly when you use ModData in unexpected ways.
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
ChromeProvider.Initialize(Manifest.Chrome);
SheetBuilder = new SheetBuilder(SheetType.Indexed);
SpriteLoader = new SpriteLoader(new string[0], SheetBuilder);
VoxelLoader = new VoxelLoader();
CursorProvider.Initialize(Manifest.Cursors);
CursorProvider = new CursorProvider(this);
}
public IEnumerable<string> Languages { get; private set; }
@@ -75,7 +91,7 @@ namespace OpenRA
var yaml = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal);
Languages = yaml.Select(t => t.Key).ToArray();
yaml = MiniYaml.MergeLiberal(map.Translations, yaml);
yaml = MiniYaml.MergeLiberal(map.TranslationDefinitions, yaml);
foreach (var y in yaml)
{
@@ -118,16 +134,11 @@ namespace OpenRA
// Mount map package so custom assets can be used. TODO: check priority.
GlobalFileSystem.Mount(GlobalFileSystem.OpenPackage(map.Path, null, int.MaxValue));
using (new Support.PerfTimer("LoadRules"))
Rules.LoadRules(Manifest, map);
SpriteLoader = new SpriteLoader(Rules.TileSets[map.Tileset].Extensions, SheetBuilder);
using (new Support.PerfTimer("Map.LoadRules"))
map.PreloadRules();
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequenceDefinitions);
using (new Support.PerfTimer("SequenceProvider.Initialize"))
{
// TODO: Don't load the sequences for assets that are not used in this tileset. Maybe use the existing EditorTilesetFilters.
SequenceProvider.Initialize(Manifest.Sequences, map.Sequences);
}
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequences);
return map;
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -14,9 +14,9 @@ using System.Linq;
namespace OpenRA
{
public class Mod
public class ModMetadata
{
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
public static readonly Dictionary<string, ModMetadata> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
public string Id;
public string Title;
@@ -24,9 +24,9 @@ namespace OpenRA
public string Version;
public string Author;
public static Dictionary<string, Mod> ValidateMods(string[] mods)
public static Dictionary<string, ModMetadata> ValidateMods(string[] mods)
{
var ret = new Dictionary<string, Mod>();
var ret = new Dictionary<string, ModMetadata>();
foreach (var m in mods)
{
var yamlPath = new[] { "mods", m, "mod.yaml" }.Aggregate(Path.Combine);
@@ -37,7 +37,7 @@ namespace OpenRA
if (!yaml.NodesDict.ContainsKey("Metadata"))
continue;
var mod = FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]);
var mod = FieldLoader.Load<ModMetadata>(yaml.NodesDict["Metadata"]);
mod.Id = m;
ret.Add(m, mod);

View File

@@ -99,7 +99,6 @@
<Compile Include="Game.cs" />
<Compile Include="GameRules\ActorInfo.cs" />
<Compile Include="GameRules\MusicInfo.cs" />
<Compile Include="GameRules\Rules.cs" />
<Compile Include="GameRules\SoundInfo.cs" />
<Compile Include="GameRules\WeaponInfo.cs" />
<Compile Include="Graphics\Animation.cs" />
@@ -244,6 +243,10 @@
<Compile Include="Scripting\ScriptMemberExts.cs" />
<Compile Include="Scripting\ScriptPlayerInterface.cs" />
<Compile Include="Traits\Player\FixedColorPalette.cs" />
<Compile Include="Primitives\ReadOnlyDictionary.cs" />
<Compile Include="ModMetadata.cs" />
<Compile Include="GameRules\Ruleset.cs" />
<Compile Include="GameRules\RulesetCache.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="FileSystem\D2kSoundResources.cs" />
@@ -303,7 +306,6 @@
<Compile Include="Hotkey.cs" />
<Compile Include="Keycode.cs" />
<Compile Include="MiniYaml.cs" />
<Compile Include="Mod.cs" />
<Compile Include="Platform.cs" />
<Compile Include="StreamExts.cs" />
<Compile Include="Map\Map.cs" />

View File

@@ -47,7 +47,7 @@ namespace OpenRA
static CountryInfo ChooseCountry(World world, string name)
{
var selectableCountries = Rules.Info["world"].Traits
var selectableCountries = world.Map.Rules.Actors["world"].Traits
.WithInterface<CountryInfo>().Where( c => c.Selectable )
.ToArray();

View File

@@ -0,0 +1,90 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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;
using System.Collections.Generic;
namespace OpenRA
{
/// <summary>
/// A minimal read only dictionary interface for .NET 4
/// </summary>
/// <remarks>
/// .NET 4.5 has an implementation built-in, this code is not meant to
/// duplicate it but provide a compatible interface that can be replaced
/// when we switch to .NET 4.5 or higher.
/// </remarks>
public interface IReadOnlyDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
int Count { get; }
TValue this[TKey key] { get; }
IEnumerable<TKey> Keys { get; }
IEnumerable<TValue> Values { get; }
bool ContainsKey(TKey key);
bool TryGetValue(TKey key, out TValue value);
}
/// <summary>
/// A minimal read only dictionary for .NET 4 implemented as a wrapper
/// around an IDictionary.
/// </summary>
public class ReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> dict;
public ReadOnlyDictionary()
: this(new Dictionary<TKey, TValue>())
{
}
public ReadOnlyDictionary(IDictionary<TKey, TValue> dict)
{
if (dict == null)
throw new ArgumentNullException("dict");
this.dict = dict;
}
#region IReadOnlyDictionary implementation
public bool ContainsKey(TKey key)
{
return dict.ContainsKey(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return dict.TryGetValue(key, out value);
}
public int Count { get { return dict.Count; } }
public TValue this[TKey key] { get { return dict[key]; } }
public IEnumerable<TKey> Keys { get { return dict.Keys; } }
public IEnumerable<TValue> Values { get { return dict.Values; } }
#endregion
#region IEnumerable implementation
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return dict.GetEnumerator();
}
#endregion
#region IEnumerable implementation
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return dict.GetEnumerator();
}
#endregion
}
}

View File

@@ -296,15 +296,18 @@ namespace OpenRA
}
// Returns true if played successfully
public static bool PlayPredefined(Player p, Actor voicedUnit, string type, string definition, string variant, bool relative, WPos pos, float volumeModifier, bool attenuateVolume)
public static bool PlayPredefined(Ruleset ruleset, Player p, Actor voicedUnit, string type, string definition, string variant, bool relative, WPos pos, float volumeModifier, bool attenuateVolume)
{
if (ruleset == null)
throw new ArgumentNullException("ruleset");
if (definition == null)
return false;
if (Rules.Voices == null || Rules.Notifications == null)
if (ruleset.Voices == null || ruleset.Notifications == null)
return false;
var rules = (voicedUnit != null) ? Rules.Voices[type] : Rules.Notifications[type];
var rules = (voicedUnit != null) ? ruleset.Voices[type] : ruleset.Notifications[type];
if (rules == null)
return false;
@@ -366,7 +369,7 @@ namespace OpenRA
return false;
var type = mi.Voice.ToLowerInvariant();
return PlayPredefined(null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true);
return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true);
}
public static bool PlayVoiceLocal(string phrase, Actor voicedUnit, string variant, WPos pos, float volume)
@@ -379,15 +382,18 @@ namespace OpenRA
return false;
var type = mi.Voice.ToLowerInvariant();
return PlayPredefined(null, voicedUnit, type, phrase, variant, false, pos, volume, true);
return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, false, pos, volume, true);
}
public static bool PlayNotification(Player player, string type, string notification, string variant)
public static bool PlayNotification(Ruleset rules, Player player, string type, string notification, string variant)
{
if (rules == null)
throw new ArgumentNullException("rules");
if (type == null || notification == null)
return false;
return PlayPredefined(player, null, type.ToLowerInvariant(), notification, variant, true, WPos.Zero, 1f, false);
return PlayPredefined(rules, player, null, type.ToLowerInvariant(), notification, variant, true, WPos.Zero, 1f, false);
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -118,7 +118,7 @@ namespace OpenRA.Traits
{
if (Ore > 0.8 * OreCapacity)
{
Sound.PlayNotification(Owner, "Speech", "SilosNeeded", Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, Owner, "Speech", "SilosNeeded", Owner.Country.Race);
AlertSilo = true;
}
else
@@ -163,14 +163,14 @@ namespace OpenRA.Traits
public void playCashTickUp(Actor self)
{
if (Game.Settings.Sound.CashTicks)
Sound.PlayNotification(self.Owner, "Sounds", "CashTickUp", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickUp", self.Owner.Country.Race);
}
public void playCashTickDown(Actor self)
{
if (Game.Settings.Sound.CashTicks && nextCashTickTime == 0)
{
Sound.PlayNotification(self.Owner, "Sounds", "CashTickDown", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickDown", self.Owner.Country.Race);
nextCashTickTime = 2;
}
}

View File

@@ -19,9 +19,9 @@ namespace OpenRA.Traits
{
public override object Create(ActorInitializer init) { return new RenderSimple(init.self); }
public virtual IEnumerable<IRenderable> RenderPreview(ActorInfo ai, PaletteReference pr)
public virtual IEnumerable<IRenderable> RenderPreview(World world, ActorInfo ai, PaletteReference pr)
{
var anim = new Animation(RenderSimple.GetImage(ai), () => 0);
var anim = new Animation(world, RenderSimple.GetImage(ai), () => 0);
anim.PlayRepeating("idle");
return anim.Render(WPos.Zero, WVec.Zero, 0, pr, Scale);
@@ -35,7 +35,7 @@ namespace OpenRA.Traits
public RenderSimple(Actor self, Func<int> baseFacing)
: base(self)
{
anims.Add("", new Animation(GetImage(self), baseFacing));
anims.Add("", new Animation(self.World, GetImage(self), baseFacing));
Info = self.Info.Traits.Get<RenderSimpleInfo>();
}

View File

@@ -57,7 +57,7 @@ namespace OpenRA.Traits
var group = self.World.Selection.GetControlGroupForActor(self);
if (group == null) return;
var pipImages = new Animation("pips");
var pipImages = new Animation(self.World, "pips");
var pal = wr.Palette(Info.Palette);
pipImages.PlayFetchIndex("groups", () => (int)group);
pipImages.Tick();
@@ -75,7 +75,7 @@ namespace OpenRA.Traits
if (!pipSources.Any())
return;
var pipImages = new Animation("pips");
var pipImages = new Animation(self.World, "pips");
pipImages.PlayRepeating(pipStrings[0]);
var pipSize = pipImages.Image.size.ToInt2();
@@ -115,7 +115,7 @@ namespace OpenRA.Traits
if (!self.Owner.IsAlliedWith(self.World.RenderPlayer))
return;
var tagImages = new Animation("pips");
var tagImages = new Animation(self.World, "pips");
var pal = wr.Palette(Info.Palette);
var tagxyOffset = new int2(0, 6);
var tagBase = wr.Viewport.WorldToViewPx(basePosition);

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Traits
public PipType PipColor = PipType.Yellow;
public object Create(ActorInitializer init) { return new ResourceType(this); }
public object Create(ActorInitializer init) { return new ResourceType(this, init.world); }
}
public class ResourceType : IWorldLoaded
@@ -41,13 +41,13 @@ namespace OpenRA.Traits
public PaletteReference Palette { get; private set; }
public readonly Dictionary<string, Sprite[]> Variants;
public ResourceType(ResourceTypeInfo info)
public ResourceType(ResourceTypeInfo info, World world)
{
this.Info = info;
Variants = new Dictionary<string, Sprite[]>();
foreach (var v in info.Variants)
{
var seq = SequenceProvider.GetSequence("resources", v);
var seq = world.Map.SequenceProvider.GetSequence("resources", v);
var sprites = Exts.MakeArray(seq.Length, x => seq.GetSprite(x));
Variants.Add(v, sprites);
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -53,8 +53,13 @@ namespace OpenRA.Widgets
public Action OnDoubleClick = () => {};
public Action<KeyInput> OnKeyPress = _ => {};
public ButtonWidget()
readonly Ruleset modRules;
[ObjectCreator.UseCtor]
public ButtonWidget(Ruleset modRules)
{
this.modRules = modRules;
GetText = () => { return Text; };
GetColor = () => TextColor;
GetColorDisabled = () => TextColorDisabled;
@@ -70,6 +75,8 @@ namespace OpenRA.Widgets
protected ButtonWidget(ButtonWidget other)
: base(other)
{
this.modRules = other.modRules;
Text = other.Text;
Font = other.Font;
TextColor = other.TextColor;
@@ -113,10 +120,10 @@ namespace OpenRA.Widgets
if (!IsDisabled())
{
OnKeyPress(e);
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
Sound.PlayNotification(modRules, null, "Sounds", "ClickSound", null);
}
else
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
Sound.PlayNotification(modRules, null, "Sounds", "ClickDisabledSound", null);
return true;
}
@@ -153,12 +160,12 @@ namespace OpenRA.Widgets
{
OnMouseDown(mi);
Depressed = true;
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
Sound.PlayNotification(modRules, null, "Sounds", "ClickSound", null);
}
else
{
YieldMouseFocus(mi);
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
Sound.PlayNotification(modRules, null, "Sounds", "ClickDisabledSound", null);
}
}
else if (mi.Event == MouseInputEvent.Move && HasMouseFocus)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -11,6 +11,7 @@
using System;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Widgets
{
@@ -23,7 +24,9 @@ namespace OpenRA.Widgets
public int CheckOffset = 2;
public bool HasPressedState = ChromeMetrics.Get<bool>("CheckboxPressedState");
public CheckboxWidget()
[ObjectCreator.UseCtor]
public CheckboxWidget(Ruleset modRules)
: base(modRules)
{
GetCheckType = () => CheckType;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Widgets
{
@@ -20,7 +21,9 @@ namespace OpenRA.Widgets
Widget panel;
MaskWidget fullscreenMask;
public DropDownButtonWidget() { }
[ObjectCreator.UseCtor]
public DropDownButtonWidget(Ruleset modRules)
: base(modRules) { }
protected DropDownButtonWidget(DropDownButtonWidget widget) : base(widget) { }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -9,6 +9,8 @@
#endregion
using System;
using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Widgets
{
@@ -17,7 +19,9 @@ namespace OpenRA.Widgets
public string ItemKey;
public string BaseName = "scrollitem";
public ScrollItemWidget()
[ObjectCreator.UseCtor]
public ScrollItemWidget(Ruleset modRules)
: base(modRules)
{
IsVisible = () => false;
VisualHeight = 0;

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Widgets
if (Unit != null && Sequence != null)
{
var anim = new Animation(Unit, () => Facing);
var anim = new Animation(worldRenderer.world, Unit, () => Facing);
anim.PlayFetchIndex(Sequence, () => Frame);
GetAnimation = () => anim;
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Widgets
public Func<string> GetPalette;
public Func<Sprite> GetSprite;
readonly WorldRenderer worldRenderer;
protected readonly WorldRenderer worldRenderer;
[ObjectCreator.UseCtor]
public SpriteWidget(WorldRenderer worldRenderer)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -18,10 +18,13 @@ namespace OpenRA
{
public class WidgetLoader
{
Dictionary<string, MiniYamlNode> widgets = new Dictionary<string, MiniYamlNode>();
readonly Dictionary<string, MiniYamlNode> widgets = new Dictionary<string, MiniYamlNode>();
readonly ModData modData;
public WidgetLoader(ModData modData)
{
this.modData = modData;
foreach (var file in modData.Manifest.ChromeLayout.Select(a => MiniYaml.FromFile(a)))
foreach( var w in file )
{
@@ -55,6 +58,8 @@ namespace OpenRA
if (child.Key != "Children")
FieldLoader.LoadField(widget, child.Key, child.Value.Value);
if (!args.ContainsKey("modRules"))
args = new WidgetArgs(args) { { "modRules", modData.DefaultRules } };
widget.Initialize(args);
foreach (var child in node.Value.Nodes)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -118,14 +118,14 @@ namespace OpenRA
}
}
internal World(Manifest manifest, Map map, OrderManager orderManager, bool isShellmap)
internal World(Map map, OrderManager orderManager, bool isShellmap)
{
IsShellmap = isShellmap;
this.orderManager = orderManager;
orderGenerator_ = new UnitOrderGenerator();
Map = map;
TileSet = Rules.TileSets[Map.Tileset];
TileSet = map.Rules.TileSets[Map.Tileset];
SharedRandom = new XRandom(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
WorldActor = CreateActor("World", new TypeDictionary());

View File

@@ -151,7 +151,7 @@ namespace OpenRA
var selectable = a.Info.Traits.GetOrDefault<SelectableInfo>();
if (selectable == null) return null;
var v = selectable.Voice;
return (v == null) ? null : Rules.Voices[v.ToLowerInvariant()];
return (v == null) ? null : a.World.Map.Rules.Voices[v.ToLowerInvariant()];
}
public static void PlayVoiceForOrders(this World w, Order[] orders)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -69,7 +69,7 @@ namespace OpenRA.Lint
foreach (var testMap in maps)
{
if (testMap.Rules.Count < 1)
if (testMap.RuleDefinitions.Count < 1)
{
if (verbose)
Console.WriteLine("No custom rules detected. Omitting Map: {0}".F(testMap.Title));
@@ -79,7 +79,7 @@ namespace OpenRA.Lint
if (verbose)
Console.WriteLine("Map: {0}".F(testMap.Title));
Rules.LoadRules(Game.modData.Manifest, testMap);
testMap.PreloadRules();
foreach (var customPassType in Game.modData.ObjectCreator
.GetTypesImplementing<ILintPass>())

View File

@@ -18,11 +18,11 @@ namespace OpenRA.Mods.Cnc.Effects
{
public class IonCannon : IEffect
{
Target target;
Animation anim;
Player firedBy;
string palette;
string weapon;
readonly Target target;
readonly Animation anim;
readonly Player firedBy;
readonly string palette;
readonly string weapon;
public IonCannon(Player firedBy, string weapon, World world, CPos location, string effect, string palette)
{
@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Cnc.Effects
this.weapon = weapon;
this.palette = palette;
target = Target.FromCell(location);
anim = new Animation(effect);
anim = new Animation(world, effect);
anim.PlayThen("idle", () => Finish(world));
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Cnc
if (r == null) return;
if (!info.Resources.Contains(r.Info.Name)) return;
var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()];
var weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
self.InflictDamage(self.World.WorldActor, weapon.Warheads[0].Damage, weapon.Warheads[0]);
poisonTicks = weapon.ROF;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Cnc
owner.World.AddFrameEndTask(w =>
{
var altitude = Rules.Info[actorType].Traits.Get<PlaneInfo>().CruiseAltitude;
var altitude = self.World.Map.Rules.Actors[actorType].Traits.Get<PlaneInfo>().CruiseAltitude;
var a = w.CreateActor(actorType, new TypeDictionary
{
new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),
@@ -69,7 +69,7 @@ namespace OpenRA.Mods.Cnc
rb.PlayCustomAnimRepeating(self, "idle");
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit));
Sound.PlayNotification(self.Owner, "Speech", (Info as ProductionAirdropInfo).ReadyAudio, self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", (Info as ProductionAirdropInfo).ReadyAudio, self.Owner.Country.Race);
}));
a.QueueActivity(new Fly(a, Target.FromCell(endPos)));

View File

@@ -35,19 +35,19 @@ namespace OpenRA.Mods.RA.Render
var turret = self.TraitsImplementing<Turreted>()
.First(t => t.Name == info.Turret);
left = new Animation(name, () => turret.turretFacing);
left = new Animation(self.World, name, () => turret.turretFacing);
left.Play("left");
anims.Add("left", new AnimationWithOffset(left, null, () => facing.Facing > 128, 0));
right = new Animation(name, () => turret.turretFacing);
right = new Animation(self.World, name, () => turret.turretFacing);
right.Play("right");
anims.Add("right", new AnimationWithOffset(right, null, () => facing.Facing <= 128, 0));
var leftWake = new Animation(name);
var leftWake = new Animation(self.World, name);
leftWake.Play("wake-left");
anims.Add("wake-left", new AnimationWithOffset(leftWake, null, () => facing.Facing > 128, -87));
var rightWake = new Animation(name);
var rightWake = new Animation(self.World, name);
rightWake.Play("wake-right");
anims.Add("wake-right", new AnimationWithOffset(rightWake, null, () => facing.Facing <= 128, -87));

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
public class CncIngameChromeLogic
{
Widget ingameRoot;
World world;
readonly World world;
[ObjectCreator.UseCtor]
public CncIngameChromeLogic(Widget widget, World world)
@@ -95,7 +95,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
.Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive);
if (radarEnabled != cachedRadarEnabled)
Sound.PlayNotification(null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null);
cachedRadarEnabled = radarEnabled;
// Switch to observer mode after win/loss

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
// TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions
Action onQuit = () =>
{
Sound.PlayNotification(null, "Speech", "Leave", null);
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", null);
resumeDisabled = true;
Game.RunAfterDelay(1200, () => mpe.Fade(MenuPaletteEffect.EffectType.Black));
Game.RunAfterDelay(1200 + 40 * mpe.Info.FadeLength, () =>

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
public class CncInstallMusicLogic
{
[ObjectCreator.UseCtor]
public CncInstallMusicLogic(Widget widget, Action onExit)
public CncInstallMusicLogic(Widget widget, Ruleset modRules, Action onExit)
{
var installButton = widget.GetOrNull<ButtonWidget>("INSTALL_BUTTON");
if (installButton != null)
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
GlobalFileSystem.Mount(Path.Combine(path, "scores.mix"));
GlobalFileSystem.Mount(Path.Combine(path, "transit.mix"));
Rules.Music.Do(m => m.Value.Reload());
modRules.Music.Do(m => m.Value.Reload());
var musicPlayerLogic = (MusicPlayerLogic)installButton.Parent.LogicObject;
musicPlayerLogic.BuildMusicTable();
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
{ "filesToCopy", new[] { "SCORES.MIX" } },
{ "filesToExtract", new[] { "transit.mix" } },
});
installButton.IsVisible = () => Rules.InstalledMusic.ToArray().Length < 3; // HACK around music being split between transit.mix and scores.mix
installButton.IsVisible = () => modRules.InstalledMusic.ToArray().Length < 3; // HACK around music being split between transit.mix and scores.mix
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -16,7 +16,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
public class ProductionTabsLogic
{
ProductionTabsWidget tabs;
World world;
readonly World world;
void SetupProductionGroupButton(ProductionTypeButtonWidget button)
{

View File

@@ -23,6 +23,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
[ObjectCreator.UseCtor]
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette)
{
var mapRules = palette.World.Map.Rules;
var pm = palette.World.LocalPlayer.PlayerActor.Trait<PowerManager>();
var pr = palette.World.LocalPlayer.PlayerActor.Trait<PlayerResources>();
@@ -45,7 +46,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
if (actor == null || actor == lastActor)
return;
var info = Rules.Info[actor];
var info = mapRules.Actors[actor];
var tooltip = info.Traits.Get<TooltipInfo>();
var buildable = info.Traits.Get<BuildableInfo>();
var cost = info.Traits.Get<ValuedInfo>().Cost;
@@ -53,7 +54,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
nameLabel.GetText = () => tooltip.Name;
var prereqs = buildable.Prerequisites.Select(a => ActorName(a));
var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a));
var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : "";
requiresLabel.GetText = () => requiresString;
@@ -92,11 +93,10 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
};
}
static string ActorName(string a)
static string ActorName(Ruleset rules, string a)
{
ActorInfo ai;
Rules.Info.TryGetValue(a.ToLowerInvariant(), out ai);
if (ai != null && ai.Traits.Contains<TooltipInfo>())
if (rules.Actors.TryGetValue(a.ToLowerInvariant(), out ai) && ai.Traits.Contains<TooltipInfo>())
return ai.Traits.Get<TooltipInfo>().Name;
return a;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -72,9 +72,9 @@ namespace OpenRA.Mods.Cnc.Widgets
tooltipContainer = Exts.Lazy(() =>
Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
cantBuild = new Animation("clock");
cantBuild = new Animation(world, "clock");
cantBuild.PlayFetchIndex("idle", () => 0);
clock = new Animation("clock");
clock = new Animation(world, "clock");
}
public override void Tick()
@@ -114,7 +114,7 @@ namespace OpenRA.Mods.Cnc.Widgets
if (mi.Event != MouseInputEvent.Down)
return true;
var actor = Rules.Info[icon.Name];
var actor = World.Map.Rules.Actors[icon.Name];
var first = icon.Queued.FirstOrDefault();
if (mi.Button == MouseButton.Left)
@@ -135,7 +135,7 @@ namespace OpenRA.Mods.Cnc.Widgets
{
// Queue a new item
Sound.Play(TabClick);
Sound.PlayNotification(World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race);
Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race);
World.IssueOrder(Order.StartProduction(CurrentQueue.self, icon.Name,
Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1));
}
@@ -152,13 +152,13 @@ namespace OpenRA.Mods.Cnc.Widgets
// instant cancel of things we havent started yet and things that are finished
if (first.Paused || first.Done || first.TotalCost == first.RemainingCost)
{
Sound.PlayNotification(World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race);
Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race);
World.IssueOrder(Order.CancelProduction(CurrentQueue.self, icon.Name,
Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1));
}
else
{
Sound.PlayNotification(World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race);
Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race);
World.IssueOrder(Order.PauseProduction(CurrentQueue.self, icon.Name, true));
}
}
@@ -183,7 +183,7 @@ namespace OpenRA.Mods.Cnc.Widgets
var x = i % Columns;
var y = i / Columns;
var rect = new Rectangle(rb.X + x * 64 + 1, rb.Y + y * 48 + 1, 64, 48);
var icon = new Animation(RenderSimple.GetImage(item));
var icon = new Animation(World, RenderSimple.GetImage(item));
icon.Play(item.Traits.Get<TooltipInfo>().Icon);
var pi = new ProductionIcon()
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -60,6 +60,8 @@ namespace OpenRA.Mods.Cnc.Widgets
class ProductionTabsWidget : Widget
{
readonly World world;
public readonly string PaletteWidget = null;
public readonly string TypesContainer = null;
@@ -79,7 +81,9 @@ namespace OpenRA.Mods.Cnc.Widgets
[ObjectCreator.UseCtor]
public ProductionTabsWidget(World world)
{
Groups = Rules.Info.Values.SelectMany(a => a.Traits.WithInterface<ProductionQueueInfo>())
this.world = world;
Groups = world.Map.Rules.Actors.Values.SelectMany(a => a.Traits.WithInterface<ProductionQueueInfo>())
.Select(q => q.Group).Distinct().ToDictionary(g => g, g => new ProductionTabGroup() { Group = g });
// Only visible if the production palette has icons to display
@@ -93,7 +97,7 @@ namespace OpenRA.Mods.Cnc.Widgets
if (queueGroup == null)
return true;
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickSound", null);
// Prioritize alerted queues
var queues = Groups[queueGroup].Tabs.Select(t => t.Queue)
@@ -253,9 +257,9 @@ namespace OpenRA.Mods.Cnc.Widgets
if (leftPressed || rightPressed)
{
if ((leftPressed && !leftDisabled) || (rightPressed && !rightDisabled))
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickSound", null);
else
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickDisabledSound", null);
}
// Check production tabs
@@ -263,7 +267,7 @@ namespace OpenRA.Mods.Cnc.Widgets
if (offsetloc.X > 0 && offsetloc.X < contentWidth)
{
CurrentQueue = Groups[queueGroup].Tabs[offsetloc.X / (TabWidth - 1)].Queue;
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickSound", null);
}
return true;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -16,7 +16,10 @@ namespace OpenRA.Mods.Cnc.Widgets
{
public readonly string ProductionGroup;
public ProductionTypeButtonWidget() { }
[ObjectCreator.UseCtor]
public ProductionTypeButtonWidget(Ruleset modRules)
: base(modRules) { }
protected ProductionTypeButtonWidget(ProductionTypeButtonWidget other)
: base(other)
{

View File

@@ -52,8 +52,8 @@ namespace OpenRA.Mods.Cnc.Widgets
tooltipContainer = Exts.Lazy(() =>
Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
icon = new Animation("icon");
clock = new Animation("clock");
icon = new Animation(world, "icon");
clock = new Animation(world, "clock");
}
public class SupportPowerIcon

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Cnc
public WithFire(Actor self, WithFireInfo info)
{
var rs = self.Trait<RenderSprites>();
var roof = new Animation(rs.GetImage(self));
var roof = new Animation(self.World, rs.GetImage(self));
roof.PlayThen("fire-start", () => roof.PlayRepeating("fire-loop"));
rs.anims.Add("fire", new AnimationWithOffset(roof, null, null, 1024));
}

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Cnc
public WithRoof(Actor self)
{
var rs = self.Trait<RenderSprites>();
var roof = new Animation(rs.GetImage(self), () => self.Trait<IFacing>().Facing);
var roof = new Animation(self.World, rs.GetImage(self), () => self.Trait<IFacing>().Facing);
roof.Play("roof");
rs.anims.Add("roof", new AnimationWithOffset(roof, null, null, 1024));
}

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Cnc
{
this.info = info;
health = self.Trait<Health>();
weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()];
weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
}
public void AddedToWorld(Actor self)

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA.Render
buildComplete = !self.HasTrait<Building>(); // always render instantly for units
overlay = new Animation(rs.GetImage(self));
overlay = new Animation(self.World, rs.GetImage(self));
overlay.Play(info.Sequence);
rs.anims.Add("crane_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay,

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.RA.Render
if (!init.Contains<SkipMakeAnimsInit>())
{
var overlay = new Animation(rs.GetImage(init.self));
var overlay = new Animation(init.world, rs.GetImage(init.self));
overlay.PlayThen(info.Sequence, () => buildComplete = false);
rs.anims.Add("make_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay, null, () => !buildComplete));

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA.Render
buildComplete = !self.HasTrait<Building>(); // always render instantly for units
overlay = new Animation(rs.GetImage(self));
overlay = new Animation(self.World, rs.GetImage(self));
overlay.Play(info.Sequence);
rs.anims.Add("docking_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay,

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Render
buildComplete = !self.HasTrait<Building>(); // always render instantly for units
overlay = new Animation(rs.GetImage(self));
overlay = new Animation(self.World, rs.GetImage(self));
overlay.PlayRepeating(info.Sequence);
rs.anims.Add("production_overlay_{0}".F(info.Sequence),
new AnimationWithOffset(overlay,

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.D2k
{
foreach (var name in info.Weapons)
{
var wep = Rules.Weapons[name];
var wep = self.World.Map.Rules.Weapons[name];
var pieces = self.World.SharedRandom.Next(info.Pieces[0], info.Pieces[1]);
var range = self.World.SharedRandom.Next(info.Range[0].Range, info.Range[1].Range);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -68,9 +68,9 @@ namespace OpenRA.Mods.RA.AI
// Place the building
var type = BuildingType.Building;
if (Rules.Info[currentBuilding.Item].Traits.Contains<AttackBaseInfo>())
if (ai.Map.Rules.Actors[currentBuilding.Item].Traits.Contains<AttackBaseInfo>())
type = BuildingType.Defense;
else if (Rules.Info[currentBuilding.Item].Traits.Contains<OreRefineryInfo>())
else if (ai.Map.Rules.Actors[currentBuilding.Item].Traits.Contains<OreRefineryInfo>())
type = BuildingType.Refinery;
var location = ai.ChooseBuildLocation(currentBuilding.Item, type);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -83,7 +83,7 @@ namespace OpenRA.Mods.RA.AI
static object LoadBuildingLimits(MiniYaml y) { return LoadList<int>(y, "BuildingLimits"); }
public object Create(ActorInitializer init) { return new HackyAI(this); }
public object Create(ActorInitializer init) { return new HackyAI(this, init); }
}
public class Enemy { public int Aggro; }
@@ -119,15 +119,17 @@ namespace OpenRA.Mods.RA.AI
const int MaxBaseDistance = 40;
public const int feedbackTime = 30; // ticks; = a bit over 1s. must be >= netlag.
public World world { get { return p.PlayerActor.World; } }
public readonly World world;
public Map Map { get { return world.Map; } }
IBotInfo IBot.Info { get { return this.Info; } }
public HackyAI(HackyAIInfo info)
public HackyAI(HackyAIInfo info, ActorInitializer init)
{
Info = info;
world = init.world;
// Temporary hack.
rallypointTestBuilding = Rules.Info[Info.RallypointTestBuilding].Traits.Get<BuildingInfo>();
rallypointTestBuilding = Map.Rules.Actors[Info.RallypointTestBuilding].Traits.Get<BuildingInfo>();
}
public static void BotDebug(string s, params object[] args)
@@ -151,7 +153,7 @@ namespace OpenRA.Mods.RA.AI
random = new XRandom((int)p.PlayerActor.ActorID);
resourceTypes = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()
resourceTypes = Map.Rules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
.Select(t => t.TerrainType).ToArray();
}
@@ -185,8 +187,8 @@ namespace OpenRA.Mods.RA.AI
foreach (var unit in Info.UnitsToBuild)
if (buildableThings.Any(b => b.Name == unit.Key))
if (myUnits.Count(a => a == unit.Key) < unit.Value * myUnits.Length)
if (HasAdequateAirUnits(Rules.Info[unit.Key]))
return Rules.Info[unit.Key];
if (HasAdequateAirUnits(Map.Rules.Actors[unit.Key]))
return Map.Rules.Actors[unit.Key];
return null;
}
@@ -215,7 +217,7 @@ namespace OpenRA.Mods.RA.AI
ActorInfo GetBuildingInfoByCommonName(string commonName, Player owner)
{
if (commonName == "ConstructionYard")
return Rules.Info.Where(k => Info.BuildingCommonNames[commonName].Contains(k.Key)).Random(random).Value;
return Map.Rules.Actors.Where(k => Info.BuildingCommonNames[commonName].Contains(k.Key)).Random(random).Value;
return GetInfoByCommonName(Info.BuildingCommonNames, commonName, owner);
}
@@ -230,7 +232,7 @@ namespace OpenRA.Mods.RA.AI
if (!names.Any() || !names.ContainsKey(commonName))
return null;
return Rules.Info.Where(k => names[commonName].Contains(k.Key) &&
return Map.Rules.Actors.Where(k => names[commonName].Contains(k.Key) &&
k.Value.Traits.Get<BuildableInfo>().Owner.Contains(owner.Country.Race)).Random(random).Value;
}
@@ -314,8 +316,8 @@ namespace OpenRA.Mods.RA.AI
foreach (var frac in Info.BuildingFractions)
if (buildableThings.Any(b => b.Name == frac.Key))
if (myBuildings.Count(a => a == frac.Key) < frac.Value * myBuildings.Length && HasAdequateNumber(frac.Key, p) &&
playerPower.ExcessPower >= Rules.Info[frac.Key].Traits.Get<BuildingInfo>().Power)
return Rules.Info[frac.Key];
playerPower.ExcessPower >= Map.Rules.Actors[frac.Key].Traits.Get<BuildingInfo>().Power)
return Map.Rules.Actors[frac.Key];
return null;
}
@@ -334,7 +336,7 @@ namespace OpenRA.Mods.RA.AI
public CPos? ChooseBuildLocation(string actorType, bool distanceToBaseIsImportant, int maxBaseDistance, BuildingType type)
{
var bi = Rules.Info[actorType].Traits.GetOrDefault<BuildingInfo>();
var bi = Map.Rules.Actors[actorType].Traits.GetOrDefault<BuildingInfo>();
if (bi == null)
return null;
@@ -348,7 +350,7 @@ namespace OpenRA.Mods.RA.AI
foreach (var t in tlist)
if (world.CanPlaceBuilding(actorType, bi, t, null))
if (bi.IsCloseEnoughToBase(world, p, actorType, t))
if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(actorType, bi, t), false)))
if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(Map.Rules, actorType, bi, t), false)))
return t;
}
@@ -377,7 +379,7 @@ namespace OpenRA.Mods.RA.AI
if (distanceToBaseIsImportant && !bi.IsCloseEnoughToBase(world, p, actorType, t))
continue;
if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(actorType, bi, t), false)))
if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(Map.Rules, actorType, bi, t), false)))
return t;
}
}
@@ -850,7 +852,7 @@ namespace OpenRA.Mods.RA.AI
if (queue == null)
return;
if (Rules.Info[name] != null)
if (Map.Rules.Actors[name] != null)
world.IssueOrder(Order.StartProduction(queue.self, name, 1));
}

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA
public void Killed(Actor self, AttackInfo e)
{
var player = (info.NotifyAll) ? self.World.LocalPlayer : self.Owner;
Sound.PlayNotification(player, "Speech", info.Notification, self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, player, "Speech", info.Notification, self.Owner.Country.Race);
}
}
}

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Mods.RA
Coords = Exts.Lazy(() => self.Trait<IBodyOrientation>());
limitedAmmo = Exts.Lazy(() => self.TraitOrDefault<LimitedAmmo>());
Weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()];
Weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
Burst = Weapon.Burst;
if (info.LocalOffset.Length % 3 != 0)

View File

@@ -157,7 +157,7 @@ namespace OpenRA.Mods.RA
if (barrel != null && a.Info.MuzzleSequence != null)
{
// Muzzle facing is fixed once the firing starts
var muzzleAnim = new Animation(paxRender[a.Actor].GetImage(a.Actor), () => muzzleFacing);
var muzzleAnim = new Animation(self.World, paxRender[a.Actor].GetImage(a.Actor), () => muzzleFacing);
var sequence = a.Info.MuzzleSequence;
if (a.Info.MuzzleSplitFacings > 0)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA
// Build a list of templates that should be overlayed with bridges
foreach(var bridge in Info.Bridges)
{
var bi = Rules.Info[bridge].Traits.Get<BridgeInfo>();
var bi = w.Map.Rules.Actors[bridge].Traits.Get<BridgeInfo>();
foreach (var template in bi.Templates)
BridgeTypes.Add(template.First, Pair.New(bridge, template.Second));
}

View File

@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Buildings
for (var i = 0; i < rows * width; i++)
{
var index = i;
var anim = new Animation(rs.GetImage(self));
var anim = new Animation(self.World, rs.GetImage(self));
var cellOffset = new CVec(i % width, i / width + bibOffset);
// Some mods may define terrain-specific bibs

6
OpenRA.Mods.RA/Buildings/Building.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -65,7 +65,7 @@ namespace OpenRA.Mods.RA.Buildings
return false;
var buildingMaxBounds = (CVec)Dimensions;
var buildingTraits = Rules.Info[buildingName].Traits;
var buildingTraits = world.Map.Rules.Actors[buildingName].Traits;
if (buildingTraits.Contains<BibInfo>() && !(buildingTraits.Get<BibInfo>().HasMinibib))
buildingMaxBounds += new CVec(0, 1);
@@ -91,7 +91,7 @@ namespace OpenRA.Mods.RA.Buildings
}
}
var buildingTiles = FootprintUtils.Tiles(buildingName, this, topLeft).ToList();
var buildingTiles = FootprintUtils.Tiles(world.Map.Rules, buildingName, this, topLeft).ToList();
return nearnessCandidates
.Any(a => buildingTiles
.Any(b => Math.Abs(a.X - b.X) <= Adjacent

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Buildings
if (b == null)
return;
foreach (var u in FootprintUtils.Tiles(a.Info.Name, b.Info, a.Location))
foreach (var u in FootprintUtils.Tiles(map.Rules, a.Info.Name, b.Info, a.Location))
if (map.IsInMap(u) && influence[u.X, u.Y] == null)
influence[u.X, u.Y] = a;
};
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA.Buildings
if (b == null)
return;
foreach (var u in FootprintUtils.Tiles(a.Info.Name, b.Info, a.Location))
foreach (var u in FootprintUtils.Tiles(map.Rules, a.Info.Name, b.Info, a.Location))
if (map.IsInMap(u) && influence[u.X, u.Y] == a)
influence[u.X, u.Y] = null;
};

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA.Buildings
if (order.OrderString == "PowerDown")
{
disabled = !disabled;
Sound.PlayNotification(self.Owner, "Sounds", (disabled ? "EnablePower" : "DisablePower"), self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", (disabled ? "EnablePower" : "DisablePower"), self.Owner.Country.Race);
PowerManager.UpdateActor(self, disabled ? 0 : normalPower);
if (disabled)

8
OpenRA.Mods.RA/Buildings/FootprintUtils.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -16,13 +16,13 @@ namespace OpenRA.Mods.RA.Buildings
{
public static class FootprintUtils
{
public static IEnumerable<CPos> Tiles(string name, BuildingInfo buildingInfo, CPos topLeft)
public static IEnumerable<CPos> Tiles(Ruleset rules, string name, BuildingInfo buildingInfo, CPos topLeft)
{
var dim = (CVec)buildingInfo.Dimensions;
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x));
var buildingTraits = Rules.Info[name].Traits;
var buildingTraits = rules.Actors[name].Traits;
if (buildingTraits.Contains<BibInfo>() && !(buildingTraits.Get<BibInfo>().HasMinibib))
{
dim += new CVec(0, 1);
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Buildings
public static IEnumerable<CPos> Tiles(Actor a)
{
return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location );
return Tiles(a.World.Map.Rules, a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location);
}
public static IEnumerable<CPos> UnpathableTiles(string name, BuildingInfo buildingInfo, CPos position)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -108,7 +108,7 @@ namespace OpenRA.Mods.RA.Buildings
if (--nextPowerAdviceTime <= 0)
{
if (lowPower)
Sound.PlayNotification(self.Owner, "Speech", "LowPower", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "LowPower", self.Owner.Country.Race);
nextPowerAdviceTime = Info.AdviceInterval;
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Buildings
else
{
Repairer = p;
Sound.PlayNotification(Repairer, "Speech", "Repairing", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, Repairer, "Speech", "Repairing", self.Owner.Country.Race);
self.World.AddFrameEndTask(
w => w.Add(new RepairIndicator(self, Info.IndicatorPalettePrefix, p)));

6
OpenRA.Mods.RA/Buildings/Util.cs Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -35,14 +35,14 @@ namespace OpenRA.Mods.RA.Buildings
return true;
var res = world.WorldActor.Trait<ResourceLayer>();
return FootprintUtils.Tiles(name, building, topLeft).All(
return FootprintUtils.Tiles(world.Map.Rules, name, building, topLeft).All(
t => world.Map.IsInMap(t.X, t.Y) && res.GetResource(t) == null &&
world.IsCellBuildable(t, building, toIgnore));
}
public static IEnumerable<CPos> GetLineBuildCells(World world, CPos location, string name, BuildingInfo bi)
{
var lbi = Rules.Info[name].Traits.Get<LineBuildInfo>();
var lbi = world.Map.Rules.Actors[name].Traits.Get<LineBuildInfo>();
var topLeft = location; // 1x1 assumption!
if (world.IsCellBuildable(topLeft, bi))

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA
{
Info = info;
var anim = new Animation("fire", () => 0);
var anim = new Animation(self.World, "fire", () => 0);
anim.IsDecoration = true;
anim.PlayRepeating(Info.Anim);
self.Trait<RenderSprites>().anims.Add("fire", anim);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA
return;
var race = info.NewOwnerVoice ? newOwner.Country.Race : oldOwner.Country.Race;
Sound.PlayNotification(captor.World.LocalPlayer, "Speech", info.Notification, race);
Sound.PlayNotification(self.World.Map.Rules, captor.World.LocalPlayer, "Speech", info.Notification, race);
}
}
}

View File

@@ -158,7 +158,7 @@ namespace OpenRA.Mods.RA
public static void DoExplosion(Actor attacker, string weapontype, WPos pos)
{
var weapon = Rules.Weapons[weapontype.ToLowerInvariant()];
var weapon = attacker.World.Map.Rules.Weapons[weapontype.ToLowerInvariant()];
if (weapon.Report != null && weapon.Report.Any())
Sound.Play(weapon.Report.Random(attacker.World.SharedRandom), pos);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.RA
Game.RunAfterDelay(Info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(self.World))
Sound.PlayNotification(self.Owner, "Speech", "Lose", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Lose", self.Owner.Country.Race);
});
}
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA
Game.Debug("{0} is victorious.".F(self.Owner.PlayerName));
if (self.Owner == self.World.LocalPlayer)
Game.RunAfterDelay(Info.NotificationDelay, () => Sound.PlayNotification(self.Owner, "Speech", "Win", self.Owner.Country.Race));
Game.RunAfterDelay(Info.NotificationDelay, () => Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Win", self.Owner.Country.Race));
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA
{
var crate = w.CreateActor(false, crateActor, new TypeDictionary { new OwnerInit(w.WorldActor.Owner) });
var startPos = w.ChooseRandomEdgeCell();
var altitude = Rules.Info[info.DeliveryAircraft].Traits.Get<PlaneInfo>().CruiseAltitude;
var altitude = self.World.Map.Rules.Actors[info.DeliveryAircraft].Traits.Get<PlaneInfo>().CruiseAltitude;
var plane = w.CreateActor(info.DeliveryAircraft, new TypeDictionary
{
new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Crates
public bool CanGiveTo(Actor collector)
{
var bi = Rules.Info[Info.Unit].Traits.GetOrDefault<BuildableInfo>();
var bi = self.World.Map.Rules.Actors[Info.Unit].Traits.GetOrDefault<BuildableInfo>();
// this unit is not buildable by the collector's country, so
// don't give them free ones either.
@@ -68,7 +68,7 @@ namespace OpenRA.Mods.RA.Crates
IEnumerable<CPos> GetSuitableCells(CPos near)
{
var mi = Rules.Info[Info.Unit].Traits.Get<MobileInfo>();
var mi = self.World.Map.Rules.Actors[Info.Unit].Traits.Get<MobileInfo>();
for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++)

View File

@@ -21,8 +21,8 @@ namespace OpenRA.Mods.RA.Effects
readonly WPos position;
readonly string palettePrefix;
readonly string posterPalette;
readonly Animation arrow = new Animation("beacon");
readonly Animation circles = new Animation("beacon");
readonly Animation arrow;
readonly Animation circles;
readonly Animation poster;
static readonly int maxArrowHeight = 512;
int arrowHeight = maxArrowHeight;
@@ -35,12 +35,15 @@ namespace OpenRA.Mods.RA.Effects
this.palettePrefix = palettePrefix;
this.posterPalette = posterPalette;
arrow = new Animation(owner.World, "beacon");
circles = new Animation(owner.World, "beacon");
arrow.Play("arrow");
circles.Play("circles");
if (posterType != null)
{
poster = new Animation("beacon");
poster = new Animation(owner.World, "beacon");
poster.Play(posterType);
}

View File

@@ -66,6 +66,8 @@ namespace OpenRA.Mods.RA.Effects
this.args = args;
this.pos = args.Source;
var world = args.SourceActor.World;
if (info.Angle.Length > 1 && info.Speed.Length > 1)
{
angle = new WAngle(args.SourceActor.World.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle));
@@ -89,7 +91,7 @@ namespace OpenRA.Mods.RA.Effects
if (info.Image != null)
{
anim = new Animation(info.Image, GetEffectiveFacing);
anim = new Animation(world, info.Image, GetEffectiveFacing);
anim.PlayRepeating("idle");
}

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Effects
this.pos = pos;
this.cell = pos.ToCPos();
this.paletteName = paletteName;
anim = new Animation(image);
anim = new Animation(world, image);
anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this)));
}

View File

@@ -17,13 +17,15 @@ namespace OpenRA.Mods.RA.Effects
class CrateEffect : IEffect
{
readonly string palette;
Actor a;
Animation anim = new Animation("crate-effects");
readonly Actor a;
readonly Animation anim;
public CrateEffect(Actor a, string seq, string palette)
{
this.a = a;
this.palette = palette;
anim = new Animation(a.World, "crate-effects");
anim.PlayThen(seq, () => a.World.AddFrameEndTask(w => w.Remove(this)));
}

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Effects
this.pos = pos;
this.cell = pos.ToCPos();
this.palette = palette;
anim = new Animation("explosion");
anim = new Animation(world, "explosion");
anim.PlayThen(sequence, () => world.AddFrameEndTask(w => w.Remove(this)));
}

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Effects
{
this.self = self;
this.info = info;
anim = new Animation("gpsdot");
anim = new Animation(self.World, "gpsdot");
anim.PlayRepeating(info.String);
self.World.AddFrameEndTask(w => w.Add(this));

View File

@@ -16,27 +16,29 @@ namespace OpenRA.Mods.RA.Effects
{
class GpsSatellite : IEffect
{
WPos Pos;
Animation Anim = new Animation("sputnik");
WPos pos;
readonly Animation anim;
public GpsSatellite(WPos pos)
public GpsSatellite(World world, WPos pos)
{
Pos = pos;
Anim.PlayRepeating("idle");
this.pos = pos;
anim = new Animation(world, "sputnik");
anim.PlayRepeating("idle");
}
public void Tick( World world )
{
Anim.Tick();
Pos += new WVec(0, 0, 427);
anim.Tick();
pos += new WVec(0, 0, 427);
if (Pos.Z > Pos.Y)
if (pos.Z > pos.Y)
world.AddFrameEndTask(w => w.Remove(this));
}
public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
return Anim.Render(Pos, wr.Palette("effect"));
return anim.Render(pos, wr.Palette("effect"));
}
}
}

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Effects
pos = args.Source;
velocity = new WVec(WRange.Zero, WRange.Zero, -info.Velocity);
anim = new Animation(info.Image);
anim = new Animation(args.SourceActor.World, info.Image);
if (anim.HasSequence("open"))
anim.PlayThen("open", () => anim.PlayRepeating("idle"));
else

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA.Effects
this.target = args.PassiveTarget;
if (info.HitAnim != null)
this.hitanim = new Animation(info.HitAnim);
this.hitanim = new Animation(args.SourceActor.World, info.HitAnim);
}
public void Tick(World world)

View File

@@ -88,7 +88,7 @@ namespace OpenRA.Mods.RA.Effects
if (info.Image != null)
{
anim = new Animation(info.Image, () => facing);
anim = new Animation(args.SourceActor.World, info.Image, () => facing);
anim.PlayRepeating("idle");
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -45,11 +45,11 @@ namespace OpenRA.Mods.RA.Effects
descendSource = targetPos + offset;
descendTarget = targetPos;
anim = new Animation(weapon);
anim = new Animation(firedBy.World, weapon);
anim.PlayRepeating("up");
pos = launchPos;
var weaponRules = Rules.Weapons[weapon.ToLowerInvariant()];
var weaponRules = firedBy.World.Map.Rules.Weapons[weapon.ToLowerInvariant()];
if (weaponRules.Report != null && weaponRules.Report.Any())
Sound.Play(weaponRules.Report.Random(firedBy.World.SharedRandom), pos);

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Effects
this.cargo = cargo;
var pai = cargo.Info.Traits.GetOrDefault<ParachuteAttachmentInfo>();
paraAnim = new Animation(pai != null ? pai.ParachuteSprite : "parach");
paraAnim = new Animation(cargo.World, pai != null ? pai.ParachuteSprite : "parach");
paraAnim.PlayThen("open", () => paraAnim.PlayRepeating("idle"));
if (pai != null)

View File

@@ -18,12 +18,15 @@ namespace OpenRA.Mods.RA.Effects
{
class PowerdownIndicator : IEffect
{
Actor a;
Animation anim = new Animation("poweroff");
readonly Actor a;
readonly Animation anim;
public PowerdownIndicator(Actor a)
{
this.a = a; anim.PlayRepeating("offline");
this.a = a;
anim = new Animation(a.World, "poweroff");
anim.PlayRepeating("offline");
}
public void Tick(World world)

View File

@@ -21,14 +21,19 @@ namespace OpenRA.Mods.RA.Effects
readonly Actor building;
readonly RA.RallyPoint rp;
readonly string palettePrefix;
public Animation flag = new Animation("rallypoint");
public Animation circles = new Animation("rallypoint");
readonly Animation flag;
readonly Animation circles;
public RallyPoint(Actor building, string palettePrefix)
{
this.building = building;
rp = building.Trait<RA.RallyPoint>();
this.palettePrefix = palettePrefix;
rp = building.Trait<RA.RallyPoint>();
flag = new Animation(building.World, "rallypoint");
circles = new Animation(building.World, "rallypoint");
flag.PlayRepeating("flag");
circles.Play("circles");
}

View File

@@ -17,16 +17,17 @@ namespace OpenRA.Mods.RA.Effects
{
class Rank : IEffect
{
Actor self;
Animation anim = new Animation("rank");
readonly Actor self;
readonly Animation anim;
readonly string paletteName;
public Rank(Actor self, string paletteName)
{
this.self = self;
this.paletteName = paletteName;
var xp = self.Trait<GainsExperience>();
var xp = self.Trait<GainsExperience>();
anim = new Animation(self.World, "rank");
anim.PlayRepeating("rank");
anim.PlayFetchIndex("rank", () => xp.Level == 0 ? 0 : xp.Level - 1);
}

View File

@@ -18,18 +18,20 @@ namespace OpenRA.Mods.RA.Effects
{
class RepairIndicator : IEffect
{
Actor building;
Player player;
string palettePrefix;
Animation anim = new Animation("allyrepair");
RepairableBuilding rb;
readonly Actor building;
readonly Player player;
readonly string palettePrefix;
readonly Animation anim;
readonly RepairableBuilding rb;
public RepairIndicator(Actor building, string palettePrefix, Player player)
{
this.building = building;
this.player = player;
this.palettePrefix = palettePrefix;
rb = building.Trait<RepairableBuilding>();
anim = new Animation(building.World, "allyrepair");
anim.PlayRepeating("repair");
}

View File

@@ -17,11 +17,13 @@ namespace OpenRA.Mods.RA.Effects
class SatelliteLaunch : IEffect
{
int frame = 0;
Animation doors = new Animation("atek");
WPos pos;
readonly Animation doors;
readonly WPos pos;
public SatelliteLaunch(Actor a)
{
doors = new Animation(a.World, "atek");
doors.PlayThen("active",
() => a.World.AddFrameEndTask(w => w.Remove(this)));
@@ -33,7 +35,7 @@ namespace OpenRA.Mods.RA.Effects
doors.Tick();
if (++frame == 19)
world.AddFrameEndTask(w => w.Add(new GpsSatellite(pos)));
world.AddFrameEndTask(w => w.Add(new GpsSatellite(world, pos)));
}
public IEnumerable<IRenderable> Render(WorldRenderer wr)

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