Example #1
0
        public void StartGame(Arguments args)
        {
            Launch = new LaunchArguments(args);
            Ui.ResetAll();
            Game.Settings.Save();

            if (Launch.Benchmark)
            {
                Log.AddChannel("cpu", "cpu.csv");
                Log.Write("cpu", "tick;time [ms]");

                Log.AddChannel("render", "render.csv");
                Log.Write("render", "frame;time [ms]");

                Console.WriteLine("Saving benchmark data into {0}".F(Path.Combine(Platform.SupportDir, "Logs")));

                Game.BenchmarkMode = true;
            }

            // Join a server directly
            var connect = Launch.GetConnectAddress();

            if (!string.IsNullOrEmpty(connect))
            {
                var parts = connect.Split(':');

                if (parts.Length == 2)
                {
                    var host = parts[0];
                    var port = Exts.ParseIntegerInvariant(parts[1]);
                    Game.LoadShellMap();
                    Game.RemoteDirectConnect(host, port);
                    return;
                }
            }

            // Load a replay directly
            if (!string.IsNullOrEmpty(Launch.Replay))
            {
                var replayMeta = ReplayMetadata.Read(Launch.Replay);
                if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap))
                {
                    Game.JoinReplay(Launch.Replay);
                }

                if (replayMeta != null)
                {
                    var mod = replayMeta.GameInfo.Mod;
                    if (mod != null && mod != Game.ModData.Manifest.Mod.Id && ModMetadata.AllMods.ContainsKey(mod))
                    {
                        Game.InitializeMod(mod, args);
                    }
                }

                return;
            }

            Game.LoadShellMap();
            Game.Settings.Save();
        }
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            var replay = ReplayMetadata.Read(args[1]);

            if (replay == null)
            {
                throw new InvalidDataException("Failed to read replay meta data");
            }

            var info = replay.GameInfo;

            var lines = FieldSaver.Save(info).ToLines(replay.FilePath);

            foreach (var line in lines)
            {
                Console.WriteLine(line);
            }

            Console.WriteLine("\tPlayers:");
            var playerCount = 0;

            foreach (var p in info.Players)
            {
                var playerLines = FieldSaver.Save(p).ToLines("{0}".F(playerCount++));
                foreach (var line in playerLines)
                {
                    Console.WriteLine("\t\t" + line);
                }
            }
        }
Example #3
0
        public virtual void StartGame(Arguments args)
        {
            Launch = new LaunchArguments(args);
            Ui.ResetAll();
            Game.Settings.Save();

            if (!string.IsNullOrEmpty(Launch.Benchmark))
            {
                Console.WriteLine("Saving benchmark data into {0}".F(Path.Combine(Platform.SupportDir, "Logs")));

                Game.BenchmarkMode(Launch.Benchmark);
            }

            // Join a server directly
            var connect = Launch.GetConnectEndPoint();

            if (connect != null)
            {
                Game.LoadShellMap();
                Game.RemoteDirectConnect(connect);
                return;
            }

            // Start a map directly
            if (!string.IsNullOrEmpty(Launch.Map))
            {
                Game.LoadMap(Launch.Map);
                return;
            }

            // Load a replay directly
            if (!string.IsNullOrEmpty(Launch.Replay))
            {
                ReplayMetadata replayMeta = null;
                try
                {
                    replayMeta = ReplayMetadata.Read(Launch.Replay);
                }
                catch { }

                if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap))
                {
                    Game.JoinReplay(Launch.Replay);
                }

                if (replayMeta != null)
                {
                    var mod = replayMeta.GameInfo.Mod;
                    if (mod != null && mod != Game.ModData.Manifest.Id && Game.Mods.ContainsKey(mod))
                    {
                        Game.InitializeMod(mod, args);
                    }
                }

                return;
            }

            Game.LoadShellMap();
            Game.Settings.Save();
        }
Example #4
0
 void RenameReplay(ReplayMetadata replay, string newFilenameWithoutExtension)
 {
     try
     {
         replay.RenameFile(newFilenameWithoutExtension);
         replayState[replay].Item.Text = newFilenameWithoutExtension;
     }
     catch (Exception ex)
     {
         Log.Write("debug", ex.ToString());
         return;
     }
 }
