Refactoring to remove static Rules & SequenceProvider

This commit is contained in:
Pavlos Touboulidis
2014-05-05 02:43:08 +03:00
parent c68427eaa6
commit 63ec6d60e7
114 changed files with 914 additions and 615 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(ModInformation.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.AddStaticResources(tileSet, surface1.Map, Minimap.TerrainBitmap(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.AddStaticResources(tileset, surface1.Map, Minimap.TerrainBitmap(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.AddStaticResources(tileset, map, Minimap.TerrainBitmap(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,6 +19,8 @@ namespace OpenRA.Editor
{
static class Program
{
public static MapRuleset Rules;
[STAThread]
static void Main(string[] args)
{

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

@@ -117,6 +117,7 @@ namespace OpenRA
}, parent, id);
}
// TODO: Delayed actions shouldn't be static or at least should be cleared when the map/world is changed
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 +152,11 @@ namespace OpenRA
using (new PerfSample("render_widgets"))
{
Ui.Draw();
var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default";
CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame);
if (modData != null && modData.CursorProvider != null)
{
var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default";
modData.CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame);
}
}
using (new PerfSample("render_flip"))
@@ -248,6 +252,7 @@ namespace OpenRA
BeforeGameStart();
Map map;
using (new PerfTimer("PrepareMap"))
map = modData.PrepareMap(mapUID);
using (new PerfTimer("NewWorld"))
@@ -354,7 +359,7 @@ namespace OpenRA
}
Console.WriteLine("Available mods:");
foreach (var mod in Mod.AllMods)
foreach (var mod in ModInformation.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 +384,7 @@ namespace OpenRA
orderManager.Dispose();
// Fall back to default if the mod doesn't exist
if (!Mod.AllMods.ContainsKey(mod))
if (!ModInformation.AllMods.ContainsKey(mod))
mod = new GameSettings().Mod;
Console.WriteLine("Loading mod: {0}", mod);

View File

@@ -17,34 +17,10 @@ using OpenRA.Support;
namespace OpenRA
{
public static class Rules
{
public static Dictionary<string, ActorInfo> Info { get { return Game.modData.Rules.Actors; } }
public static Dictionary<string, WeaponInfo> Weapons { get { return Game.modData.Rules.Weapons; } }
public static Dictionary<string, SoundInfo> Voices { get { return Game.modData.Rules.Voices; } }
public static Dictionary<string, SoundInfo> Notifications { get { return Game.modData.Rules.Notifications; } }
public static Dictionary<string, MusicInfo> Music { get { return Game.modData.Rules.Music; } }
public static Dictionary<string, string> Movies { get { return Game.modData.Rules.Movies; } }
public static Dictionary<string, TileSet> TileSets { get { return Game.modData.Rules.TileSets; } }
public static void LoadRules(Manifest m, Map map)
{
// HACK: Fallback for code that hasn't been updated yet
Game.modData.Rules = new ModRules(Game.modData);
Game.modData.Rules.ActivateMap(map);
}
public static IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
}
public class ModRules
public class RulesetCache
{
readonly ModData modData;
//
// These contain all unique instances created from each mod/map combination
//
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>();
@@ -53,40 +29,60 @@ namespace OpenRA
readonly Dictionary<string, string> movieCache = new Dictionary<string, string>();
readonly Dictionary<string, TileSet> tileSetCache = new Dictionary<string, TileSet>();
//
// These are the instances needed for the current map
//
public Dictionary<string, ActorInfo> Actors { get; private set; }
public Dictionary<string, WeaponInfo> Weapons { get; private set; }
public Dictionary<string, SoundInfo> Voices { get; private set; }
public Dictionary<string, SoundInfo> Notifications { get; private set; }
public Dictionary<string, MusicInfo> Music { get; private set; }
public Dictionary<string, string> Movies { get; private set; }
public Dictionary<string, TileSet> TileSets { get; private set; }
public Action OnProgress = () => { if (Game.modData != null && Game.modData.LoadScreen != null) Game.modData.LoadScreen.Display(); };
public ModRules(ModData modData)
public RulesetCache(ModData modData)
{
this.modData = modData;
}
public void ActivateMap(Map map)
public ModRuleset LoadModRules()
{
var m = modData.Manifest;
using (new PerfTimer("Actors"))
Actors = LoadYamlRules(actorCache, m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
using (new PerfTimer("Weapons"))
Weapons = LoadYamlRules(weaponCache, m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
using (new PerfTimer("Voices"))
Voices = LoadYamlRules(voiceCache, m.Voices, map.Voices, (k, _) => new SoundInfo(k.Value));
using (new PerfTimer("Notifications"))
Notifications = LoadYamlRules(notificationCache, m.Notifications, map.Notifications, (k, _) => new SoundInfo(k.Value));
Dictionary<string, MusicInfo> music;
Dictionary<string, string> movies;
Dictionary<string, TileSet> tileSets;
using (new PerfTimer("Music"))
Music = LoadYamlRules(musicCache, m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
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);
movies = LoadYamlRules(movieCache, m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
using (new PerfTimer("TileSets"))
TileSets = LoadTileSets(tileSetCache, m.TileSets);
tileSets = LoadTileSets(tileSetCache, m.TileSets);
return new ModRuleset(music, movies, tileSets);
}
public MapRuleset LoadDefaultRules()
{
return LoadMapRules(new Map());
}
public MapRuleset LoadMapRules(Map map)
{
var m = modData.Manifest;
Dictionary<string, ActorInfo> actors;
Dictionary<string, WeaponInfo> weapons;
Dictionary<string, SoundInfo> voices;
Dictionary<string, SoundInfo> notifications;
OnProgress();
using (new PerfTimer("Actors"))
actors = LoadYamlRules(actorCache, m.Rules, map.RuleDefinitions, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
OnProgress();
using (new PerfTimer("Weapons"))
weapons = LoadYamlRules(weaponCache, m.Weapons, map.WeaponDefinitions, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
OnProgress();
using (new PerfTimer("Voices"))
voices = LoadYamlRules(voiceCache, m.Voices, map.VoiceDefinitions, (k, _) => new SoundInfo(k.Value));
OnProgress();
using (new PerfTimer("Notifications"))
notifications = LoadYamlRules(notificationCache, m.Notifications, map.NotificationDefinitions, (k, _) => new SoundInfo(k.Value));
OnProgress();
return new MapRuleset(LoadModRules(), actors, weapons, voices, notifications);
}
Dictionary<string, T> LoadYamlRules<T>(
@@ -131,7 +127,7 @@ namespace OpenRA
}
else
{
t = new TileSet(file);
t = new TileSet(modData, file);
itemCache.Add(file, t);
items.Add(t.Id, t);

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,
@@ -28,6 +28,9 @@ namespace OpenRA.Graphics
public string Name { get { return name; } }
readonly SequenceProvider sequenceProvider;
static SequenceProvider lastSequenceProvider;
public Animation(string name)
: this(name, () => 0) {}
@@ -36,6 +39,17 @@ namespace OpenRA.Graphics
this.name = name.ToLowerInvariant();
this.tickFunc = () => {};
this.facingFunc = facingFunc;
// TODO: This is wrong, don't use the static
if (Game.orderManager != null && Game.orderManager.world != null && Game.orderManager.world.Map != null)
sequenceProvider = Game.orderManager.world.Map.SequenceProvider;
// HACK: This just makes sure we have a sequence provider in between map changes for delayed actions
// It sucks but it can only be removed when we don't use the statics above but replace them with
// a possible parameter on this constructor.
if (sequenceProvider == null)
sequenceProvider = lastSequenceProvider;
else
lastSequenceProvider = sequenceProvider;
}
int CurrentFrame { get { return backwards ? CurrentSequence.Start + CurrentSequence.Length - frame - 1 : frame; } }
@@ -66,7 +80,7 @@ namespace OpenRA.Graphics
{
backwards = false;
tickAlways = false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = 0;
tickFunc = () =>
{
@@ -81,7 +95,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 +104,7 @@ namespace OpenRA.Graphics
{
backwards = false;
tickAlways = false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
frame = 0;
tickFunc = () =>
{
@@ -114,7 +128,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 +142,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 +173,7 @@ namespace OpenRA.Graphics
public Sequence GetSequence(string sequenceName)
{
return SequenceProvider.GetSequence(name, sequenceName);
return sequenceProvider.GetSequence(name, sequenceName);
}
}
}

View File

@@ -16,23 +16,18 @@ 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 Action OnProgress = () => { if (Game.modData != null && Game.modData.LoadScreen != null) Game.modData.LoadScreen.Display(); };
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 +44,37 @@ 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)
{
OnProgress();
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 +86,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)
public static Bitmap AddStaticResources(TileSet tileset, Map map, 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 = map.Rules.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,10 @@ 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);
Bitmap terrain = TerrainBitmap(tileset, map, actualSize);
return AddStaticResources(tileset, map, 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

@@ -17,102 +17,101 @@ using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public static class SequenceProvider
public class SequenceProvider
{
public static Sequence GetSequence(string unitName, string sequenceName)
readonly Lazy<IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>> sequences;
public SequenceProvider(Map map)
{
return Game.modData.SequenceProvider.GetSequence(unitName, sequenceName);
this.sequences = Exts.Lazy(() => map.Rules.TileSets[map.Tileset].Data.SequenceCache.LoadSequences(map));
}
public static bool HasSequence(string unitName, string sequenceName)
public Sequence GetSequence(string unitName, string sequenceName)
{
return Game.modData.SequenceProvider.HasSequence(unitName, sequenceName);
try
{
return sequences.Value[unitName].Value[sequenceName];
}
catch (KeyNotFoundException)
{
if (sequences.Value.ContainsKey(unitName))
throw new InvalidOperationException("Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
else
throw new InvalidOperationException("Unit `{0}` does not have all sequences defined.".F(unitName));
}
}
public static IEnumerable<string> Sequences(string unitName)
public bool HasSequence(string unitName, string sequenceName)
{
return Game.modData.SequenceProvider.Sequences(unitName);
if (!sequences.Value.ContainsKey(unitName))
throw new InvalidOperationException("Unit `{0}` does not have sequence `{1}` defined.".F(unitName, sequenceName));
return sequences.Value[unitName].Value.ContainsKey(sequenceName);
}
public IEnumerable<string> Sequences(string unitName)
{
if (!sequences.Value.ContainsKey(unitName))
throw new InvalidOperationException("Unit `{0}` does not have all sequences defined.".F(unitName));
return sequences.Value[unitName].Value.Keys;
}
}
public class ModSequenceProvider
public class SequenceCache
{
readonly ModData modData;
readonly TileSet tileSet;
readonly Dictionary<string, Lazy<Dictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<Dictionary<string, Sequence>>>();
Dictionary<string, Lazy<Dictionary<string, Sequence>>> sequences;
readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
public ModSequenceProvider(ModData modData)
public Action OnProgress = () => { if (Game.modData != null && Game.modData.LoadScreen != null) Game.modData.LoadScreen.Display(); };
public SequenceCache(ModData modData, TileSet tileSet)
{
this.modData = modData;
this.tileSet = tileSet;
}
public void ActivateMap(Map map)
public IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> LoadSequences(Map map)
{
sequences = Load(modData.Manifest.Sequences, map.Tileset, map.Sequences);
using (new Support.PerfTimer("LoadSequences"))
return Load(map.SequenceDefinitions);
}
public Dictionary<string, Lazy<Dictionary<string, Sequence>>> Load(string[] sequenceFiles, string tileset, List<MiniYamlNode> sequenceNodes)
IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes)
{
Game.modData.LoadScreen.Display();
OnProgress();
var sequenceFiles = modData.Manifest.Sequences;
var nodes = sequenceFiles
.Select(s => MiniYaml.FromFile(s))
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
var items = new Dictionary<string, Lazy<Dictionary<string, Sequence>>>();
var items = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
foreach (var node in nodes)
{
// Sequence loading uses the active SpriteLoader that depends on the current map's tileset
var key = node.Value.ToLines(node.Key).JoinWith("|");
var key = tileset + node.Value.ToLines(node.Key).JoinWith("|");
Lazy<Dictionary<string, Sequence>> t;
Lazy<IReadOnlyDictionary<string, Sequence>> t;
if (sequenceCache.TryGetValue(key, out t))
{
items.Add(node.Key, t);
}
else
{
t = Exts.Lazy(() => node.Value.NodesDict.ToDictionary(x => x.Key, x => new Sequence(node.Key, x.Key, x.Value)));
t = Exts.Lazy(() => (IReadOnlyDictionary<string, Sequence>)new ReadOnlyDictionary<string, Sequence>(
node.Value.NodesDict.ToDictionary(x => x.Key, x =>
new Sequence(tileSet.Data.SpriteLoader, node.Key, x.Key, x.Value))));
sequenceCache.Add(key, t);
items.Add(node.Key, t);
}
OnProgress();
}
return items;
}
public Sequence GetSequence(string unitName, string sequenceName)
{
try { return sequences[unitName].Value[sequenceName]; }
catch (KeyNotFoundException)
{
if (sequences.ContainsKey(unitName))
throw new InvalidOperationException(
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
else
throw new InvalidOperationException(
"Unit `{0}` does not have all sequences defined.".F(unitName));
}
}
public bool HasSequence(string unitName, string sequenceName)
{
if (!sequences.ContainsKey(unitName))
throw new InvalidOperationException(
"Unit `{0}` does not have sequence `{1}` defined.".F(unitName, sequenceName));
return sequences[unitName].Value.ContainsKey(sequenceName);
}
public IEnumerable<string> Sequences(string unitName)
{
if (!sequences.ContainsKey(unitName))
throw new InvalidOperationException(
"Unit `{0}` does not have all sequences defined.".F(unitName));
return sequences[unitName].Value.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 ModInformation 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<ModInformation>(yaml["Metadata"]);
Mod.Id = mod;
// TODO: Use fieldloader

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<MapRuleset> rules;
public MapRuleset Rules { get { return rules != null ? rules.Value : null; } }
public SequenceProvider SequenceProvider { get; private set; }
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,19 @@ 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));
SequenceProvider = new SequenceProvider(this);
}
public MapRuleset PreloadRules()
{
return rules.Value;
}
public CPos[] GetSpawnPoints()
@@ -282,13 +301,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 +471,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 +508,10 @@ namespace OpenRA
});
}
public void FixOpenAreas()
public void FixOpenAreas(MapRuleset 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.ModRules.TileSets[p.Map.Tileset], p.Map, true);
p.Minimap = sheetBuilder.Add(bitmap);
lock (syncRoot)

View File

@@ -0,0 +1,65 @@
#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;
namespace OpenRA
{
public class ModRuleset
{
public readonly IReadOnlyDictionary<string, MusicInfo> Music;
public readonly IReadOnlyDictionary<string, string> Movies;
public readonly IReadOnlyDictionary<string, TileSet> TileSets;
public ModRuleset(ModRuleset other)
{
this.Music = other.Music;
this.Movies = other.Movies;
this.TileSets = other.TileSets;
}
public ModRuleset(
IDictionary<string, MusicInfo> music,
IDictionary<string, string> movies,
IDictionary<string, TileSet> tileSets)
{
this.Music = new ReadOnlyDictionary<string, MusicInfo>(music);
this.Movies = new ReadOnlyDictionary<string, string>(movies);
this.TileSets = new ReadOnlyDictionary<string, TileSet>(tileSets);
}
public IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
}
public class MapRuleset : ModRuleset
{
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 MapRuleset(
ModRuleset modRuleset,
IDictionary<string, ActorInfo> actors,
IDictionary<string, WeaponInfo> weapons,
IDictionary<string, SoundInfo> voices,
IDictionary<string, SoundInfo> notifications)
: base(modRuleset)
{
this.Actors = new ReadOnlyDictionary<string, ActorInfo>(actors);
this.Weapons = new ReadOnlyDictionary<string, WeaponInfo>(weapons);
this.Voices = new ReadOnlyDictionary<string, SoundInfo>(voices);
this.Notifications = new ReadOnlyDictionary<string, SoundInfo>(notifications);
}
}
}

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(
@@ -73,24 +82,39 @@ namespace OpenRA
}
}
public class TileSetData
{
Lazy<SpriteLoader> spriteLoader;
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
public readonly SequenceCache SequenceCache;
public TileSetData(ModData modData, TileSet tileSet)
{
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
SequenceCache = new SequenceCache(modData, tileSet);
}
}
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() { }
[FieldLoader.IgnoreAttribute]
public readonly TileSetData Data;
public TileSet(string filepath)
public TileSet(ModData modData, string filepath)
{
var yaml = MiniYaml.DictFromFile(filepath);
@@ -104,6 +128,16 @@ namespace OpenRA
// Templates
Templates = yaml["Templates"].NodesDict.Values
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
Data = new TileSetData(modData, this);
}
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)
@@ -139,5 +173,7 @@ namespace OpenRA
return ret;
}
}
}

37
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,11 +25,14 @@ namespace OpenRA
public readonly WidgetLoader WidgetLoader;
public readonly MapCache MapCache;
public ILoadScreen LoadScreen = null;
public SheetBuilder SheetBuilder;
public SpriteLoader SpriteLoader;
public VoxelLoader VoxelLoader;
public ModSequenceProvider SequenceProvider;
public ModRules Rules;
public readonly RulesetCache RulesetCache;
public CursorProvider CursorProvider { get; private set; }
Lazy<ModRuleset> modRules;
public ModRuleset ModRules { get { return modRules.Value; } }
Lazy<MapRuleset> defaultRules;
public MapRuleset DefaultRules { get { return defaultRules.Value; } }
public ModData(string mod)
{
@@ -40,14 +43,16 @@ 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);
SequenceProvider = new ModSequenceProvider(this);
Rules = new ModRules(this);
RulesetCache = new RulesetCache(this);
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);
modRules = Exts.Lazy(() => RulesetCache.LoadModRules());
defaultRules = Exts.Lazy(() => RulesetCache.LoadDefaultRules());
}
public void InitializeLoaders()
@@ -56,10 +61,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; }
@@ -79,7 +83,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)
{
@@ -122,14 +126,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("Rules.ActivateMap"))
Rules.ActivateMap(map);
SpriteLoader = new SpriteLoader(Rules.TileSets[map.Tileset].Extensions, SheetBuilder);
using (new Support.PerfTimer("Map.LoadRules"))
map.PreloadRules();
using (new Support.PerfTimer("SequenceProvider.ActivateMap"))
SequenceProvider.ActivateMap(map);
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequenceDefinitions);
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 ModInformation
{
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
public static readonly Dictionary<string, ModInformation> 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, ModInformation> ValidateMods(string[] mods)
{
var ret = new Dictionary<string, Mod>();
var ret = new Dictionary<string, ModInformation>();
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<ModInformation>(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="ModInformation.cs" />
<Compile Include="Map\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(MapRuleset 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(MapRuleset 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

@@ -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); }
}
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, ActorInitializer init)
{
this.Info = info;
Variants = new Dictionary<string, Sprite[]>();
foreach (var v in info.Variants)
{
var seq = SequenceProvider.GetSequence("resources", v);
var seq = init.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,
@@ -11,6 +11,8 @@
using System;
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Widgets
{
@@ -53,8 +55,13 @@ namespace OpenRA.Widgets
public Action OnDoubleClick = () => {};
public Action<KeyInput> OnKeyPress = _ => {};
public ButtonWidget()
readonly MapRuleset rules;
[ObjectCreator.UseCtor]
public ButtonWidget(MapRuleset rules)
{
this.rules = rules;
GetText = () => { return Text; };
GetColor = () => TextColor;
GetColorDisabled = () => TextColorDisabled;
@@ -70,6 +77,8 @@ namespace OpenRA.Widgets
protected ButtonWidget(ButtonWidget other)
: base(other)
{
this.rules = other.rules;
Text = other.Text;
Font = other.Font;
TextColor = other.TextColor;
@@ -113,10 +122,10 @@ namespace OpenRA.Widgets
if (!IsDisabled())
{
OnKeyPress(e);
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
Sound.PlayNotification(rules, null, "Sounds", "ClickSound", null);
}
else
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
Sound.PlayNotification(rules, null, "Sounds", "ClickDisabledSound", null);
return true;
}
@@ -153,12 +162,12 @@ namespace OpenRA.Widgets
{
OnMouseDown(mi);
Depressed = true;
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
Sound.PlayNotification(rules, null, "Sounds", "ClickSound", null);
}
else
{
YieldMouseFocus(mi);
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
Sound.PlayNotification(rules, 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(MapRuleset rules)
: base(rules)
{
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(MapRuleset rules)
: base(rules) { }
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(MapRuleset rules)
: base(rules)
{
IsVisible = () => false;
VisualHeight = 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,
@@ -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("rules"))
args = new WidgetArgs(args) { { "rules", 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,
@@ -125,7 +125,7 @@ namespace OpenRA
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

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

@@ -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,
@@ -12,6 +12,7 @@ using System;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Widgets.Logic;
using OpenRA.Traits;
using OpenRA.Widgets;
@@ -39,7 +40,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, () =>
@@ -64,10 +65,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
menu.Get<ButtonWidget>("MUSIC_BUTTON").OnClick = () =>
{
hideButtons = true;
Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs()
{
{ "onExit", () => hideButtons = false },
});
MusicPlayerLogic.OpenWindow(world, () => hideButtons = false);
};
menu.Get<ButtonWidget>("SETTINGS_BUTTON").OnClick = () =>

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, MapRuleset rules, 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());
rules.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 = () => rules.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

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
public class ProductionTooltipLogic
{
[ObjectCreator.UseCtor]
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette)
public ProductionTooltipLogic(Widget widget, MapRuleset rules, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette)
{
var pm = palette.World.LocalPlayer.PlayerActor.Trait<PowerManager>();
var pr = palette.World.LocalPlayer.PlayerActor.Trait<PlayerResources>();
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
if (actor == null || actor == lastActor)
return;
var info = Rules.Info[actor];
var info = rules.Actors[actor];
var tooltip = info.Traits.Get<TooltipInfo>();
var buildable = info.Traits.Get<BuildableInfo>();
var cost = info.Traits.Get<ValuedInfo>().Cost;
@@ -53,7 +53,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(rules, a));
var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : "";
requiresLabel.GetText = () => requiresString;
@@ -92,11 +92,10 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
};
}
static string ActorName(string a)
static string ActorName(MapRuleset 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,
@@ -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));
}
}

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,
@@ -9,6 +9,8 @@
#endregion
using OpenRA.Widgets;
using OpenRA.Graphics;
using OpenRA.Network;
namespace OpenRA.Mods.Cnc.Widgets
{
@@ -16,7 +18,10 @@ namespace OpenRA.Mods.Cnc.Widgets
{
public readonly string ProductionGroup;
public ProductionTypeButtonWidget() { }
[ObjectCreator.UseCtor]
public ProductionTypeButtonWidget(MapRuleset rules)
: base(rules) { }
protected ProductionTypeButtonWidget(ProductionTypeButtonWidget other)
: base(other)
{

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

@@ -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,18 @@ 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 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 +154,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 +188,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 +218,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 +233,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 +317,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 +337,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 +351,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 +380,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 +853,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

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

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(MapRuleset 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

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

@@ -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,
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA.Effects
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

@@ -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,
@@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA
dudesValue /= 100;
var eligibleLocations = FootprintUtils.Tiles(self).ToList();
var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = Rules.Info[a].Traits.Get<ValuedInfo>().Cost }).ToArray();
var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = self.World.Map.Rules.Actors[a].Traits.Get<ValuedInfo>().Cost }).ToArray();
while (eligibleLocations.Count > 0 && actorTypes.Any(a => a.Cost <= dudesValue))
{

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.RA
{
Level++;
Sound.PlayNotification(self.Owner, "Sounds", "LevelUp", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "LevelUp", self.Owner.Country.Race);
self.World.AddFrameEndTask(w => w.Add(new CrateEffect(self, "levelup", info.ChevronPalette)));
if (Level == 1)
self.World.AddFrameEndTask(w =>

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.Collections.Generic;
using System.Reflection;
using OpenRA;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
@@ -23,22 +24,22 @@ namespace OpenRA.Mods.RA
{
EmitError = emitError;
foreach (var actorInfo in Rules.Info)
foreach (var actorInfo in map.Rules.Actors)
foreach (var traitInfo in actorInfo.Value.Traits.WithInterface<ITraitInfo>())
CheckTrait(actorInfo.Value, traitInfo);
CheckTrait(actorInfo.Value, traitInfo, map);
}
void CheckTrait(ActorInfo actorInfo, ITraitInfo traitInfo)
void CheckTrait(ActorInfo actorInfo, ITraitInfo traitInfo, Map map)
{
var actualType = traitInfo.GetType();
foreach (var field in actualType.GetFields())
{
if (field.HasAttribute<ActorReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, Rules.Info, "actor");
CheckReference(actorInfo, traitInfo, field, map.Rules.Actors, "actor");
if (field.HasAttribute<WeaponReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, Rules.Weapons, "weapon");
CheckReference(actorInfo, traitInfo, field, map.Rules.Weapons, "weapon");
if (field.HasAttribute<VoiceReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, Rules.Voices, "voice");
CheckReference(actorInfo, traitInfo, field, map.Rules.Voices, "voice");
}
}
@@ -57,7 +58,7 @@ namespace OpenRA.Mods.RA
}
void CheckReference<T>(ActorInfo actorInfo, ITraitInfo traitInfo, FieldInfo fieldInfo,
Dictionary<string, T> dict, string type)
IReadOnlyDictionary<string, T> dict, string type)
{
var values = GetFieldValues(traitInfo, fieldInfo);
foreach (var v in values)

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,
@@ -19,11 +19,11 @@ namespace OpenRA.Mods.RA
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
var sequences = MiniYaml.MergeLiberal(map.Sequences,
var sequences = MiniYaml.MergeLiberal(map.SequenceDefinitions,
Game.modData.Manifest.Sequences.Select(s => MiniYaml.FromFile(s))
.Aggregate(MiniYaml.MergeLiberal));
foreach (var actorInfo in Rules.Info)
foreach (var actorInfo in map.Rules.Actors)
foreach (var renderInfo in actorInfo.Value.Traits.WithInterface<RenderSimpleInfo>())
{
var image = renderInfo.Image ?? actorInfo.Value.Name;

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.Mods.RA
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
foreach (var actorInfo in Rules.Info.Where(a => !a.Key.StartsWith("^")))
foreach (var actorInfo in map.Rules.Actors.Where(a => !a.Key.StartsWith("^")))
try
{
var traits = actorInfo.Value.TraitsInConstructOrder().ToArray();

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,13 +18,13 @@ namespace OpenRA.Mods.RA
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
var providedPrereqs = Rules.Info.Keys.Concat(
Rules.Info.SelectMany(a => a.Value.Traits
var providedPrereqs = map.Rules.Actors.Keys.Concat(
map.Rules.Actors.SelectMany(a => a.Value.Traits
.WithInterface<ProvidesCustomPrerequisiteInfo>()
.Select(p => p.Prerequisite))).ToArray();
// TODO: this check is case insensitive while the real check in-game is not
foreach (var i in Rules.Info)
foreach (var i in map.Rules.Actors)
{
var bi = i.Value.Traits.GetOrDefault<BuildableInfo>();
if (bi != 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,
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA
this.self = self;
var tileset = self.World.TileSet.Id.ToLower();
tile = SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
tile = self.World.Map.SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
}
public IEnumerable<IOrderTargeter> Orders
@@ -120,8 +120,8 @@ namespace OpenRA.Mods.RA
minefieldStart = xy;
var tileset = self.World.TileSet.Id.ToLower();
tileOk = SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
tileBlocked = SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0);
tileOk = self.World.Map.SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
tileBlocked = self.World.Map.SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0);
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)

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,
@@ -31,10 +31,10 @@ namespace OpenRA.Mods.RA.Orders
Producer = producer;
Building = name;
var tileset = producer.World.TileSet.Id.ToLower();
BuildingInfo = Rules.Info[Building].Traits.Get<BuildingInfo>();
BuildingInfo = producer.World.Map.Rules.Actors[Building].Traits.Get<BuildingInfo>();
buildOk = SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
buildBlocked = SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0);
buildOk = producer.World.Map.SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
buildBlocked = producer.World.Map.SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0);
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
@@ -57,11 +57,11 @@ namespace OpenRA.Mods.RA.Orders
if (!world.CanPlaceBuilding(Building, BuildingInfo, topLeft, null)
|| !BuildingInfo.IsCloseEnoughToBase(world, Producer.Owner, Building, topLeft))
{
Sound.PlayNotification(Producer.Owner, "Speech", "BuildingCannotPlaceAudio", Producer.Owner.Country.Race);
Sound.PlayNotification(world.Map.Rules, Producer.Owner, "Speech", "BuildingCannotPlaceAudio", Producer.Owner.Country.Race);
yield break;
}
var isLineBuild = Rules.Info[Building].Traits.Contains<LineBuildInfo>();
var isLineBuild = world.Map.Rules.Actors[Building].Traits.Contains<LineBuildInfo>();
yield return new Order(isLineBuild ? "LineBuild" : "PlaceBuilding",
Producer.Owner.PlayerActor, false) { TargetLocation = topLeft, TargetString = Building };
}
@@ -74,14 +74,16 @@ namespace OpenRA.Mods.RA.Orders
var position = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos();
var topLeft = position - FootprintUtils.AdjustForBuildingSize(BuildingInfo);
var actorInfo = Rules.Info[Building];
var rules = world.Map.Rules;
var actorInfo = rules.Actors[Building];
foreach (var dec in actorInfo.Traits.WithInterface<IPlaceBuildingDecoration>())
dec.Render(wr, world, actorInfo, position.CenterPosition); /* hack hack */
var cells = new Dictionary<CPos, bool>();
// Linebuild for walls.
// Assumes a 1x1 footprint; weird things will happen for other footprints
if (Rules.Info[Building].Traits.Contains<LineBuildInfo>())
if (rules.Actors[Building].Traits.Contains<LineBuildInfo>())
{
foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, Building, BuildingInfo))
cells.Add(t, BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, t));
@@ -90,7 +92,7 @@ namespace OpenRA.Mods.RA.Orders
{
if (!initialized)
{
var rbi = Rules.Info[Building].Traits.GetOrDefault<RenderBuildingInfo>();
var rbi = rules.Actors[Building].Traits.GetOrDefault<RenderBuildingInfo>();
if (rbi == null)
preview = new IRenderable[0];
else
@@ -98,7 +100,7 @@ namespace OpenRA.Mods.RA.Orders
var palette = rbi.Palette ?? (Producer.Owner != null ?
rbi.PlayerPalette + Producer.Owner.InternalName : null);
preview = rbi.RenderPreview(Rules.Info[Building], wr.Palette(palette));
preview = rbi.RenderPreview(rules.Actors[Building], wr.Palette(palette));
}
initialized = true;
@@ -110,7 +112,7 @@ namespace OpenRA.Mods.RA.Orders
var res = world.WorldActor.Trait<ResourceLayer>();
var isCloseEnough = BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, topLeft);
foreach (var t in FootprintUtils.Tiles(Building, BuildingInfo, topLeft))
foreach (var t in FootprintUtils.Tiles(rules, Building, BuildingInfo, topLeft))
cells.Add(t, isCloseEnough && world.IsCellBuildable(t, BuildingInfo) && res.GetResource(t) == null);
}

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,
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.RA
if (self.World.WorldTick - lastAttackTime > info.NotifyInterval * 25)
{
Sound.PlayNotification(self.Owner, "Speech", "BaseAttack", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "BaseAttack", self.Owner.Country.Race);
if (radarPings != null)
radarPings.Add(() => self.Owner == self.World.LocalPlayer, self.CenterPosition, info.RadarPingColor, info.RadarPingDuration);

6
OpenRA.Mods.RA/Player/ClassicProductionQueue.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,
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA
foreach (var p in producers.Where(p => !p.Actor.IsDisabled()))
{
if (p.Trait.Produce(p.Actor, Rules.Info[name]))
if (p.Trait.Produce(p.Actor, self.World.Map.Rules.Actors[name]))
{
FinishProduction();
return true;
@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA
public override int GetBuildTime(String unitString)
{
var unit = Rules.Info[unitString];
var unit = self.World.Map.Rules.Actors[unitString];
if (unit == null || !unit.Traits.Contains<BuildableInfo>())
return 0;

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,
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA
if (self.World.WorldTick - lastAttackTime > info.NotifyInterval * 25)
{
Sound.PlayNotification(self.Owner, "Speech", "HarvesterAttack", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "HarvesterAttack", self.Owner.Country.Race);
if (radarPings != null)
radarPings.Add(() => self.Owner == self.World.LocalPlayer, self.CenterPosition, info.RadarPingColor, info.RadarPingDuration);

View File

@@ -53,7 +53,7 @@ namespace OpenRA.Mods.RA
self.World.Add(playerBeacon);
if (self.Owner.IsAlliedWith(self.World.RenderPlayer))
Sound.PlayNotification(null, info.NotificationType, info.Notification,
Sound.PlayNotification(self.World.Map.Rules, null, info.NotificationType, info.Notification,
self.World.RenderPlayer != null ? self.World.RenderPlayer.Country.Race : null);
if (radarPings != null)

6
OpenRA.Mods.RA/Player/PlaceBuilding.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,
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA
if (queue == null)
return;
var unit = Rules.Info[order.TargetString];
var unit = self.World.Map.Rules.Actors[order.TargetString];
var buildingInfo = unit.Traits.Get<BuildingInfo>();
if (order.OrderString == "LineBuild")
@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA
if (GetNumBuildables(self.Owner) > prevItems)
w.Add(new DelayedAction(10,
() => Sound.PlayNotification(order.Player, "Speech", "NewOptions", order.Player.Country.Race)));
() => Sound.PlayNotification(self.World.Map.Rules, order.Player, "Speech", "NewOptions", order.Player.Country.Race)));
});
}
}

20
OpenRA.Mods.RA/Player/ProductionQueue.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,
@@ -135,7 +135,7 @@ namespace OpenRA.Mods.RA
IEnumerable<ActorInfo> AllBuildables(string category)
{
return Rules.Info.Values
return self.World.Map.Rules.Actors.Values
.Where( x => x.Name[ 0 ] != '^' )
.Where( x => x.Traits.Contains<BuildableInfo>() )
.Where( x => x.Traits.Get<BuildableInfo>().Queue == category );
@@ -149,14 +149,14 @@ namespace OpenRA.Mods.RA
public void PrerequisitesAvailable(string key)
{
var ps = Produceable[ Rules.Info[key] ];
var ps = Produceable[ self.World.Map.Rules.Actors[key] ];
if (!ps.Sticky)
ps.Buildable = true;
}
public void PrerequisitesUnavailable(string key)
{
var ps = Produceable[ Rules.Info[key] ];
var ps = Produceable[ self.World.Map.Rules.Actors[key] ];
if (!ps.Sticky)
ps.Buildable = false;
}
@@ -209,7 +209,7 @@ namespace OpenRA.Mods.RA
{
case "StartProduction":
{
var unit = Rules.Info[order.TargetString];
var unit = self.World.Map.Rules.Actors[order.TargetString];
var bi = unit.Traits.Get<BuildableInfo>();
if (bi.Queue != Info.Type)
return; /* Not built by this queue */
@@ -243,15 +243,15 @@ namespace OpenRA.Mods.RA
var isBuilding = unit.Traits.Contains<BuildingInfo>();
if (isBuilding && !hasPlayedSound)
{
hasPlayedSound = Sound.PlayNotification(self.Owner, "Speech", Info.ReadyAudio, self.Owner.Country.Race);
hasPlayedSound = Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.ReadyAudio, self.Owner.Country.Race);
}
else if (!isBuilding)
{
if (BuildUnit(order.TargetString))
Sound.PlayNotification(self.Owner, "Speech", Info.ReadyAudio, self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.ReadyAudio, self.Owner.Country.Race);
else if (!hasPlayedSound && time > 0)
{
hasPlayedSound = Sound.PlayNotification(self.Owner, "Speech", Info.BlockedAudio, self.Owner.Country.Race);
hasPlayedSound = Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.BlockedAudio, self.Owner.Country.Race);
}
}
})));
@@ -274,7 +274,7 @@ namespace OpenRA.Mods.RA
virtual public int GetBuildTime(String unitString)
{
var unit = Rules.Info[unitString];
var unit = self.World.Map.Rules.Actors[unitString];
if (unit == null || ! unit.Traits.Contains<BuildableInfo>())
return 0;
@@ -329,7 +329,7 @@ namespace OpenRA.Mods.RA
}
var sp = self.TraitsImplementing<Production>().FirstOrDefault(p => p.Info.Produces.Contains(Info.Type));
if (sp != null && !self.IsDisabled() && sp.Produce(self, Rules.Info[name]))
if (sp != null && !self.IsDisabled() && sp.Produce(self, self.World.Map.Rules.Actors[name]))
{
FinishProduction();
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,
@@ -77,7 +77,7 @@ namespace OpenRA.Mods.RA
isPrimary = true;
Sound.PlayNotification(self.Owner, "Speech", "PrimaryBuildingSelected", self.Owner.Country.Race);
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "PrimaryBuildingSelected", 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,
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA
var range = FallbackRange;
if (armaments.Any())
range = armaments.Select(a => Rules.Weapons[a.Weapon.ToLowerInvariant()].Range).Max();
range = armaments.Select(a => w.Map.Rules.Weapons[a.Weapon.ToLowerInvariant()].Range).Max();
if (range == WRange.Zero)
return;

View File

@@ -67,7 +67,7 @@ namespace OpenRA.Scripting
public int BuildTime(string type)
{
ActorInfo ai;
if (!Rules.Info.TryGetValue(type, out ai))
if (!context.World.Map.Rules.Actors.TryGetValue(type, out ai))
throw new LuaException("Unknown actor type '{0}'".F(type));
return ai.GetBuildTime();
@@ -77,7 +77,7 @@ namespace OpenRA.Scripting
public int CruiseAltitude(string type)
{
ActorInfo ai;
if (!Rules.Info.TryGetValue(type, out ai))
if (!context.World.Map.Rules.Actors.TryGetValue(type, out ai))
throw new LuaException("Unknown actor type '{0}'".F(type));
var pi = ai.Traits.GetOrDefault<PlaneInfo>();

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,
@@ -171,10 +171,10 @@ namespace OpenRA.Mods.RA.Scripting
public object TraitInfoOrDefault(string actorType, string className)
{
var type = Game.modData.ObjectCreator.FindType(className);
if (type == null || !Rules.Info.ContainsKey(actorType))
if (type == null || !world.Map.Rules.Actors.ContainsKey(actorType))
return null;
return Rules.Info[actorType].Traits.GetOrDefault(type);
return world.Map.Rules.Actors[actorType].Traits.GetOrDefault(type);
}
[LuaGlobal]
@@ -202,13 +202,13 @@ namespace OpenRA.Mods.RA.Scripting
[LuaGlobal]
public void PlaySpeechNotification(Player player, string notification)
{
Sound.PlayNotification(player, "Speech", notification, player != null ? player.Country.Race : null);
Sound.PlayNotification(world.Map.Rules, player, "Speech", notification, player != null ? player.Country.Race : null);
}
[LuaGlobal]
public void PlaySoundNotification(Player player, string notification)
{
Sound.PlayNotification(player, "Sounds", notification, player != null ? player.Country.Race : null);
Sound.PlayNotification(world.Map.Rules, player, "Sounds", notification, player != null ? player.Country.Race : null);
}
[LuaGlobal]
@@ -248,7 +248,7 @@ namespace OpenRA.Mods.RA.Scripting
[LuaGlobal]
public void PlayRandomMusic()
{
if (!Rules.InstalledMusic.Any() || !Game.Settings.Sound.MapMusic)
if (!Game.Settings.Sound.MapMusic || !world.Map.Rules.InstalledMusic.Any())
return;
Game.ConnectionStateChanged += StopMusic;
PlayMusic();
@@ -256,7 +256,7 @@ namespace OpenRA.Mods.RA.Scripting
void PlayMusic()
{
var track = Rules.InstalledMusic.Random(Game.CosmeticRandom);
var track = world.Map.Rules.InstalledMusic.Random(Game.CosmeticRandom);
Sound.PlayMusicThen(track.Value, PlayMusic);
}
@@ -385,7 +385,7 @@ namespace OpenRA.Mods.RA.Scripting
ClassicProductionQueue GetSharedQueueForUnit(Player player, string unit)
{
var ri = Rules.Info[unit];
var ri = world.Map.Rules.Actors[unit];
var bi = ri.Traits.GetOrDefault<BuildableInfo>();
if (bi == null)
@@ -406,7 +406,7 @@ namespace OpenRA.Mods.RA.Scripting
[LuaGlobal]
public void BuildWithPerFactoryQueue(Actor factory, string unit, double amount)
{
var ri = Rules.Info[unit];
var ri = world.Map.Rules.Actors[unit];
var bi = ri.Traits.GetOrDefault<BuildableInfo>();
if (bi == null)

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Scripting
public void Produce(string actorType)
{
ActorInfo actorInfo;
if (!Rules.Info.TryGetValue(actorType, out actorInfo))
if (!self.World.Map.Rules.Actors.TryGetValue(actorType, out actorInfo))
throw new LuaException("Unknown actor type '{0}'".F(actorType));
self.QueueActivity(new WaitFor(() => p.Produce(self, actorInfo)));

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,
@@ -76,7 +76,7 @@ namespace OpenRA.Mods.RA
variantStride = info.Index.Length;
for (var j = 0; j < info.Variants.Length; j++)
{
var seq = SequenceProvider.GetSequence(info.Sequence, info.Variants[j]);
var seq = map.SequenceProvider.GetSequence(info.Sequence, info.Variants[j]);
for (var i = 0; i < info.Index.Length; i++)
sprites[j * variantStride + i] = seq.GetSprite(i);
}
@@ -95,7 +95,7 @@ namespace OpenRA.Mods.RA
{
var ts = Game.modData.Manifest.TileSize;
var data = Exts.MakeArray<byte>(ts.Width * ts.Height, _ => (byte)info.ShroudColor);
var s = Game.modData.SheetBuilder.Add(data, ts);
var s = map.Rules.TileSets[map.Tileset].Data.SpriteLoader.SheetBuilder.Add(data, ts);
unexploredTile = new Sprite(s.sheet, s.bounds, s.offset, s.channel, info.ShroudBlend);
}
else

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,
@@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA
void SpawnUnitsForPlayer(World w, Player p, CPos sp)
{
var spawnClass = p.PlayerReference.StartingUnitsClass ?? w.LobbyInfo.GlobalSettings.StartingUnitsClass;
var unitGroup = Rules.Info["world"].Traits.WithInterface<MPStartUnitsInfo>()
var unitGroup = w.Map.Rules.Actors["world"].Traits.WithInterface<MPStartUnitsInfo>()
.Where(g => g.Class == spawnClass && g.Races != null && g.Races.Contains(p.Country.Race))
.RandomOrDefault(w.SharedRandom);
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.RA
foreach (var s in unitGroup.SupportActors)
{
var mi = Rules.Info[s.ToLowerInvariant()].Traits.Get<MobileInfo>();
var mi = w.Map.Rules.Actors[s.ToLowerInvariant()].Traits.Get<MobileInfo>();
var validCells = supportSpawnCells.Where(c => mi.CanEnterCell(w, c));
if (!validCells.Any())
throw new InvalidOperationException("No cells available to spawn starting unit {0}".F(s));

View File

@@ -28,9 +28,9 @@ namespace OpenRA.Mods.RA
this.info = info;
}
public void WorldLoaded(World w, WorldRenderer wr)
public void WorldLoaded(World world, WorldRenderer wr)
{
Sound.PlayNotification(null, "Speech", info.Notification, null);
Sound.PlayNotification(world.Map.Rules, null, "Speech", info.Notification, null);
}
}
}

2
OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs Executable file → Normal file
View File

@@ -59,7 +59,7 @@ namespace OpenRA.Mods.RA
var attackRotation = WRot.FromFacing(attackFacing);
var delta = new WVec(0, -1024, 0).Rotate(attackRotation);
var altitude = Rules.Info[info.UnitType].Traits.Get<PlaneInfo>().CruiseAltitude.Range;
var altitude = self.World.Map.Rules.Actors[info.UnitType].Traits.Get<PlaneInfo>().CruiseAltitude.Range;
var target = order.TargetLocation.CenterPosition + new WVec(0, 0, altitude);
var startEdge = target - (self.World.DistanceToMapEdge(target, -delta) + info.Cordon).Range * delta / 1024;
var finishEdge = target + (self.World.DistanceToMapEdge(target, delta) + info.Cordon).Range * delta / 1024;

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA
public override IOrderGenerator OrderGenerator(string order, SupportPowerManager manager)
{
Sound.PlayToPlayer(manager.self.Owner, Info.SelectTargetSound);
return new SelectTarget(order, manager, this);
return new SelectTarget(self.World, order, manager, this);
}
public override void Activate(Actor self, Order order, SupportPowerManager manager)
@@ -115,20 +115,20 @@ namespace OpenRA.Mods.RA
readonly SupportPowerManager manager;
readonly string order;
public SelectTarget(string order, SupportPowerManager manager, ChronoshiftPower power)
public SelectTarget(World world, string order, SupportPowerManager manager, ChronoshiftPower power)
{
this.manager = manager;
this.order = order;
this.power = power;
this.range = (power.Info as ChronoshiftPowerInfo).Range;
tile = SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
tile = world.Map.SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
world.CancelInputMode();
if (mi.Button == MouseButton.Left)
world.OrderGenerator = new SelectDestination(order, manager, power, xy);
world.OrderGenerator = new SelectDestination(world, order, manager, power, xy);
yield break;
}
@@ -173,7 +173,7 @@ namespace OpenRA.Mods.RA
readonly SupportPowerManager manager;
readonly string order;
public SelectDestination(string order, SupportPowerManager manager, ChronoshiftPower power, CPos sourceLocation)
public SelectDestination(World world, string order, SupportPowerManager manager, ChronoshiftPower power, CPos sourceLocation)
{
this.manager = manager;
this.order = order;
@@ -182,9 +182,9 @@ namespace OpenRA.Mods.RA
this.range = (power.Info as ChronoshiftPowerInfo).Range;
var tileset = manager.self.World.TileSet.Id.ToLower();
validTile = SequenceProvider.GetSequence("overlay", "target-valid-{0}".F(tileset)).GetSprite(0);
invalidTile = SequenceProvider.GetSequence("overlay", "target-invalid").GetSprite(0);
sourceTile = SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
validTile = world.Map.SequenceProvider.GetSequence("overlay", "target-valid-{0}".F(tileset)).GetSprite(0);
invalidTile = world.Map.SequenceProvider.GetSequence("overlay", "target-invalid").GetSprite(0);
sourceTile = world.Map.SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA
public override IOrderGenerator OrderGenerator(string order, SupportPowerManager manager)
{
Sound.PlayToPlayer(manager.self.Owner, Info.SelectTargetSound);
return new SelectTarget(order, manager, this);
return new SelectTarget(self.World, order, manager, this);
}
public override void Activate(Actor self, Order order, SupportPowerManager manager)
@@ -76,13 +76,13 @@ namespace OpenRA.Mods.RA
readonly SupportPowerManager manager;
readonly string order;
public SelectTarget(string order, SupportPowerManager manager, IronCurtainPower power)
public SelectTarget(World world, string order, SupportPowerManager manager, IronCurtainPower power)
{
this.manager = manager;
this.order = order;
this.power = power;
this.range = (power.Info as IronCurtainPowerInfo).Range;
tile = SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
tile = world.Map.SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)

4
OpenRA.Mods.RA/SupportPowers/ParatroopersPower.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,
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA
flare.QueueActivity(new RemoveSelf());
}
var altitude = Rules.Info[info.UnitType].Traits.Get<PlaneInfo>().CruiseAltitude;
var altitude = self.World.Map.Rules.Actors[info.UnitType].Traits.Get<PlaneInfo>().CruiseAltitude;
var a = w.CreateActor(info.UnitType, new TypeDictionary
{
new CenterPositionInit(startPos.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),

4
OpenRA.Mods.RA/SupportPowers/SpyPlanePower.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,
@@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA
base.Activate(self, order, manager);
var enterCell = self.World.ChooseRandomEdgeCell();
var altitude = Rules.Info["u2"].Traits.Get<PlaneInfo>().CruiseAltitude;
var altitude = self.World.Map.Rules.Actors["u2"].Traits.Get<PlaneInfo>().CruiseAltitude;
var plane = self.World.CreateActor("u2", new TypeDictionary
{

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,
@@ -79,8 +79,8 @@ namespace OpenRA.Mods.RA
public IEnumerable<IRenderable> GenerateRenderables(WorldRenderer wr)
{
var bright = SequenceProvider.GetSequence(image, "bright");
var dim = SequenceProvider.GetSequence(image, "dim");
var bright = wr.world.Map.SequenceProvider.GetSequence(image, "bright");
var dim = wr.world.Map.SequenceProvider.GetSequence(image, "dim");
var source = wr.ScreenPosition(pos);
var target = wr.ScreenPosition(pos + 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,
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA
{
this.self = self;
Info = info;
bi = Rules.Info[info.IntoActor].Traits.GetOrDefault<BuildingInfo>();
bi = self.World.Map.Rules.Actors[info.IntoActor].Traits.GetOrDefault<BuildingInfo>();
}
public string VoicePhraseForOrder(Actor self, Order order)

32
OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs Executable file → Normal file
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,
@@ -124,11 +124,11 @@ namespace OpenRA.Mods.RA.Widgets
// Play palette-open sound at the start of the activate anim (open)
if (paletteAnimationFrame == 1 && paletteOpen)
Sound.PlayNotification(null, "Sounds", "BuildPaletteOpen", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "BuildPaletteOpen", null);
// Play palette-close sound at the start of the activate anim (close)
if (paletteAnimationFrame == paletteAnimationLength + -1 && !paletteOpen)
Sound.PlayNotification(null, "Sounds", "BuildPaletteClose", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "BuildPaletteClose", null);
// Animation is complete
if ((paletteAnimationFrame == 0 && !paletteOpen)
@@ -314,7 +314,7 @@ namespace OpenRA.Mods.RA.Widgets
{
return mi =>
{
Sound.PlayNotification(null, "Sounds", "TabClick", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
if (name != null)
HandleBuildPalette(world, name, (mi.Button == MouseButton.Left));
@@ -328,7 +328,7 @@ namespace OpenRA.Mods.RA.Widgets
if (mi.Button != MouseButton.Left)
return;
Sound.PlayNotification(null, "Sounds", "TabClick", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
var wasOpen = paletteOpen;
paletteOpen = CurrentQueue != queue || !wasOpen;
CurrentQueue = queue;
@@ -337,10 +337,10 @@ namespace OpenRA.Mods.RA.Widgets
};
}
static string Description(string a)
static string Description(MapRuleset rules, string a)
{
ActorInfo ai;
Rules.Info.TryGetValue(a.ToLowerInvariant(), out ai);
rules.Actors.TryGetValue(a.ToLowerInvariant(), out ai);
if (ai != null && ai.Traits.Contains<TooltipInfo>())
return ai.Traits.Get<TooltipInfo>().Name;
@@ -349,7 +349,7 @@ namespace OpenRA.Mods.RA.Widgets
void HandleBuildPalette(World world, string item, bool isLmb)
{
var unit = Rules.Info[item];
var unit = world.Map.Rules.Actors[item];
var producing = CurrentQueue.AllQueued().FirstOrDefault(a => a.Item == item);
if (isLmb)
@@ -379,9 +379,9 @@ namespace OpenRA.Mods.RA.Widgets
var buildLimit = unit.Traits.Get<BuildableInfo>().BuildLimit;
if (!((buildLimit != 0) && (inWorld + queued >= buildLimit)))
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);
else
Sound.PlayNotification(world.LocalPlayer, "Speech", CurrentQueue.Info.BlockedAudio, world.LocalPlayer.Country.Race);
Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.BlockedAudio, world.LocalPlayer.Country.Race);
}
StartProduction(world, item);
@@ -393,14 +393,14 @@ namespace OpenRA.Mods.RA.Widgets
// instant cancel of things we havent really started yet, and things that are finished
if (producing.Paused || producing.Done || producing.TotalCost == producing.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);
int numberToCancel = Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1;
world.IssueOrder(Order.CancelProduction(CurrentQueue.self, item, numberToCancel));
}
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, item, true));
}
}
@@ -463,7 +463,7 @@ namespace OpenRA.Mods.RA.Widgets
var pl = world.LocalPlayer;
var p = pos.ToFloat2() - new float2(297, -3);
var info = Rules.Info[unit];
var info = world.Map.Rules.Actors[unit];
var tooltip = info.Traits.Get<TooltipInfo>();
var buildable = info.Traits.Get<BuildableInfo>();
var cost = info.Traits.Get<ValuedInfo>().Cost;
@@ -497,7 +497,7 @@ namespace OpenRA.Mods.RA.Widgets
p += new int2(5, 35);
if (!canBuildThis)
{
var prereqs = buildable.Prerequisites.Select(Description);
var prereqs = buildable.Prerequisites.Select(s => Description(world.Map.Rules, s));
if (prereqs.Any())
{
Game.Renderer.Fonts["Regular"].DrawText(RequiresText.F(prereqs.JoinWith(", ")), p.ToInt2(), Color.White);
@@ -520,7 +520,7 @@ namespace OpenRA.Mods.RA.Widgets
if (toBuild != null)
{
Sound.PlayNotification(null, "Sounds", "TabClick", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
HandleBuildPalette(world, toBuild.Name, true);
return true;
}
@@ -531,7 +531,7 @@ namespace OpenRA.Mods.RA.Widgets
// NOTE: Always return true here to prevent mouse events from passing through the sidebar and interacting with the world behind it.
bool ChangeTab(bool reverse)
{
Sound.PlayNotification(null, "Sounds", "TabClick", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
var queues = VisibleQueues.Concat(VisibleQueues);
if (reverse)
queues = queues.Reverse();

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,
@@ -38,11 +38,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Sprite[] currentSprites;
int currentFrame;
readonly World world;
static readonly string[] AllowedExtensions = { ".shp", ".r8", "tmp", ".tem", ".des", ".sno", ".int" };
[ObjectCreator.UseCtor]
public AssetBrowserLogic(Widget widget, Action onExit, World world)
{
this.world = world;
panel = widget;
assetSource = GlobalFileSystem.MountedFolders.First();
@@ -192,7 +196,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
return false;
currentFilename = filename;
currentSprites = Game.modData.SpriteLoader.LoadAllSprites(filename);
currentSprites = world.Map.Rules.TileSets[world.Map.Tileset].Data.SpriteLoader.LoadAllSprites(filename);
currentFrame = 0;
frameSlider.MaximumValue = (float)currentSprites.Length - 1;
frameSlider.Ticks = currentSprites.Length;

View File

@@ -20,6 +20,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
public class IngameChatLogic
{
readonly World world;
readonly ContainerWidget chatOverlay;
readonly ChatDisplayWidget chatOverlayDisplay;
@@ -35,6 +37,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
[ObjectCreator.UseCtor]
public IngameChatLogic(Widget widget, OrderManager orderManager, World world)
{
this.world = world;
chatTraits = world.WorldActor.TraitsImplementing<INotifyChat>().ToList();
var players = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot);
@@ -161,7 +165,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (scrolledToBottom)
chatScrollPanel.ScrollToBottom();
Sound.PlayNotification(null, "Sounds", "ChatLine", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ChatLine", null);
}
}
}

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,
@@ -18,9 +18,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
public class IngameChromeLogic
{
Widget gameRoot;
Widget playerRoot;
World world;
readonly Widget gameRoot;
readonly Widget playerRoot;
readonly World world;
[ObjectCreator.UseCtor]
public IngameChromeLogic(World world)
@@ -149,7 +149,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
.Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive);
if (radarActive != cachedRadarActive)
Sound.PlayNotification(null, "Sounds", (radarActive ? "RadarUp" : "RadarDown"), null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", (radarActive ? "RadarUp" : "RadarDown"), null);
cachedRadarActive = radarActive;
// Switch to observer mode after win/loss

View File

@@ -63,7 +63,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
widget.Get<ButtonWidget>("MUSIC").OnClick = () =>
{
widget.Visible = false;
Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs { { "onExit", () => { widget.Visible = true; } } });
MusicPlayerLogic.OpenWindow(world, () => { widget.Visible = true; });
};
widget.Get<ButtonWidget>("RESUME").OnClick = () => onExit();
@@ -82,7 +82,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
void LeaveGame(World world)
{
Sound.PlayNotification(null, "Speech", "Leave", world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
Game.Disconnect();
Ui.CloseWindow();
Game.LoadShellMap();

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,
@@ -29,6 +29,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
readonly Action onExit;
readonly OrderManager orderManager;
readonly bool skirmishMode;
readonly World world;
enum PanelType { Players, Options, Kick, ForceStart }
PanelType panel = PanelType.Players;
@@ -98,6 +99,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
this.onStart = onStart;
this.onExit = onExit;
this.skirmishMode = skirmishMode;
this.world = world;
Game.LobbyInfoChanged += UpdateCurrentMap;
Game.LobbyInfoChanged += UpdatePlayerList;
@@ -132,7 +134,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
colorPreview = lobby.Get<ColorPreviewManagerWidget>("COLOR_MANAGER");
colorPreview.Color = Game.Settings.Player.Color;
countryNames = Rules.Info["world"].Traits.WithInterface<CountryInfo>()
countryNames = world.Map.Rules.Actors["world"].Traits.WithInterface<CountryInfo>()
.Where(c => c.Selectable)
.ToDictionary(a => a.Race, a => a.Name);
countryNames.Add("random", "Any");
@@ -170,7 +172,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players ||
!orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots || !s.LockTeam);
var botNames = Rules.Info["player"].Traits.WithInterface<IBotInfo>().Select(t => t.Name);
var botNames = world.Map.Rules.Actors["player"].Traits.WithInterface<IBotInfo>().Select(t => t.Name);
slotsButton.OnMouseDown = _ =>
{
var options = new Dictionary<string, IEnumerable<DropDownOption>>();
@@ -375,7 +377,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
};
Func<string, string> className = c => classNames.ContainsKey(c) ? classNames[c] : c;
var classes = Rules.Info["world"].Traits.WithInterface<MPStartUnitsInfo>()
var classes = world.Map.Rules.Actors["world"].Traits.WithInterface<MPStartUnitsInfo>()
.Select(a => a.Class).Distinct();
startingUnits.IsDisabled = () => Map.Status != MapStatus.Available || !Map.Map.Options.ConfigurableStartingUnits || configurationDisabled();
@@ -409,7 +411,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
startingCash.GetText = () => Map.Status != MapStatus.Available || Map.Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
startingCash.OnMouseDown = _ =>
{
var options = Rules.Info["player"].Traits.Get<PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption
var options = world.Map.Rules.Actors["player"].Traits.Get<PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption
{
Title = "${0}".F(c),
IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingCash == c,
@@ -481,7 +483,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var musicButton = lobby.GetOrNull<ButtonWidget>("MUSIC_BUTTON");
if (musicButton != null)
musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs { { "onExit", DoNothing } });
musicButton.OnClick = () => MusicPlayerLogic.OpenWindow(world);
var settingsButton = lobby.GetOrNull<ButtonWidget>("SETTINGS_BUTTON");
if (settingsButton != null)
@@ -499,7 +501,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Game.LobbyInfoChanged += WidgetUtils.Once(() =>
{
var slot = orderManager.LobbyInfo.FirstEmptyBotSlot();
var bot = Rules.Info["player"].Traits.WithInterface<IBotInfo>().Select(t => t.Name).FirstOrDefault();
var bot = world.Map.Rules.Actors["player"].Traits.WithInterface<IBotInfo>().Select(t => t.Name).FirstOrDefault();
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
if (slot != null && bot != null)
orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
@@ -542,7 +544,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (scrolledToBottom)
chatPanel.ScrollToBottom();
Sound.PlayNotification(null, "Sounds", "ChatLine", null);
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ChatLine", null);
}
void UpdateCurrentMap()
@@ -559,7 +561,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
// Restore default starting cash if the last map set it to something invalid
var pri = Rules.Info["player"].Traits.Get<PlayerResourcesInfo>();
var pri = world.Map.Rules.Actors["player"].Traits.Get<PlayerResourcesInfo>();
if (!Map.Map.Options.StartingCash.HasValue && !pri.SelectableCash.Contains(orderManager.LobbyInfo.GlobalSettings.StartingCash))
orderManager.IssueOrder(Order.Command("startingcash {0}".F(pri.DefaultCash)));
}
@@ -588,7 +590,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
template = emptySlotTemplate.Clone();
if (Game.IsHost)
LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager);
LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, world.Map.Rules);
else
LobbyUtils.SetupSlotWidget(template, slot, client);
@@ -607,7 +609,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
LobbyUtils.SetupClientWidget(template, slot, client, orderManager, client.Bot == null);
if (client.Bot != null)
LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager);
LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, world.Map.Rules);
else
LobbyUtils.SetupEditableNameWidget(template, slot, client, orderManager);

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