Write() public static method

public static Write ( string channel, string value ) : void
channel string
value string
return void
Example #1
0
        public Player(World world, Session.Client client, PlayerReference pr)
        {
            World           = world;
            InternalName    = pr.Name;
            PlayerReference = pr;

            inMissionMap = world.Map.Visibility.HasFlag(MapVisibility.MissionSelector);

            // Real player or host-created bot
            if (client != null)
            {
                ClientIndex = client.Index;
                Color       = client.Color;
                if (client.Bot != null)
                {
                    var botInfo        = world.Map.Rules.Actors["player"].TraitInfos <IBotInfo>().First(b => b.Type == client.Bot);
                    var botsOfSameType = world.LobbyInfo.Clients.Where(c => c.Bot == client.Bot).ToArray();
                    PlayerName = botsOfSameType.Length == 1 ? botInfo.Name : "{0} {1}".F(botInfo.Name, botsOfSameType.IndexOf(client) + 1);
                }
                else
                {
                    PlayerName = client.Name;
                }

                BotType        = client.Bot;
                Faction        = ChooseFaction(world, client.Faction, !pr.LockFaction);
                DisplayFaction = ChooseDisplayFaction(world, client.Faction);
            }
            else
            {
                // Map player
                ClientIndex    = 0;              // Owned by the host (TODO: fix this)
                Color          = pr.Color;
                PlayerName     = pr.Name;
                NonCombatant   = pr.NonCombatant;
                Playable       = pr.Playable;
                Spectating     = pr.Spectating;
                BotType        = pr.Bot;
                Faction        = ChooseFaction(world, pr.Faction, false);
                DisplayFaction = ChooseDisplayFaction(world, pr.Faction);
            }

            if (!Spectating)
            {
                PlayerMask = new LongBitSet <PlayerBitMask>(InternalName);
            }

            var playerActorType = world.Type == WorldType.Editor ? "EditorPlayer" : "Player";

            PlayerActor = world.CreateActor(playerActorType, new TypeDictionary {
                new OwnerInit(this)
            });
            Shroud           = PlayerActor.Trait <Shroud>();
            FrozenActorLayer = PlayerActor.TraitOrDefault <FrozenActorLayer>();

            // Enable the bot logic on the host
            IsBot = BotType != null;
            if (IsBot && Game.IsHost)
            {
                var logic = PlayerActor.TraitsImplementing <IBot>().FirstOrDefault(b => b.Info.Type == BotType);
                if (logic == null)
                {
                    Log.Write("debug", "Invalid bot type: {0}", BotType);
                }
                else
                {
                    logic.Activate(this);
                }
            }

            stanceColors.Self     = ChromeMetrics.Get <Color>("PlayerStanceColorSelf");
            stanceColors.Allies   = ChromeMetrics.Get <Color>("PlayerStanceColorAllies");
            stanceColors.Enemies  = ChromeMetrics.Get <Color>("PlayerStanceColorEnemies");
            stanceColors.Neutrals = ChromeMetrics.Get <Color>("PlayerStanceColorNeutrals");

            unlockRenderPlayer = PlayerActor.TraitsImplementing <IUnlocksRenderPlayer>().ToArray();
        }
Example #2
0
        internal static void Initialize(Arguments args)
        {
            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            InitializeSettings(args);

            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("sync", "syncreport.log");
            Log.AddChannel("server", "server.log");
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");
            Log.AddChannel("irc", "irc.log");

            if (Settings.Server.DiscoverNatDevices)
            {
                UPnP.TryNatDiscovery();
            }
            else
            {
                Settings.Server.NatDeviceAvailable = false;
                Settings.Server.AllowPortForward   = false;
            }

            GeoIP.Initialize();

            var renderers = new[] { Settings.Graphics.Renderer, "Default", null };

            foreach (var r in renderers)
            {
                if (r == null)
                {
                    throw new InvalidOperationException("No suitable renderers were found. Check graphics.log for details.");
                }

                Settings.Graphics.Renderer = r;
                try
                {
                    Renderer = new Renderer(Settings.Graphics, Settings.Server);
                    break;
                }
                catch (Exception e)
                {
                    Log.Write("graphics", "{0}", e);
                    Console.WriteLine("Renderer initialization failed. Fallback in place. Check graphics.log for details.");
                }
            }

            Sound = new Sound(Settings.Sound.Engine);

            GlobalChat = new GlobalChat();

            Console.WriteLine("Available mods:");
            foreach (var mod in ModMetadata.AllMods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
            }

            InitializeMod(Settings.Game.Mod, args);

            if (Settings.Server.DiscoverNatDevices)
            {
                RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.StoppingNatDiscovery);
            }
        }
Example #3
0
        static void Run(string[] args)
        {
            var engineDir = Environment.GetEnvironmentVariable("ENGINE_DIR");

            if (!string.IsNullOrEmpty(engineDir))
            {
                Platform.OverrideEngineDir(engineDir);
            }

            Log.AddChannel("perf", null);
            Log.AddChannel("debug", null);

            Game.InitializeSettings(Arguments.Empty);

            var envModSearchPaths = Environment.GetEnvironmentVariable("MOD_SEARCH_PATHS");
            var modSearchPaths    = !string.IsNullOrWhiteSpace(envModSearchPaths) ?
                                    FieldLoader.GetValue <string[]>("MOD_SEARCH_PATHS", envModSearchPaths) :
                                    new[] { Path.Combine(Platform.EngineDir, "mods") };

            if (args.Length == 0)
            {
                PrintUsage(new InstalledMods(modSearchPaths, new string[0]), null);
                return;
            }

            var modId            = args[0];
            var explicitModPaths = new string[0];

            if (File.Exists(modId) || Directory.Exists(modId))
            {
                explicitModPaths = new[] { modId };
                modId            = Path.GetFileNameWithoutExtension(modId);
            }

            var mods = new InstalledMods(modSearchPaths, explicitModPaths);

            if (!mods.Keys.Contains(modId))
            {
                PrintUsage(mods, null);
                return;
            }

            var modData = new ModData(mods[modId], mods);
            var utility = new Utility(modData, mods);

            args = args.Skip(1).ToArray();
            var actions = new UtilityActions();

            foreach (var commandType in modData.ObjectCreator.GetTypesImplementing <IUtilityCommand>())
            {
                var command = (IUtilityCommand)Activator.CreateInstance(commandType);
                var kvp     = new KeyValuePair <Action <Utility, string[]>, Func <string[], bool> >(command.Run, command.ValidateArguments);
                actions.Add(command.Name, kvp);
            }

            if (args.Length == 0)
            {
                PrintUsage(mods, actions);
                return;
            }

            try
            {
                var command = args[0];
                if (!actions.ContainsKey(command))
                {
                    throw new NoSuchCommandException(command);
                }

                var action             = actions[command].Key;
                var validateActionArgs = actions[command].Value;

                if (validateActionArgs.Invoke(args))
                {
                    action.Invoke(utility, args);
                }
                else
                {
                    Console.WriteLine("Invalid arguments for '{0}'", command);
                    GetActionUsage(command, action);
                }
            }
            catch (Exception e)
            {
                Log.AddChannel("utility", "utility.log");
                Log.Write("utility", "Received args: {0}", args.JoinWith(" "));
                Log.Write("utility", "{0}", e);

                if (e is NoSuchCommandException)
                {
                    Console.WriteLine(e.Message);
                }
                else
                {
                    Console.WriteLine("Error: Utility application crashed. See utility.log for details");
                    throw;
                }
            }
        }
