using System; using System.Collections.Generic; using System.Linq; using OpenRa.Effects; using OpenRa.Support; using OpenRa.FileFormats; using OpenRa.Graphics; using OpenRa.Traits; namespace OpenRa { public class World { List actors = new List(); List effects = new List(); List> frameEndActions = new List>(); public readonly Dictionary players = new Dictionary(); int localPlayerIndex; public Player LocalPlayer { get { return players[localPlayerIndex]; } } public void SetLocalPlayer(int index) { if (index != localPlayerIndex) { localPlayerIndex = index; Game.viewport.GoToStartLocation(LocalPlayer); Game.chat.AddLine(LocalPlayer, "is now YOU"); } } public readonly BuildingInfluenceMap BuildingInfluence; public readonly UnitInfluenceMap UnitInfluence; public readonly PathFinder PathFinder; public readonly Map Map; public readonly TileSet TileSet; // for tricky things like bridges. public readonly ICustomTerrain[,] customTerrain = new ICustomTerrain[128, 128]; public readonly WorldRenderer WorldRenderer; internal readonly Minimap Minimap; readonly int oreFrequency; int oreTicks; public World() { Timer.Time( "----World.ctor" ); Map = new Map( Rules.AllRules ); Timer.Time( "new Map: {0}" ); TileSet = new TileSet( Map.TileSuffix ); SpriteSheetBuilder.Initialize( Map ); Timer.Time( "Tileset: {0}" ); BuildingInfluence = new BuildingInfluenceMap( this ); UnitInfluence = new UnitInfluenceMap( this ); Timer.Time( "BIM/UIM: {0}" ); oreFrequency = (int)(Rules.General.GrowthRate * 60 * 25); oreTicks = oreFrequency; Map.InitOreDensity(); Timer.Time( "Ore: {0}" ); CreateActor("World", new int2(int.MaxValue, int.MaxValue), null); for (int i = 0; i < 8; i++) players[i] = new Player(this, i, Game.LobbyInfo.Clients.FirstOrDefault(a => a.Index == i)); Timer.Time( "worldActor, players: {0}" ); Bridges.MakeBridges(this); PathFinder = new PathFinder(this); Timer.Time( "bridge, pathing: {0}" ); WorldRenderer = new WorldRenderer(this, Game.renderer); Minimap = new Minimap(this, Game.renderer); Timer.Time( "renderer, minimap: {0}" ); Timer.Time( "----end World.ctor" ); } public Actor CreateActor( string name, int2 location, Player owner ) { var a = new Actor( this, name, location, owner ); Add( a ); return a; } public void Add(Actor a) { a.IsInWorld = true; actors.Add(a); ActorAdded(a); } public void Remove(Actor a) { a.IsInWorld = false; actors.Remove(a); ActorRemoved(a); } public void Add(IEffect b) { effects.Add(b); } public void Remove(IEffect b) { effects.Remove(b); } public void AddFrameEndTask( Action a ) { frameEndActions.Add( a ); } public event Action ActorAdded = _ => { }; public event Action ActorRemoved = _ => { }; public void Tick() { if (--oreTicks == 0) using( new PerfSample( "ore" ) ) { this.GrowOre( Game.SharedRandom ); Minimap.InvalidateOre(); oreTicks = oreFrequency; } foreach (var a in actors) a.Tick(); foreach (var e in effects) e.Tick( this ); Game.viewport.Tick(); var acts = frameEndActions; frameEndActions = new List>(); foreach (var a in acts) a(this); UnitInfluence.Tick(); Minimap.Update(); foreach (var player in players.Values) player.Tick(); } public IEnumerable Actors { get { return actors; } } public IEnumerable Effects { get { return effects; } } uint nextAID = 0; internal uint NextAID() { return nextAID++; } public int SyncHash() { using (new PerfSample("synchash")) { int ret = 0; foreach (var a in Actors) ret += (int)a.ActorID * Sync.CalculateSyncHash(a); return ret; } } } }