Example #5
0
        public void StartGame(Arguments args)
        {
            Launch = new LaunchArguments(args);
            Ui.ResetAll();
            Game.Settings.Save();

            // Join a server directly
            var connect = Launch.GetConnectAddress();

            if (!string.IsNullOrEmpty(connect))
            {
                var parts = connect.Split(':');

                if (parts.Length == 2)
                {
                    var host = parts[0];
                    var port = Exts.ParseIntegerInvariant(parts[1]);
                    Game.LoadShellMap();
                    Game.RemoteDirectConnect(host, port);
                    return;
                }
            }

            // Load a replay directly
            if (!string.IsNullOrEmpty(Launch.Replay))
            {
                var replayMeta = ReplayMetadata.Read(Launch.Replay);
                if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap))
                {
                    Game.JoinReplay(Launch.Replay);
                }

                if (replayMeta != null)
                {
                    var mod = replayMeta.GameInfo.Mod;
                    if (mod != null && mod != Game.ModData.Manifest.Mod.Id && ModMetadata.AllMods.ContainsKey(mod))
                    {
                        Game.InitializeMod(mod, args);
                    }
                }

                return;
            }

            Game.LoadShellMap();
            Game.Settings.Save();
        }
Example #6
0
        void RenameReplay(ReplayMetadata replay, string newFilenameWithoutExtension)
        {
            try
            {
                var item = replayState[replay].Item;
                replay.RenameFile(newFilenameWithoutExtension);
                item.Text = newFilenameWithoutExtension;

                var label = item.Get <LabelWithTooltipWidget>("TITLE");
                WidgetUtils.TruncateLabelToTooltip(label, item.Text);
            }
            catch (Exception ex)
            {
                Log.Write("debug", ex.ToString());
                return;
            }
        }
Example #7
0
        void AddReplay(ReplayMetadata replay, ScrollItemWidget template)
        {
            var item = ScrollItemWidget.Setup(template,
                                              () => selectedReplay == replay,
                                              () => SelectReplay(replay),
                                              () => WatchReplay());

            replayState[replay] = new ReplayState
            {
                Item    = item,
                Visible = true
            };

            item.Text = Path.GetFileNameWithoutExtension(replay.FilePath);
            item.Get <LabelWidget>("TITLE").GetText = () => item.Text;
            item.IsVisible = () => replayState[replay].Visible;
            replayList.AddChild(item);
        }
Example #8
0
        public static bool PromptConfirmReplayCompatibility(ReplayMetadata replayMeta, Action onCancel = null)
        {
            if (onCancel == null)
            {
                onCancel = DoNothing;
            }

            if (replayMeta == null)
            {
                return(IncompatibleReplayDialog("outdated engine", null, onCancel));
            }

            var version = replayMeta.GameInfo.Version;

            if (version == null)
            {
                return(IncompatibleReplayDialog("unknown version", version, onCancel));
            }

            var mod = replayMeta.GameInfo.Mod;

            if (mod == null)
            {
                return(IncompatibleReplayDialog("unknown mod", mod, onCancel));
            }

            var allMods = ModMetadata.AllMods;

            if (!allMods.ContainsKey(mod))
            {
                return(IncompatibleReplayDialog("unavailable mod", mod, onCancel));
            }
            else if (allMods[mod].Version != version)
            {
                return(IncompatibleReplayDialog("incompatible version", version, onCancel));
            }

            if (replayMeta.GameInfo.MapPreview.Status != MapStatus.Available)
            {
                return(IncompatibleReplayDialog("unavailable map", replayMeta.GameInfo.MapUid, onCancel));
            }

            return(true);
        }
Example #9
0
        public static bool PromptConfirmReplayCompatibility(ReplayMetadata replayMeta, Action onCancel = null)
        {
            if (onCancel == null)
            {
                onCancel = DoNothing;
            }

            if (replayMeta == null)
            {
                ConfirmationDialogs.ButtonPrompt("Incompatible Replay", "Replay metadata could not be read.", onCancel: onCancel);
                return(false);
            }

            var version = replayMeta.GameInfo.Version;

            if (version == null)
            {
                return(IncompatibleReplayDialog("unknown version", version, onCancel));
            }

            var mod = replayMeta.GameInfo.Mod;

            if (mod == null)
            {
                return(IncompatibleReplayDialog("unknown mod", mod, onCancel));
            }

            if (!Game.Mods.ContainsKey(mod))
            {
                return(IncompatibleReplayDialog("unavailable mod", mod, onCancel));
            }

            if (Game.Mods[mod].Metadata.Version != version)
            {
                return(IncompatibleReplayDialog("incompatible version", version, onCancel));
            }

            if (replayMeta.GameInfo.MapPreview.Status != MapStatus.Available)
            {
                return(IncompatibleReplayDialog("unavailable map", replayMeta.GameInfo.MapUid, onCancel));
            }

            return(true);
        }