Example #4
0
        /// <summary>
        /// Removes invalid mod registrations:
        /// * LaunchPath no longer exists
        /// * LaunchPath and mod id matches the active mod, but the version is different
        /// * Filename doesn't match internal key
        /// * Fails to parse as a mod registration
        /// </summary>
        internal void ClearInvalidRegistrations(ExternalMod activeMod, ModRegistration registration)
        {
            var sources = new List <string>();

            if (registration.HasFlag(ModRegistration.System))
            {
                sources.Add(Platform.SystemSupportDir);
            }

            if (registration.HasFlag(ModRegistration.User))
            {
                sources.Add(Platform.SupportDir);
            }

            var activeModKey = ExternalMod.MakeKey(activeMod);

            foreach (var source in sources.Distinct())
            {
                var metadataPath = Path.Combine(source, "ModMetadata");
                if (!Directory.Exists(metadataPath))
                {
                    continue;
                }

                foreach (var path in Directory.GetFiles(metadataPath, "*.yaml"))
                {
                    string modKey = null;
                    try
                    {
                        var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value;
                        var m    = FieldLoader.Load <ExternalMod>(yaml);
                        modKey = ExternalMod.MakeKey(m);

                        // Continue to the next entry if it is the active mod (even if the LaunchPath is bogus)
                        if (modKey == activeModKey)
                        {
                            continue;
                        }

                        // Continue to the next entry if this one is valid
                        if (File.Exists(m.LaunchPath) && Path.GetFileNameWithoutExtension(path) == modKey &&
                            !(activeMod != null && m.LaunchPath == activeMod.LaunchPath && m.Id == activeMod.Id && m.Version != activeMod.Version))
                        {
                            continue;
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed to parse mod metadata file '{0}'", path);
                        Log.Write("debug", e.ToString());
                    }

                    // Remove from the ingame mod switcher
                    if (Path.GetFileNameWithoutExtension(path) == modKey)
                    {
                        mods.Remove(modKey);
                    }

                    // Remove stale or corrupted metadata
                    try
                    {
                        File.Delete(path);
                        Log.Write("debug", "Removed invalid mod metadata file '{0}'", path);
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed to remove mod metadata file '{0}'", path);
                        Log.Write("debug", e.ToString());
                    }
                }
            }
        }
Example #5
0
        public void QueryRemoteMapDetails(string repositoryUrl, IEnumerable <string> uids, Action <MapPreview> mapDetailsReceived = null, Action queryFailed = null)
        {
            var maps = uids.Distinct()
                       .Select(uid => previews[uid])
                       .Where(p => p.Status == MapStatus.Unavailable)
                       .ToDictionary(p => p.Uid, p => p);

            if (!maps.Any())
            {
                return;
            }

            foreach (var p in maps.Values)
            {
                p.UpdateRemoteSearch(MapStatus.Searching, null);
            }

            var url = repositoryUrl + "hash/" + string.Join(",", maps.Keys) + "/yaml";

            Action <DownloadDataCompletedEventArgs> onInfoComplete = i =>
            {
                if (i.Error != null)
                {
                    Log.Write("debug", "Remote map query failed with error: {0}", Download.FormatErrorMessage(i.Error));
                    Log.Write("debug", "URL was: {0}", url);
                    foreach (var p in maps.Values)
                    {
                        p.UpdateRemoteSearch(MapStatus.Unavailable, null);
                    }

                    queryFailed?.Invoke();

                    return;
                }

                var data = Encoding.UTF8.GetString(i.Result);
                try
                {
                    var yaml = MiniYaml.FromString(data);
                    foreach (var kv in yaml)
                    {
                        maps[kv.Key].UpdateRemoteSearch(MapStatus.DownloadAvailable, kv.Value, mapDetailsReceived);
                    }

                    foreach (var map in maps)
                    {
                        if (map.Value.Status != MapStatus.DownloadAvailable)
                        {
                            map.Value.UpdateRemoteSearch(MapStatus.Unavailable, null);
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Can't parse remote map search data:\n{0}", data);
                    Log.Write("debug", "Exception: {0}", e);
                    queryFailed?.Invoke();
                }
            };

            new Download(url, _ => { }, onInfoComplete);
        }
Example #6
0
        public MPos Clamp(MPos uv)
        {
            if (MaximumTerrainHeight == 0)
            {
                return((MPos)Clamp((PPos)uv));
            }

            // Already in bounds, so don't need to do anything.
            if (ProjectedCellsCovering(uv).Any(containsTest))
            {
                return(uv);
            }

            // Clamping map coordinates is trickier than it might first look!
            // This needs to handle three nasty cases:
            //  * The requested cell is well outside the map region
            //  * The requested cell is near the top edge inside the map but outside the projected layer
            //  * The clamped projected cell lands on a cliff face with no associated map cell
            //
            // Handling these cases properly requires abuse of our knowledge of the projection transform.
            //
            // The U coordinate doesn't change significantly in the projection, so clamp this
            // straight away and ensure the point is somewhere inside the map
            uv = cellProjection.Clamp(new MPos(uv.U.Clamp(Bounds.Left, Bounds.Right), uv.V));

            // Project this guessed cell and take the first available cell
            // If it is projected outside the layer, then make another guess.
            var allProjected = ProjectedCellsCovering(uv);
            var projected    = allProjected.Any() ? allProjected.First()
                                : new PPos(uv.U, uv.V.Clamp(Bounds.Top, Bounds.Bottom));

            // Clamp the projected cell to the map area
            projected = Clamp(projected);

            // Project the cell back into map coordinates.
            // This may fail if the projected cell covered a cliff or another feature
            // where there is a large change in terrain height.
            var unProjected = Unproject(projected);

            if (!unProjected.Any())
            {
                // Adjust V until we find a cell that works
                for (var x = 2; x <= 2 * MaximumTerrainHeight; x++)
                {
                    var dv   = ((x & 1) == 1 ? 1 : -1) * x / 2;
                    var test = new PPos(projected.U, projected.V + dv);
                    if (!Contains(test))
                    {
                        continue;
                    }

                    unProjected = Unproject(test);
                    if (unProjected.Any())
                    {
                        break;
                    }
                }

                // This shouldn't happen.  But if it does, return the original value and hope the caller doesn't explode.
                if (!unProjected.Any())
                {
                    Log.Write("debug", "Failed to clamp map cell {0} to map bounds", uv);
                    return(uv);
                }
            }

            return(projected.V == Bounds.Bottom ? unProjected.MaxBy(x => x.V) : unProjected.MinBy(x => x.V));
        }
Example #7
0
        static void InnerLogicTick(OrderManager orderManager)
        {
            var tick = RunTime;

            var world = orderManager.World;

            var uiTickDelta = tick - Ui.LastTickTime;

            if (uiTickDelta >= Timestep)
            {
                // Explained below for the world tick calculation
                var integralTickTimestep = (uiTickDelta / Timestep) * Timestep;
                Ui.LastTickTime += integralTickTimestep >= TimestepJankThreshold ? integralTickTimestep : Timestep;

                Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, Ui.Tick);
                Cursor.Tick();
            }

            var worldTimestep  = world == null ? Timestep : world.IsLoadingGameSave ? 1 : world.Timestep;
            var worldTickDelta = tick - orderManager.LastTickTime;

            if (worldTimestep != 0 && worldTickDelta >= worldTimestep)
            {
                using (new PerfSample("tick_time"))
                {
                    // Tick the world to advance the world time to match real time:
                    //    If dt < TickJankThreshold then we should try and catch up by repeatedly ticking
                    //    If dt >= TickJankThreshold then we should accept the jank and progress at the normal rate
                    // dt is rounded down to an integer tick count in order to preserve fractional tick components.
                    var integralTickTimestep = (worldTickDelta / worldTimestep) * worldTimestep;
                    orderManager.LastTickTime += integralTickTimestep >= TimestepJankThreshold ? integralTickTimestep : worldTimestep;

                    Sound.Tick();
                    Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, orderManager.TickImmediate);

                    if (world == null)
                    {
                        return;
                    }

                    var isNetTick = LocalTick % NetTickScale == 0;

                    if (!isNetTick || orderManager.IsReadyForNextFrame)
                    {
                        ++orderManager.LocalFrameNumber;

                        Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");

                        if (isNetTick)
                        {
                            orderManager.Tick();
                        }

                        Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, () =>
                        {
                            world.OrderGenerator.Tick(world);
                        });

                        world.Tick();

                        PerfHistory.Tick();
                    }
                    else if (orderManager.NetFrameNumber == 0)
                    {
                        orderManager.LastTickTime = RunTime;
                    }

                    // Wait until we have done our first world Tick before TickRendering
                    if (orderManager.LocalFrameNumber > 0)
                    {
                        Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, () => world.TickRender(worldRenderer));
                    }
                }

                benchmark?.Tick(LocalTick);
            }
        }