Example #10
0
        void DeleteReplay(ReplayMetadata replay)
        {
            try
            {
                File.Delete(replay.FilePath);
            }
            catch (Exception ex)
            {
                Game.Debug("Failed to delete replay file '{0}'. See the logs for details.", replay.FilePath);
                Log.Write("debug", ex.ToString());
                return;
            }

            if (replay == selectedReplay)
            {
                SelectReplay(null);
            }

            replayList.RemoveChild(replayState[replay].Item);
            replays.Remove(replay);
            replayState.Remove(replay);
        }
Example #11
0
        void LoadReplays(string dir, ScrollItemWidget template)
        {
            using (new Support.PerfTimer("Load replays"))
            {
                var loadedReplays = new ConcurrentBag <ReplayMetadata>();
                Parallel.ForEach(Directory.GetFiles(dir, "*.orarep", SearchOption.AllDirectories), (fileName, pls) =>
                {
                    if (cancelLoadingReplays)
                    {
                        pls.Stop();
                        return;
                    }

                    var replay = ReplayMetadata.Read(fileName);
                    if (replay != null)
                    {
                        loadedReplays.Add(replay);
                    }
                });

                if (cancelLoadingReplays)
                {
                    return;
                }

                var sortedReplays = loadedReplays.OrderByDescending(replay => replay.GameInfo.StartTimeUtc).ToList();
                Game.RunAfterTick(() =>
                {
                    replayList.RemoveChildren();
                    foreach (var replay in sortedReplays)
                    {
                        AddReplay(replay, template);
                    }

                    SetupReplayDependentFilters();
                    ApplyFilter();
                });
            }
        }
Example #12
0
        void AddReplay(ReplayMetadata replay, ScrollItemWidget template)
        {
            replays.Add(replay);

            var item = ScrollItemWidget.Setup(template,
                                              () => selectedReplay == replay,
                                              () => SelectReplay(replay),
                                              () => WatchReplay());

            replayState[replay] = new ReplayState
            {
                Item    = item,
                Visible = true
            };

            item.Text = Path.GetFileNameWithoutExtension(replay.FilePath);
            var label = item.Get <LabelWithTooltipWidget>("TITLE");

            WidgetUtils.TruncateLabelToTooltip(label, item.Text);

            item.IsVisible = () => replayState[replay].Visible;
            replayList.AddChild(item);
        }
        public void Run(ModData modData, string[] args)
        {
            var replay = ReplayMetadata.Read(args[1]);
            var info   = replay.GameInfo;

            var lines = FieldSaver.Save(info).ToLines(replay.FilePath);

            foreach (var line in lines)
            {
                Console.WriteLine(line);
            }

            Console.WriteLine("\tPlayers:");
            var playerCount = 0;

            foreach (var p in info.Players)
            {
                var playerLines = FieldSaver.Save(p).ToLines("{0}".F(playerCount++));
                foreach (var line in playerLines)
                {
                    Console.WriteLine("\t\t" + line);
                }
            }
        }
Example #14
0
        public void StartGame(Arguments args)
        {
            Ui.ResetAll();
            Game.Settings.Save();

            // Check whether the mod content is installed
            // TODO: The installation code has finally been beaten into shape, so we can
            // finally move it all into the planned "Manage Content" panel in the modchooser mod.
            var installData       = Game.ModData.Manifest.Get <ContentInstaller>();
            var installModContent = !installData.TestFiles.All(f => GlobalFileSystem.Exists(f));
            var installModMusic   = args != null && args.Contains("Install.Music");

            if (installModContent || installModMusic)
            {
                var widgetArgs = new WidgetArgs()
                {
                    { "continueLoading", () => Game.InitializeMod(Game.Settings.Game.Mod, args) },
                };

                if (installData.BackgroundWidget != null)
                {
                    Ui.LoadWidget(installData.BackgroundWidget, Ui.Root, widgetArgs);
                }

                var menu = installModContent ? installData.MenuWidget : installData.MusicMenuWidget;
                Ui.OpenWindow(menu, widgetArgs);

                return;
            }

            // Join a server directly
            var connect = string.Empty;

            if (args != null)
            {
                if (args.Contains("Launch.Connect"))
                {
                    connect = args.GetValue("Launch.Connect", null);
                }

                if (args.Contains("Launch.URI"))
                {
                    connect = args.GetValue("Launch.URI", null);
                    if (connect != null)
                    {
                        connect = connect.Replace("openra://", "");
                        connect = connect.TrimEnd('/');
                    }
                }
            }

            if (!string.IsNullOrEmpty(connect))
            {
                var parts = connect.Split(':');

                if (parts.Length == 2)
                {
                    var host = parts[0];
                    var port = Exts.ParseIntegerInvariant(parts[1]);
                    Game.LoadShellMap();
                    Game.RemoteDirectConnect(host, port);
                    return;
                }
            }

            // Load a replay directly
            var replayFilename = args != null?args.GetValue("Launch.Replay", null) : null;

            if (!string.IsNullOrEmpty(replayFilename))
            {
                var replayMeta = ReplayMetadata.Read(replayFilename);
                if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap))
                {
                    Game.JoinReplay(replayFilename);
                }

                if (replayMeta != null)
                {
                    var mod = replayMeta.GameInfo.Mod;
                    if (mod != null && mod != Game.ModData.Manifest.Mod.Id && ModMetadata.AllMods.ContainsKey(mod))
                    {
                        Game.InitializeMod(mod, args);
                    }
                }

                return;
            }

            Game.LoadShellMap();
            Game.Settings.Save();
        }
Example #15
0
        void SelectReplay(ReplayMetadata replay)
        {
            selectedReplay = replay;
            map            = selectedReplay != null ? selectedReplay.GameInfo.MapPreview : MapCache.UnknownMap;

            if (replay == null)
            {
                return;
            }

            try
            {
                if (map.Status != MapStatus.Available)
                {
                    if (map.Status == MapStatus.DownloadAvailable)
                    {
                        LoadMapPreviewRules(map);
                    }
                    else if (Game.Settings.Game.AllowDownloading)
                    {
                        modData.MapCache.QueryRemoteMapDetails(services.MapRepository, new[] { map.Uid }, LoadMapPreviewRules);
                    }
                }

                var players = replay.GameInfo.Players
                              .GroupBy(p => p.Team)
                              .OrderBy(g => g.Key);

                var teams   = new Dictionary <string, IEnumerable <GameInformation.Player> >();
                var noTeams = players.Count() == 1;
                foreach (var p in players)
                {
                    var label = noTeams ? "Players" : p.Key == 0 ? "No Team" : "Team {0}".F(p.Key);
                    teams.Add(label, p);
                }

                playerList.RemoveChildren();

                foreach (var kv in teams)
                {
                    var group = kv.Key;
                    if (group.Length > 0)
                    {
                        var header = ScrollItemWidget.Setup(playerHeader, () => true, () => { });
                        header.Get <LabelWidget>("LABEL").GetText = () => group;
                        playerList.AddChild(header);
                    }

                    foreach (var option in kv.Value)
                    {
                        var o = option;

                        var color = o.Color;

                        var item = ScrollItemWidget.Setup(playerTemplate, () => false, () => { });

                        var label = item.Get <LabelWidget>("LABEL");
                        var font  = Game.Renderer.Fonts[label.Font];
                        var name  = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font);
                        label.GetText  = () => name;
                        label.GetColor = () => color;

                        var flag = item.Get <ImageWidget>("FLAG");
                        flag.GetImageCollection = () => "flags";
                        var factionInfo = modData.DefaultRules.Actors["world"].TraitInfos <FactionInfo>();
                        flag.GetImageName = () => (factionInfo != null && factionInfo.Any(f => f.InternalName == o.FactionId)) ? o.FactionId : "Random";

                        playerList.AddChild(item);
                    }
                }
            }
            catch (Exception e)
            {
                Log.Write("debug", "Exception while parsing replay: {0}", e);
                SelectReplay(null);
            }
        }