Example #8
0
        public Player(World world, Session.Client client, PlayerReference pr)
        {
            World           = world;
            InternalName    = pr.Name;
            PlayerReference = pr;

            inMissionMap = world.Map.Visibility.HasFlag(MapVisibility.MissionSelector);

            // Real player or host-created bot
            if (client != null)
            {
                ClientIndex = client.Index;
                Color       = client.Color;
                if (client.Bot != null)
                {
                    var botInfo        = world.Map.Rules.Actors["player"].TraitInfos <IBotInfo>().First(b => b.Type == client.Bot);
                    var botsOfSameType = world.LobbyInfo.Clients.Where(c => c.Bot == client.Bot).ToArray();
                    PlayerName = botsOfSameType.Length == 1 ? botInfo.Name : "{0} {1}".F(botInfo.Name, botsOfSameType.IndexOf(client) + 1);
                }
                else
                {
                    PlayerName = client.Name;
                }

                BotType        = client.Bot;
                Faction        = ChooseFaction(world, client.Faction, !pr.LockFaction);
                DisplayFaction = ChooseDisplayFaction(world, client.Faction);
            }
            else
            {
                // Map player
                ClientIndex    = 0;              // Owned by the host (TODO: fix this)
                Color          = pr.Color;
                PlayerName     = pr.Name;
                NonCombatant   = pr.NonCombatant;
                Playable       = pr.Playable;
                Spectating     = pr.Spectating;
                BotType        = pr.Bot;
                Faction        = ChooseFaction(world, pr.Faction, false);
                DisplayFaction = ChooseDisplayFaction(world, pr.Faction);
            }

            if (!Spectating)
            {
                PlayerMask = new LongBitSet <PlayerBitMask>(InternalName);
            }

            // Set this property before running any Created callbacks on the player actor
            IsBot = BotType != null;

            // Special case handling is required for the Player actor:
            // Since Actor.Created would be called before PlayerActor is assigned here
            // querying player traits in INotifyCreated.Created would crash.
            // Therefore assign the uninitialized actor and run the Created callbacks
            // by calling Initialize ourselves.
            var playerActorType = world.Type == WorldType.Editor ? EditorPlayerActorType : PlayerActorType;

            PlayerActor = new Actor(world, playerActorType, new TypeDictionary {
                new OwnerInit(this)
            });
            PlayerActor.Initialize(true);

            Shroud           = PlayerActor.Trait <Shroud>();
            FrozenActorLayer = PlayerActor.TraitOrDefault <FrozenActorLayer>();

            // Enable the bot logic on the host
            if (IsBot && Game.IsHost)
            {
                var logic = PlayerActor.TraitsImplementing <IBot>().FirstOrDefault(b => b.Info.Type == BotType);
                if (logic == null)
                {
                    Log.Write("debug", "Invalid bot type: {0}", BotType);
                }
                else
                {
                    logic.Activate(this);
                }
            }

            stanceColors.Self     = ChromeMetrics.Get <Color>("PlayerStanceColorSelf");
            stanceColors.Allies   = ChromeMetrics.Get <Color>("PlayerStanceColorAllies");
            stanceColors.Enemies  = ChromeMetrics.Get <Color>("PlayerStanceColorEnemies");
            stanceColors.Neutrals = ChromeMetrics.Get <Color>("PlayerStanceColorNeutrals");

            unlockRenderPlayer = PlayerActor.TraitsImplementing <IUnlocksRenderPlayer>().ToArray();
        }
Example #9
0
        static void Initialize(Arguments args)
        {
            var engineDirArg = args.GetValue("Engine.EngineDir", null);

            if (!string.IsNullOrEmpty(engineDirArg))
            {
                Platform.OverrideEngineDir(engineDirArg);
            }

            var supportDirArg = args.GetValue("Engine.SupportDir", null);

            if (!string.IsNullOrEmpty(supportDirArg))
            {
                Platform.OverrideSupportDir(supportDirArg);
            }

            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            // Load the engine version as early as possible so it can be written to exception logs
            try
            {
                EngineVersion = File.ReadAllText(Path.Combine(Platform.EngineDir, "VERSION")).Trim();
            }
            catch { }

            if (string.IsNullOrEmpty(EngineVersion))
            {
                EngineVersion = "Unknown";
            }

            Console.WriteLine("Engine version is {0}", EngineVersion);
            Console.WriteLine("Runtime: {0}", Platform.RuntimeVersion);

            // Special case handling of Game.Mod argument: if it matches a real filesystem path
            // then we use this to override the mod search path, and replace it with the mod id
            var modID            = args.GetValue("Game.Mod", null);
            var explicitModPaths = new string[0];

            if (modID != null && (File.Exists(modID) || Directory.Exists(modID)))
            {
                explicitModPaths = new[] { modID };
                modID            = Path.GetFileNameWithoutExtension(modID);
            }

            InitializeSettings(args);

            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("server", "server.log", true);
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");
            Log.AddChannel("nat", "nat.log");
            Log.AddChannel("client", "client.log");

            var platforms = new[] { Settings.Game.Platform, "Default", null };

            foreach (var p in platforms)
            {
                if (p == null)
                {
                    throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details.");
                }

                Settings.Game.Platform = p;
                try
                {
                    var rendererPath = Path.Combine(Platform.BinDir, "OpenRA.Platforms." + p + ".dll");

#if !MONO
                    var loader       = new AssemblyLoader(rendererPath);
                    var platformType = loader.LoadDefaultAssembly().GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
#else
                    var assembly     = Assembly.LoadFile(rendererPath);
                    var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
#endif

                    if (platformType == null)
                    {
                        throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation.");
                    }

                    var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null);
                    Renderer = new Renderer(platform, Settings.Graphics);
                    Sound    = new Sound(platform, Settings.Sound);

                    break;
                }
                catch (Exception e)
                {
                    Log.Write("graphics", "{0}", e);
                    Console.WriteLine("Renderer initialization failed. Check graphics.log for details.");

                    Renderer?.Dispose();

                    Sound?.Dispose();
                }
            }

            if (Settings.Server.DiscoverNatDevices)
            {
                discoverNat = UPnP.DiscoverNatDevices(Settings.Server.NatDiscoveryTimeout);
            }

            var modSearchArg   = args.GetValue("Engine.ModSearchPaths", null);
            var modSearchPaths = modSearchArg != null?
                                 FieldLoader.GetValue <string[]>("Engine.ModsPath", modSearchArg) :
                                     new[] { Path.Combine(Platform.EngineDir, "mods") };

            Mods = new InstalledMods(modSearchPaths, explicitModPaths);
            Console.WriteLine("Internal mods:");
            foreach (var mod in Mods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version);
            }

            modLaunchWrapper = args.GetValue("Engine.LaunchWrapper", null);

            ExternalMods = new ExternalMods();

            if (modID != null && Mods.TryGetValue(modID, out _))
            {
                var launchPath = args.GetValue("Engine.LaunchPath", null);
                var launchArgs = new List <string>();

                // Sanitize input from platform-specific launchers
                // Process.Start requires paths to not be quoted, even if they contain spaces
                if (launchPath != null && launchPath.First() == '"' && launchPath.Last() == '"')
                {
                    launchPath = launchPath.Substring(1, launchPath.Length - 2);
                }

                if (launchPath == null)
                {
                    // When launching the assembly directly we must propagate the Engine.EngineDir argument if defined
                    // Platform-specific launchers are expected to manage this internally.
                    launchPath = Assembly.GetEntryAssembly().Location;
                    if (!string.IsNullOrEmpty(engineDirArg))
                    {
                        launchArgs.Add("Engine.EngineDir=\"" + engineDirArg + "\"");
                    }
                }

                ExternalMods.Register(Mods[modID], launchPath, launchArgs, ModRegistration.User);

                if (ExternalMods.TryGetValue(ExternalMod.MakeKey(Mods[modID]), out var activeMod))
                {
                    ExternalMods.ClearInvalidRegistrations(activeMod, ModRegistration.User);
                }
            }

            Console.WriteLine("External mods:");
            foreach (var mod in ExternalMods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
            }

            InitializeMod(modID, args);
        }
Example #10
0
        public static void InitializeMod(string mod, Arguments args)
        {
            // Clear static state if we have switched mods
            LobbyInfoChanged       = () => { };
            ConnectionStateChanged = om => { };
            BeforeGameStart        = () => { };
            OnRemoteDirectConnect  = endpoint => { };
            delayedActions         = new ActionQueue();

            Ui.ResetAll();

            worldRenderer?.Dispose();
            worldRenderer = null;
            server?.Shutdown();
            OrderManager?.Dispose();

            if (ModData != null)
            {
                ModData.ModFiles.UnmountAll();
                ModData.Dispose();
            }

            ModData = null;

            if (mod == null)
            {
                throw new InvalidOperationException("Game.Mod argument missing.");
            }

            if (!Mods.ContainsKey(mod))
            {
                throw new InvalidOperationException("Unknown or invalid mod '{0}'.".F(mod));
            }

            Console.WriteLine("Loading mod: {0}", mod);

            Sound.StopVideo();

            ModData = new ModData(Mods[mod], Mods, true);

            LocalPlayerProfile = new LocalPlayerProfile(Path.Combine(Platform.SupportDir, Settings.Game.AuthProfile), ModData.Manifest.Get <PlayerDatabase>());

            if (!ModData.LoadScreen.BeforeLoad())
            {
                return;
            }

            using (new PerfTimer("LoadMaps"))
                ModData.MapCache.LoadMaps();

            ModData.InitializeLoaders(ModData.DefaultFileSystem);
            Renderer.InitializeFonts(ModData);

            var grid = ModData.Manifest.Contains <MapGrid>() ? ModData.Manifest.Get <MapGrid>() : null;

            Renderer.InitializeDepthBuffer(grid);

            Cursor?.Dispose();

            Cursor = new CursorManager(ModData.CursorProvider);

            PerfHistory.Items["render"].HasNormalTick           = false;
            PerfHistory.Items["batches"].HasNormalTick          = false;
            PerfHistory.Items["render_world"].HasNormalTick     = false;
            PerfHistory.Items["render_widgets"].HasNormalTick   = false;
            PerfHistory.Items["render_flip"].HasNormalTick      = false;
            PerfHistory.Items["terrain_lighting"].HasNormalTick = false;

            JoinLocal();

            try
            {
                discoverNat?.Wait();
            }
            catch (Exception e)
            {
                Console.WriteLine("NAT discovery failed: {0}", e.Message);
                Log.Write("nat", e.ToString());
            }

            ChromeMetrics.TryGet("ChatMessageColor", out chatMessageColor);
            ChromeMetrics.TryGet("SystemMessageColor", out systemMessageColor);
            if (!ChromeMetrics.TryGet("SystemMessageLabel", out systemMessageLabel))
            {
                systemMessageLabel = "Battlefield Control";
            }

            ModData.LoadScreen.StartGame(args);
        }