Example #16
0
        bool EvaluateReplayVisibility(ReplayMetadata replay)
        {
            // Game type
            if ((filter.Type == GameType.Multiplayer && replay.GameInfo.IsSinglePlayer) || (filter.Type == GameType.Singleplayer && !replay.GameInfo.IsSinglePlayer))
            {
                return(false);
            }

            // Date type
            if (filter.Date != DateType.Any)
            {
                TimeSpan t;
                switch (filter.Date)
                {
                case DateType.Today:
                    t = TimeSpan.FromDays(1d);
                    break;

                case DateType.LastWeek:
                    t = TimeSpan.FromDays(7d);
                    break;

                case DateType.LastFortnight:
                    t = TimeSpan.FromDays(14d);
                    break;

                case DateType.LastMonth:
                default:
                    t = TimeSpan.FromDays(30d);
                    break;
                }

                if (replay.GameInfo.StartTimeUtc < DateTime.UtcNow - t)
                {
                    return(false);
                }
            }

            // Duration
            if (filter.Duration != DurationType.Any)
            {
                var minutes = replay.GameInfo.Duration.TotalMinutes;
                switch (filter.Duration)
                {
                case DurationType.VeryShort:
                    if (minutes >= 5)
                    {
                        return(false);
                    }
                    break;

                case DurationType.Short:
                    if (minutes < 5 || minutes >= 20)
                    {
                        return(false);
                    }
                    break;

                case DurationType.Medium:
                    if (minutes < 20 || minutes >= 60)
                    {
                        return(false);
                    }
                    break;

                case DurationType.Long:
                    if (minutes < 60)
                    {
                        return(false);
                    }
                    break;
                }
            }

            // Map
            if (!string.IsNullOrEmpty(filter.MapName) && string.Compare(filter.MapName, replay.GameInfo.MapTitle, true) != 0)
            {
                return(false);
            }

            // Player
            if (!string.IsNullOrEmpty(filter.PlayerName))
            {
                var player = replay.GameInfo.Players.FirstOrDefault(p => string.Compare(filter.PlayerName, p.Name, true) == 0);
                if (player == null)
                {
                    return(false);
                }

                // Outcome
                if (filter.Outcome != WinState.Undefined && filter.Outcome != player.Outcome)
                {
                    return(false);
                }

                // Faction
                if (!string.IsNullOrEmpty(filter.Faction) && string.Compare(filter.Faction, player.FactionName, true) != 0)
                {
                    return(false);
                }
            }

            return(true);
        }
        public ReplayBrowserLogic(Widget widget, Action onExit, Action onStart)
        {
            panel = widget;

            playerList     = panel.Get <ScrollPanelWidget>("PLAYER_LIST");
            playerHeader   = playerList.Get <ScrollItemWidget>("HEADER");
            playerTemplate = playerList.Get <ScrollItemWidget>("TEMPLATE");
            playerList.RemoveChildren();

            panel.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };

            replayList = panel.Get <ScrollPanelWidget>("REPLAY_LIST");
            var template = panel.Get <ScrollItemWidget>("REPLAY_TEMPLATE");

            var mod = Game.modData.Manifest.Mod;
            var dir = new[] { Platform.SupportDir, "Replays", mod.Id, mod.Version }.Aggregate(Path.Combine);

            replayList.RemoveChildren();
            if (Directory.Exists(dir))
            {
                using (new Support.PerfTimer("Load replays"))
                {
                    replays = Directory
                              .GetFiles(dir, "*.rep")
                              .Select((filename) => ReplayMetadata.Read(filename))
                              .Where((r) => r != null)
                              .OrderByDescending(r => r.GameInfo.StartTimeUtc)
                              .ToList();
                }

                foreach (var replay in replays)
                {
                    AddReplay(replay, template);
                }

                ApplyFilter();
            }
            else
            {
                replays = new List <ReplayMetadata>();
            }

            var watch = panel.Get <ButtonWidget>("WATCH_BUTTON");

            watch.IsDisabled = () => selectedReplay == null || selectedReplay.GameInfo.MapPreview.Status != MapStatus.Available;
            watch.OnClick    = () => { WatchReplay(); onStart(); };

            panel.Get("REPLAY_INFO").IsVisible = () => selectedReplay != null;

            var preview = panel.Get <MapPreviewWidget>("MAP_PREVIEW");

            preview.SpawnOccupants = () => selectedSpawns;
            preview.Preview        = () => selectedReplay != null ? selectedReplay.GameInfo.MapPreview : null;

            var title = panel.GetOrNull <LabelWidget>("MAP_TITLE");

            if (title != null)
            {
                title.GetText = () => selectedReplay != null ? selectedReplay.GameInfo.MapPreview.Title : null;
            }

            var type = panel.GetOrNull <LabelWidget>("MAP_TYPE");

            if (type != null)
            {
                type.GetText = () => selectedReplay.GameInfo.MapPreview.Type;
            }

            panel.Get <LabelWidget>("DURATION").GetText = () => WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds);

            SetupFilters();
            SetupManagement();
        }