Example #11
0
        void LoadAsyncInternal()
        {
            Log.Write("debug", "MapCache.LoadAsyncInternal started");

            // Milliseconds to wait on one loop when nothing to do
            var emptyDelay = 50;

            // Keep the thread alive for at least 5 seconds after the last minimap generation
            var maxKeepAlive = 5000 / emptyDelay;
            var keepAlive    = maxKeepAlive;

            for (;;)
            {
                List <MapPreview> todo;
                lock (syncRoot)
                {
                    todo = generateMinimap.Where(p => p.GetMinimap() == null).ToList();
                    generateMinimap.Clear();
                    if (keepAlive > 0)
                    {
                        keepAlive--;
                    }
                    if (keepAlive == 0 && todo.Count == 0)
                    {
                        previewLoaderThreadShutDown = true;
                        break;
                    }
                }

                if (todo.Count == 0)
                {
                    Thread.Sleep(emptyDelay);
                    continue;
                }
                else
                {
                    keepAlive = maxKeepAlive;
                }

                // Render the minimap into the shared sheet
                foreach (var p in todo)
                {
                    // The rendering is thread safe because it only reads from the passed instances and writes to a new bitmap
                    var createdPreview = false;
                    var bitmap         = p.CustomPreview;
                    if (bitmap == null)
                    {
                        createdPreview = true;
                        bitmap         = Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true);
                    }

                    Game.RunAfterTick(() =>
                    {
                        try
                        {
                            p.SetMinimap(sheetBuilder.Add(bitmap));
                        }
                        finally
                        {
                            if (createdPreview)
                            {
                                bitmap.Dispose();
                            }
                        }
                    });

                    // Yuck... But this helps the UI Jank when opening the map selector significantly.
                    Thread.Sleep(Environment.ProcessorCount == 1 ? 25 : 5);
                }
            }

            // The buffer is not fully reclaimed until changes are written out to the texture.
            // We will access the texture in order to force changes to be written out, allowing the buffer to be freed.
            Game.RunAfterTick(() =>
            {
                sheetBuilder.Current.ReleaseBuffer();
                sheetBuilder.Current.GetTexture();
            });
            Log.Write("debug", "MapCache.LoadAsyncInternal ended");
        }
Example #12
0
        public void LoadMaps()
        {
            // Utility mod that does not support maps
            if (!modData.Manifest.Contains <MapGrid>())
            {
                return;
            }

            // Enumerate map directories
            foreach (var kv in modData.Manifest.MapFolders)
            {
                var name           = kv.Key;
                var classification = string.IsNullOrEmpty(kv.Value)
                                        ? MapClassification.Unknown : Enum <MapClassification> .Parse(kv.Value);

                IReadOnlyPackage package;
                var optional = name.StartsWith("~", StringComparison.Ordinal);
                if (optional)
                {
                    name = name.Substring(1);
                }

                try
                {
                    // HACK: If the path is inside the the support directory then we may need to create it
                    // Assume that the path is a directory if there is not an existing file with the same name
                    var resolved = Platform.ResolvePath(name);
                    if (resolved.StartsWith(Platform.SupportDir) && !File.Exists(resolved))
                    {
                        Directory.CreateDirectory(resolved);
                    }

                    package = modData.ModFiles.OpenPackage(name);
                }
                catch
                {
                    if (optional)
                    {
                        continue;
                    }

                    throw;
                }

                mapLocations.Add(package, classification);
            }

            var mapGrid = modData.Manifest.Get <MapGrid>();

            foreach (var kv in MapLocations)
            {
                foreach (var map in kv.Key.Contents)
                {
                    IReadOnlyPackage mapPackage = null;
                    try
                    {
                        using (new Support.PerfTimer(map))
                        {
                            mapPackage = kv.Key.OpenPackage(map, modData.ModFiles);
                            if (mapPackage == null)
                            {
                                continue;
                            }

                            var uid = Map.ComputeUID(mapPackage);
                            previews[uid].UpdateFromMap(mapPackage, kv.Key, kv.Value, modData.Manifest.MapCompatibility, mapGrid.Type);
                        }
                    }
                    catch (Exception e)
                    {
                        mapPackage?.Dispose();
                        Console.WriteLine("Failed to load map: {0}", map);
                        Console.WriteLine("Details: {0}", e);
                        Log.Write("debug", "Failed to load map: {0}", map);
                        Log.Write("debug", "Details: {0}", e);
                    }
                }
            }
        }
Example #13
0
        void LoadAsyncInternal()
        {
            Log.Write("debug", "MapCache.LoadAsyncInternal started");

            // Milliseconds to wait on one loop when nothing to do
            var emptyDelay = 50;

            // Keep the thread alive for at least 5 seconds after the last minimap generation
            var maxKeepAlive = 5000 / emptyDelay;
            var keepAlive    = maxKeepAlive;

            while (true)
            {
                List <MapPreview> todo;
                lock (syncRoot)
                {
                    todo = generateMinimap.Where(p => p.GetMinimap() == null).ToList();
                    generateMinimap.Clear();
                    if (keepAlive > 0)
                    {
                        keepAlive--;
                    }
                    if (keepAlive == 0 && todo.Count == 0)
                    {
                        previewLoaderThreadShutDown = true;
                        break;
                    }
                }

                if (todo.Count == 0)
                {
                    Thread.Sleep(emptyDelay);
                    continue;
                }
                else
                {
                    keepAlive = maxKeepAlive;
                }

                // Render the minimap into the shared sheet
                foreach (var p in todo)
                {
                    if (p.Preview != null)
                    {
                        Game.RunAfterTick(() =>
                        {
                            try
                            {
                                p.SetMinimap(sheetBuilder.Add(p.Preview));
                            }
                            catch (Exception e)
                            {
                                Log.Write("debug", "Failed to load minimap with exception: {0}", e);
                            }
                        });
                    }

                    // Yuck... But this helps the UI Jank when opening the map selector significantly.
                    Thread.Sleep(Environment.ProcessorCount == 1 ? 25 : 5);
                }
            }

            // Release the buffer by forcing changes to be written out to the texture, allowing the buffer to be reclaimed by GC.
            Game.RunAfterTick(sheetBuilder.Current.ReleaseBuffer);
            Log.Write("debug", "MapCache.LoadAsyncInternal ended");
        }
Example #14
0
        public static void InitializeMod(string mod, Arguments args)
        {
            // Clear static state if we have switched mods
            LobbyInfoChanged       = () => { };
            ConnectionStateChanged = om => { };
            BeforeGameStart        = () => { };
            OnRemoteDirectConnect  = (a, b) => { };
            delayedActions         = new ActionQueue();

            Ui.ResetAll();

            if (worldRenderer != null)
            {
                worldRenderer.Dispose();
            }
            worldRenderer = null;
            if (server != null)
            {
                server.Shutdown();
            }
            if (OrderManager != null)
            {
                OrderManager.Dispose();
            }

            if (ModData != null)
            {
                ModData.ModFiles.UnmountAll();
                ModData.Dispose();
            }

            ModData = null;

            // Fall back to default if the mod doesn't exist or has missing prerequisites.
            if (!ModMetadata.AllMods.ContainsKey(mod) || !IsModInstalled(mod))
            {
                mod = new GameSettings().Mod;
            }

            Console.WriteLine("Loading mod: {0}", mod);
            Settings.Game.Mod = mod;

            Sound.StopVideo();

            ModData = new ModData(mod, true);

            using (new PerfTimer("LoadMaps"))
                ModData.MapCache.LoadMaps();

            var installData           = ModData.Manifest.Get <ContentInstaller>();
            var isModContentInstalled = installData.TestFiles.All(f => File.Exists(Platform.ResolvePath(f)));

            // Mod assets are missing!
            if (!isModContentInstalled)
            {
                InitializeMod("modchooser", new Arguments());
                return;
            }

            ModData.InitializeLoaders(ModData.DefaultFileSystem);
            Renderer.InitializeFonts(ModData);

            if (Cursor != null)
            {
                Cursor.Dispose();
            }

            if (Settings.Graphics.HardwareCursors)
            {
                try
                {
                    Cursor = new HardwareCursor(ModData.CursorProvider);
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed to initialize hardware cursors. Falling back to software cursors.");
                    Log.Write("debug", "Error was: " + e.Message);

                    Console.WriteLine("Failed to initialize hardware cursors. Falling back to software cursors.");
                    Console.WriteLine("Error was: " + e.Message);

                    Cursor = new SoftwareCursor(ModData.CursorProvider);
                }
            }
            else
            {
                Cursor = new SoftwareCursor(ModData.CursorProvider);
            }

            PerfHistory.Items["render"].HasNormalTick         = false;
            PerfHistory.Items["batches"].HasNormalTick        = false;
            PerfHistory.Items["render_widgets"].HasNormalTick = false;
            PerfHistory.Items["render_flip"].HasNormalTick    = false;

            JoinLocal();

            ModData.LoadScreen.StartGame(args);
        }
Example #15
0
        internal static void Initialize(Arguments args)
        {
            Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);

            AppDomain.CurrentDomain.AssemblyResolve += GlobalFileSystem.ResolveAssembly;

            Settings = new Settings(Platform.SupportDir + "settings.yaml", args);

            Log.LogPath = Platform.SupportDir + "Logs" + Path.DirectorySeparatorChar;
            Log.AddChannel("perf", "perf.log");
            Log.AddChannel("debug", "debug.log");
            Log.AddChannel("sync", "syncreport.log");
            Log.AddChannel("server", "server.log");
            Log.AddChannel("sound", "sound.log");
            Log.AddChannel("graphics", "graphics.log");
            Log.AddChannel("geoip", "geoip.log");

            if (Settings.Server.DiscoverNatDevices)
            {
                UPnP.TryNatDiscovery();
            }
            else
            {
                Settings.Server.NatDeviceAvailable = false;
                Settings.Server.AllowPortForward   = false;
            }

            try
            {
                GeoIpDatabase = new DatabaseReader("GeoLite2-Country.mmdb");
            }
            catch (Exception e)
            {
                Log.Write("geoip", "DatabaseReader failed: {0}", e);
            }

            GlobalFileSystem.Mount(".");             // Needed to access shaders
            var renderers = new[] { Settings.Graphics.Renderer, "Sdl2", null };

            foreach (var r in renderers)
            {
                if (r == null)
                {
                    throw new InvalidOperationException("No suitable renderers were found. Check graphics.log for details.");
                }

                Settings.Graphics.Renderer = r;
                try
                {
                    Renderer.Initialize(Settings.Graphics.Mode);
                    break;
                }
                catch (Exception e)
                {
                    Log.Write("graphics", "{0}", e);
                    Console.WriteLine("Renderer initialization failed. Fallback in place. Check graphics.log for details.");
                }
            }

            Renderer = new Renderer();

            try
            {
                Sound.Create(Settings.Sound.Engine);
            }
            catch (Exception e)
            {
                Log.Write("sound", "{0}", e);
                Console.WriteLine("Creating the sound engine failed. Fallback in place. Check sound.log for details.");
                Settings.Sound.Engine = "Null";
                Sound.Create(Settings.Sound.Engine);
            }

            Console.WriteLine("Available mods:");
            foreach (var mod in ModMetadata.AllMods)
            {
                Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
            }

            InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null));

            if (Settings.Server.DiscoverNatDevices)
            {
                RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.TryStoppingNatDiscovery);
            }
        }