Example #18
0
        void SelectReplay(ReplayMetadata replay)
        {
            selectedReplay = replay;
            selectedSpawns = (selectedReplay != null)
                                ? LobbyUtils.GetSpawnOccupants(selectedReplay.GameInfo.Players, selectedReplay.GameInfo.MapPreview)
                                : new Dictionary <CPos, SpawnOccupant>();

            if (replay == null)
            {
                return;
            }

            try
            {
                var players = replay.GameInfo.Players
                              .GroupBy(p => p.Team)
                              .OrderBy(g => g.Key);

                var teams   = new Dictionary <string, IEnumerable <GameInformation.Player> >();
                var noTeams = players.Count() == 1;
                foreach (var p in players)
                {
                    var label = noTeams ? "Players" : p.Key == 0 ? "No Team" : "Team {0}".F(p.Key);
                    teams.Add(label, p);
                }

                playerList.RemoveChildren();

                foreach (var kv in teams)
                {
                    var group = kv.Key;
                    if (group.Length > 0)
                    {
                        var header = ScrollItemWidget.Setup(playerHeader, () => true, () => { });
                        header.Get <LabelWidget>("LABEL").GetText = () => group;
                        playerList.AddChild(header);
                    }

                    foreach (var option in kv.Value)
                    {
                        var o = option;

                        var color = o.Color.RGB;

                        var item = ScrollItemWidget.Setup(playerTemplate, () => false, () => { });

                        var label = item.Get <LabelWidget>("LABEL");
                        label.GetText  = () => o.Name;
                        label.GetColor = () => color;

                        var flag = item.Get <ImageWidget>("FLAG");
                        flag.GetImageCollection = () => "flags";
                        flag.GetImageName       = () => o.FactionId;

                        playerList.AddChild(item);
                    }
                }
            }
            catch (Exception e)
            {
                Log.Write("debug", "Exception while parsing replay: {0}", e);
                SelectReplay(null);
            }
        }
Example #19
0
        internal Embed CreateEmbed(ReplayMetadata replayMetadata, string replayLink = null)
        {
            var mapEmbed  = _mapToEmbedTransformer.CreateEmbed(replayMetadata.MapUid);
            var startTime = DateTime.ParseExact(replayMetadata.StartTimeUtc, "yyyy-MM-dd HH-mm-ss", new NumberFormatInfo());
            var endTime   = DateTime.ParseExact(replayMetadata.EndTimeUtc, "yyyy-MM-dd HH-mm-ss", new NumberFormatInfo());

            var fields = new List <EmbedFieldBuilder>
            {
                new EmbedFieldBuilder
                {
                    IsInline = true,
                    Name     = "Mod:",
                    Value    = replayMetadata.Mod
                },
                new EmbedFieldBuilder
                {
                    IsInline = true,
                    Name     = "Version:",
                    Value    = replayMetadata.Version
                },
                new EmbedFieldBuilder
                {
                    IsInline = true,
                    Name     = "Map:",
                    Value    = mapEmbed == null ? $"{replayMetadata.MapTitle}" : $"[{replayMetadata.MapTitle}]({mapEmbed.Url})"
                },
                new EmbedFieldBuilder
                {
                    IsInline = false,
                    Name     = "Duration:",
                    Value    = $"||{endTime - startTime}||"
                }
            };

            var playersByTeam = replayMetadata.Players.Values.GroupBy(x => x.Team).OrderBy(x => x.Key);
            var teamsCountStr = new List <string>();

            foreach (var kvp in playersByTeam)
            {
                if (kvp.Key == 0)
                {
                    teamsCountStr.AddRange(kvp.Select(_ => "1"));

                    fields.Add(new EmbedFieldBuilder
                    {
                        IsInline = true,
                        Name     = "No team:",
                        Value    = string.Join("\n", kvp.Select(x => $"{x.Name} [{x.FactionName}]"))
                    });
                }
                else
                {
                    teamsCountStr.Add(kvp.Count().ToString());
                    fields.Add(new EmbedFieldBuilder
                    {
                        IsInline = true,
                        Name     = $"Team {kvp.Key}",
                        Value    = string.Join("\n", kvp.Select(x => $"{x.Name} [{x.FactionName}]"))
                    });
                }
            }

            var    winners = replayMetadata.Players.Values.Where(x => x.Outcome == "Won").ToArray();
            string winnerString;

            if (winners.Length == 0)
            {
                winnerString = "Winner is unknown.";
            }
            else if (winners.Length == 1)
            {
                winnerString = $"Winner is {winners[0].Name}";
            }
            else
            {
                winnerString = $"Winners are {string.Join(", ", winners.Select(x => x.Name))}";
            }

            var embed = new EmbedBuilder
            {
                Title        = replayMetadata.FileName,
                ThumbnailUrl = mapEmbed?.Thumbnail?.Url,
                Url          = replayLink,
                Description  = $"This is a {string.Join("vs", teamsCountStr)} game. || {winnerString} ||",
                Footer       = new EmbedFooterBuilder
                {
                    Text = $"Played {replayMetadata.StartTimeUtc}"
                },
                Color  = mapEmbed?.Color ?? Color.Default,
                Fields = fields
            };

            return(embed.Build());
        }
Example #20
0
        public ReplayConnection(string replayFilename)
        {
            Filename      = replayFilename;
            FinalGameTick = ReplayMetadata.Read(replayFilename).GameInfo.FinalGameTick;

            // Parse replay data into a struct that can be fed to the game in chunks
            // to avoid issues with all immediate orders being resolved on the first tick.
            using (var rs = File.OpenRead(replayFilename))
            {
                var packets = new List <(int ClientId, byte[] Packet)>();
                var chunk   = new Chunk();
                while (rs.Position < rs.Length)
                {
                    var client = rs.ReadInt32();
                    if (client == ReplayMetadata.MetaStartMarker)
                    {
                        break;
                    }

                    var packetLen = rs.ReadInt32();
                    var packet    = rs.ReadBytes(packetLen);
                    var frame     = BitConverter.ToInt32(packet, 0);
                    packets.Add((client, packet));

                    if (frame != int.MaxValue && (!lastClientsFrame.ContainsKey(client) || frame > lastClientsFrame[client]))
                    {
                        lastClientsFrame[client] = frame;
                    }

                    if (packet.Length > 4 && (packet[4] == (byte)OrderType.Disconnect || packet[4] == (byte)OrderType.SyncHash))
                    {
                        continue;
                    }

                    if (frame == 0)
                    {
                        // Parse replay metadata from orders stream
                        var orders = packet.ToOrderList(null);
                        foreach (var o in orders)
                        {
                            if (o.OrderString == "StartGame")
                            {
                                IsValid = true;
                            }
                            else if (o.OrderString == "SyncInfo" && !IsValid)
                            {
                                LobbyInfo = Session.Deserialize(o.TargetString);
                            }
                        }
                    }
                    else
                    {
                        // Regular order - finalize the chunk
                        chunk.Frame   = frame;
                        chunk.Packets = packets.ToArray();
                        packets.Clear();
                        chunks.Enqueue(chunk);
                        chunk = new Chunk();

                        TickCount = Math.Max(TickCount, frame);
                    }
                }

                var lastClientToDisconnect = lastClientsFrame.MaxBy(kvp => kvp.Value).Key;

                // 2nd parse : replace all disconnect packets without frame with real
                // disconnect frame
                // NOTE: to modify/remove if a reconnect feature is set
                foreach (var tmpChunk in chunks)
                {
                    foreach (var tmpPacketPair in tmpChunk.Packets)
                    {
                        var client = tmpPacketPair.ClientId;

                        // Don't replace the final disconnection packet - we still want this to end the replay.
                        if (client == lastClientToDisconnect)
                        {
                            continue;
                        }

                        var packet = tmpPacketPair.Packet;
                        if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect)
                        {
                            var lastClientFrame = lastClientsFrame[client];
                            var lastFramePacket = BitConverter.GetBytes(lastClientFrame);
                            Array.Copy(lastFramePacket, packet, lastFramePacket.Length);
                        }
                    }
                }
            }

            ordersFrame = LobbyInfo.GlobalSettings.OrderLatency;
        }