Example #16
0
        static void InnerLogicTick(OrderManager orderManager)
        {
            var tick = RunTime;

            var world = orderManager.World;

            var uiTickDelta = tick - Ui.LastTickTime;

            if (uiTickDelta >= Timestep)
            {
                // Explained below for the world tick calculation
                var integralTickTimestep = (uiTickDelta / Timestep) * Timestep;
                Ui.LastTickTime += integralTickTimestep >= TimestepJankThreshold ? integralTickTimestep : Timestep;

                Viewport.TicksSinceLastMove += uiTickDelta / Timestep;

                Sync.CheckSyncUnchanged(world, Ui.Tick);
                Cursor.Tick();
            }

            var worldTimestep  = world == null ? Timestep : world.Timestep;
            var worldTickDelta = tick - orderManager.LastTickTime;

            if (worldTimestep != 0 && worldTickDelta >= worldTimestep)
            {
                using (new PerfSample("tick_time"))
                {
                    // Tick the world to advance the world time to match real time:
                    //    If dt < TickJankThreshold then we should try and catch up by repeatedly ticking
                    //    If dt >= TickJankThreshold then we should accept the jank and progress at the normal rate
                    // dt is rounded down to an integer tick count in order to preserve fractional tick components.
                    var integralTickTimestep = (worldTickDelta / worldTimestep) * worldTimestep;
                    orderManager.LastTickTime += integralTickTimestep >= TimestepJankThreshold ? integralTickTimestep : worldTimestep;

                    Sound.Tick();
                    Sync.CheckSyncUnchanged(world, orderManager.TickImmediate);

                    if (world == null)
                    {
                        return;
                    }

                    // Don't tick when the shellmap is disabled
                    if (world.ShouldTick)
                    {
                        var isNetTick = LocalTick % NetTickScale == 0;

                        if (!isNetTick || orderManager.IsReadyForNextFrame)
                        {
                            ++orderManager.LocalFrameNumber;

                            Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");

                            if (BenchmarkMode)
                            {
                                Log.Write("cpu", "{0};{1}".F(LocalTick, PerfHistory.Items["tick_time"].LastValue));
                            }

                            if (isNetTick)
                            {
                                orderManager.Tick();
                            }

                            Sync.CheckSyncUnchanged(world, () =>
                            {
                                world.OrderGenerator.Tick(world);
                                world.Selection.Tick(world);
                            });

                            world.Tick();

                            PerfHistory.Tick();
                        }
                        else if (orderManager.NetFrameNumber == 0)
                        {
                            orderManager.LastTickTime = RunTime;
                        }

                        Sync.CheckSyncUnchanged(world, () => world.TickRender(worldRenderer));
                    }
                    else
                    {
                        PerfHistory.Tick();
                    }
                }
            }
        }
Example #17
0
		internal void Register(Manifest mod, string launchPath, IEnumerable<string> launchArgs, ModRegistration registration)
		{
			if (mod.Metadata.Hidden)
				return;

			var key = ExternalMod.MakeKey(mod);
			var yaml = new MiniYamlNode("Registration", new MiniYaml("", new List<MiniYamlNode>()
			{
				new MiniYamlNode("Id", mod.Id),
				new MiniYamlNode("Version", mod.Metadata.Version),
				new MiniYamlNode("Title", mod.Metadata.Title),
				new MiniYamlNode("LaunchPath", launchPath),
				new MiniYamlNode("LaunchArgs", new[] { "Game.Mod=" + mod.Id }.Concat(launchArgs).JoinWith(", "))
			}));

			using (var stream = mod.Package.GetStream("icon.png"))
				if (stream != null)
					yaml.Value.Nodes.Add(new MiniYamlNode("Icon", Convert.ToBase64String(stream.ReadAllBytes())));

			using (var stream = mod.Package.GetStream("icon-2x.png"))
				if (stream != null)
					yaml.Value.Nodes.Add(new MiniYamlNode("Icon2x", Convert.ToBase64String(stream.ReadAllBytes())));

			using (var stream = mod.Package.GetStream("icon-3x.png"))
				if (stream != null)
					yaml.Value.Nodes.Add(new MiniYamlNode("Icon3x", Convert.ToBase64String(stream.ReadAllBytes())));

			var sources = new List<string>();
			if (registration.HasFlag(ModRegistration.System))
				sources.Add(Platform.GetSupportDir(SupportDirType.System));

			if (registration.HasFlag(ModRegistration.User))
			{
				sources.Add(Platform.GetSupportDir(SupportDirType.User));

				// If using the modern support dir we must also write the registration
				// to the legacy support dir for older engine versions, but ONLY if it exists
				var legacyPath = Platform.GetSupportDir(SupportDirType.LegacyUser);
				if (Directory.Exists(legacyPath))
					sources.Add(legacyPath);
			}

			// Make sure the mod is available for this session, even if saving it fails
			LoadMod(yaml.Value, forceRegistration: true);

			var lines = new List<MiniYamlNode> { yaml }.ToLines().ToArray();
			foreach (var source in sources.Distinct())
			{
				var metadataPath = Path.Combine(source, "ModMetadata");

				try
				{
					Directory.CreateDirectory(metadataPath);
					File.WriteAllLines(Path.Combine(metadataPath, key + ".yaml"), lines);
				}
				catch (Exception e)
				{
					Log.Write("debug", "Failed to register current mod metadata");
					Log.Write("debug", e.ToString());
				}
			}
		}
Example #18
0
        public ModData(Manifest mod, InstalledMods mods, bool useLoadScreen = false)
        {
            Languages = new string[0];

            // Take a local copy of the manifest
            Manifest       = new Manifest(mod.Id, mod.Package);
            ObjectCreator  = new ObjectCreator(Manifest, mods);
            PackageLoaders = ObjectCreator.GetLoaders <IPackageLoader>(Manifest.PackageFormats, "package");

            ModFiles = new FS(mod.Id, mods, PackageLoaders);
            ModFiles.LoadFromManifest(Manifest);
            Manifest.LoadCustomData(ObjectCreator);

            if (useLoadScreen)
            {
                LoadScreen = ObjectCreator.CreateObject <ILoadScreen>(Manifest.LoadScreen.Value);
                LoadScreen.Init(this, Manifest.LoadScreen.ToDictionary(my => my.Value));
                LoadScreen.Display();
            }

            WidgetLoader = new WidgetLoader(this);
            MapCache     = new MapCache(this);

            SoundLoaders  = ObjectCreator.GetLoaders <ISoundLoader>(Manifest.SoundFormats, "sound");
            SpriteLoaders = ObjectCreator.GetLoaders <ISpriteLoader>(Manifest.SpriteFormats, "sprite");
            VideoLoaders  = ObjectCreator.GetLoaders <IVideoLoader>(Manifest.VideoFormats, "video");

            var terrainFormat = Manifest.Get <TerrainFormat>();
            var terrainLoader = ObjectCreator.FindType(terrainFormat.Type + "Loader");
            var terrainCtor   = terrainLoader?.GetConstructor(new[] { typeof(ModData) });

            if (terrainLoader == null || !terrainLoader.GetInterfaces().Contains(typeof(ITerrainLoader)) || terrainCtor == null)
            {
                throw new InvalidOperationException($"Unable to find a terrain loader for type '{terrainFormat.Type}'.");
            }

            TerrainLoader = (ITerrainLoader)terrainCtor.Invoke(new[] { this });

            var sequenceFormat = Manifest.Get <SpriteSequenceFormat>();
            var sequenceLoader = ObjectCreator.FindType(sequenceFormat.Type + "Loader");
            var sequenceCtor   = sequenceLoader != null?sequenceLoader.GetConstructor(new[] { typeof(ModData) }) : null;

            if (sequenceLoader == null || !sequenceLoader.GetInterfaces().Contains(typeof(ISpriteSequenceLoader)) || sequenceCtor == null)
            {
                throw new InvalidOperationException($"Unable to find a sequence loader for type '{sequenceFormat.Type}'.");
            }

            SpriteSequenceLoader = (ISpriteSequenceLoader)sequenceCtor.Invoke(new[] { this });

            var modelFormat = Manifest.Get <ModelSequenceFormat>();
            var modelLoader = ObjectCreator.FindType(modelFormat.Type + "Loader");
            var modelCtor   = modelLoader != null?modelLoader.GetConstructor(new[] { typeof(ModData) }) : null;

            if (modelLoader == null || !modelLoader.GetInterfaces().Contains(typeof(IModelSequenceLoader)) || modelCtor == null)
            {
                throw new InvalidOperationException($"Unable to find a model loader for type '{modelFormat.Type}'.");
            }

            ModelSequenceLoader = (IModelSequenceLoader)modelCtor.Invoke(new[] { this });
            ModelSequenceLoader.OnMissingModelError = s => Log.Write("debug", s);

            Hotkeys = new HotkeyManager(ModFiles, Game.Settings.Keys, Manifest);

            defaultRules       = Exts.Lazy(() => Ruleset.LoadDefaults(this));
            defaultTerrainInfo = Exts.Lazy(() =>
            {
                var items = new Dictionary <string, ITerrainInfo>();

                foreach (var file in Manifest.TileSets)
                {
                    var t = TerrainLoader.ParseTerrain(DefaultFileSystem, file);
                    items.Add(t.Id, t);
                }

                return((IReadOnlyDictionary <string, ITerrainInfo>)(new ReadOnlyDictionary <string, ITerrainInfo>(items)));
            });

            defaultSequences = Exts.Lazy(() =>
            {
                var items = DefaultTerrainInfo.ToDictionary(t => t.Key, t => new SequenceProvider(DefaultFileSystem, this, t.Key, null));
                return((IReadOnlyDictionary <string, SequenceProvider>)(new ReadOnlyDictionary <string, SequenceProvider>(items)));
            });

            initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
        }
Example #19
0
        public static void InitializeMod(string mod, Arguments args)
        {
            // Clear static state if we have switched mods
            LobbyInfoChanged       = () => { };
            ConnectionStateChanged = om => { };
            BeforeGameStart        = () => { };
            OnRemoteDirectConnect  = (a, b) => { };
            delayedActions         = new ActionQueue();

            Ui.ResetAll();

            if (worldRenderer != null)
            {
                worldRenderer.Dispose();
            }
            worldRenderer = null;
            if (server != null)
            {
                server.Shutdown();
            }
            if (OrderManager != null)
            {
                OrderManager.Dispose();
            }

            if (ModData != null)
            {
                ModData.Dispose();
            }
            ModData = null;

            // Fall back to default if the mod doesn't exist
            if (!ModMetadata.AllMods.ContainsKey(mod))
            {
                mod = new GameSettings().Mod;
            }

            Console.WriteLine("Loading mod: {0}", mod);
            Settings.Game.Mod = mod;

            Sound.StopVideo();
            Sound.Initialize();

            ModData = new ModData(mod, !Settings.Server.Dedicated);
            ModData.InitializeLoaders();
            if (!Settings.Server.Dedicated)
            {
                Renderer.InitializeFonts(ModData.Manifest);
            }

            using (new PerfTimer("LoadMaps"))
                ModData.MapCache.LoadMaps();

            if (Cursor != null)
            {
                Cursor.Dispose();
            }

            if (Settings.Graphics.HardwareCursors)
            {
                try
                {
                    Cursor = new HardwareCursor(ModData.CursorProvider);
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed to initialize hardware cursors. Falling back to software cursors.");
                    Log.Write("debug", "Error was: " + e.Message);

                    Console.WriteLine("Failed to initialize hardware cursors. Falling back to software cursors.");
                    Console.WriteLine("Error was: " + e.Message);

                    Cursor = new SoftwareCursor(ModData.CursorProvider);
                    Settings.Graphics.HardwareCursors = false;
                }
            }
            else
            {
                Cursor = new SoftwareCursor(ModData.CursorProvider);
            }

            PerfHistory.Items["render"].HasNormalTick         = false;
            PerfHistory.Items["batches"].HasNormalTick        = false;
            PerfHistory.Items["render_widgets"].HasNormalTick = false;
            PerfHistory.Items["render_flip"].HasNormalTick    = false;

            JoinLocal();

            if (Settings.Server.Dedicated)
            {
                while (true)
                {
                    Settings.Server.Map = WidgetUtils.ChooseInitialMap(Settings.Server.Map);
                    Settings.Save();
                    CreateServer(new ServerSettings(Settings.Server));
                    while (true)
                    {
                        Thread.Sleep(100);

                        if (server.State == Server.ServerState.GameStarted && server.Conns.Count < 1)
                        {
                            Console.WriteLine("No one is playing, shutting down...");
                            server.Shutdown();
                            break;
                        }
                    }

                    if (Settings.Server.DedicatedLoop)
                    {
                        Console.WriteLine("Starting a new server instance...");
                        ModData.MapCache.LoadMaps();
                        continue;
                    }

                    break;
                }

                Environment.Exit(0);
            }
            else
            {
                ModData.LoadScreen.StartGame(args);
            }
        }