예제 #1
0
        public static GameInformation Deserialize(string data)
        {
            try
            {
                var info = new GameInformation();

                var nodes = MiniYaml.FromString(data);
                foreach (var node in nodes)
                {
                    var keyParts = node.Key.Split('@');

                    switch (keyParts[0])
                    {
                    case "Root":
                        FieldLoader.Load(info, node.Value);
                        break;

                    case "Player":
                        info.Players.Add(FieldLoader.Load <Player>(node.Value));
                        break;
                    }
                }

                return(info);
            }
            catch (InvalidOperationException)
            {
                Log.Write("debug", "GameInformation deserialized invalid MiniYaml:\n{0}".F(data));
                throw;
            }
        }
예제 #2
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);
                    }

                    if (queryFailed != null)
                    {
                        queryFailed();
                    }

                    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);
                    }
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Can't parse remote map search data:\n{0}", data);
                    Log.Write("debug", "Exception: {0}", e);
                    if (queryFailed != null)
                    {
                        queryFailed();
                    }
                }
            };

            new Download(url, _ => { }, onInfoComplete);
        }
예제 #3
0
파일: MapCache.cs 프로젝트: lujiawen/OpenRA
        public void QueryRemoteMapDetails(string repositoryUrl, IEnumerable <string> uids, Action <MapPreview> mapDetailsReceived = null, Action <MapPreview> mapQueryFailed = null)
        {
            var queryUids = uids.Distinct()
                            .Where(uid => uid != null)
                            .Select(uid => previews[uid])
                            .Where(p => p.Status == MapStatus.Unavailable)
                            .Select(p => p.Uid)
                            .ToList();

            foreach (var uid in queryUids)
            {
                previews[uid].UpdateRemoteSearch(MapStatus.Searching, null);
            }

            Task.Run(async() =>
            {
                var client = HttpClientFactory.Create();

                // Limit each query to 50 maps at a time to avoid request size limits
                for (var i = 0; i < queryUids.Count; i += 50)
                {
                    var batchUids = queryUids.Skip(i).Take(50).ToList();
                    var url       = repositoryUrl + "hash/" + string.Join(",", batchUids) + "/yaml";
                    try
                    {
                        var httpResponseMessage = await client.GetAsync(url);
                        var result = await httpResponseMessage.Content.ReadAsStringAsync();

                        var yaml = MiniYaml.FromString(result);
                        foreach (var kv in yaml)
                        {
                            previews[kv.Key].UpdateRemoteSearch(MapStatus.DownloadAvailable, kv.Value, mapDetailsReceived);
                        }

                        foreach (var uid in batchUids)
                        {
                            var p = previews[uid];
                            if (p.Status != MapStatus.DownloadAvailable)
                            {
                                p.UpdateRemoteSearch(MapStatus.Unavailable, null);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Remote map query failed with error: {0}", e);
                        Log.Write("debug", "URL was: {0}", url);

                        foreach (var uid in batchUids)
                        {
                            var p = previews[uid];
                            p.UpdateRemoteSearch(MapStatus.Unavailable, null);
                            mapQueryFailed?.Invoke(p);
                        }
                    }
                }
            });
        }
예제 #4
0
파일: MapCache.cs 프로젝트: dnqbob/OpenRA
        public void QueryRemoteMapDetails(string repositoryUrl, IEnumerable <string> uids, Action <MapPreview> mapDetailsReceived = null, Action queryFailed = null)
        {
            var maps = uids.Distinct()
                       .Where(uid => uid != null)
                       .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";

            Task.Run(async() =>
            {
                try
                {
                    var client = HttpClientFactory.Create();

                    var httpResponseMessage = await client.GetAsync(url);
                    var result = await httpResponseMessage.Content.ReadAsStringAsync();

                    var yaml = MiniYaml.FromString(result);
                    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", "Remote map query failed with error: {0}", e);
                    Log.Write("debug", "URL was: {0}", url);

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

                    queryFailed?.Invoke();
                }
            });
        }
예제 #5
0
        public void RefreshPlayerData(Action onComplete = null)
        {
            if (State != LinkState.Unlinked && State != LinkState.Linked && State != LinkState.ConnectionFailed)
            {
                return;
            }

            Action <DownloadDataCompletedEventArgs> onQueryComplete = i =>
            {
                try
                {
                    if (i.Error != null)
                    {
                        innerState = LinkState.ConnectionFailed;
                        return;
                    }

                    var yaml = MiniYaml.FromString(Encoding.UTF8.GetString(i.Result)).First();
                    if (yaml.Key == "Player")
                    {
                        innerData = FieldLoader.Load <PlayerProfile>(yaml.Value);
                        if (innerData.KeyRevoked)
                        {
                            Log.Write("debug", "Revoking key with fingerprint {0}", Fingerprint);
                            DeleteKeypair();
                        }
                        else
                        {
                            innerState = LinkState.Linked;
                        }
                    }
                    else
                    {
                        innerState = LinkState.Unlinked;
                    }
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed to parse player data result with exception: {0}", e);
                    innerState = LinkState.ConnectionFailed;
                }
                finally
                {
                    if (onComplete != null)
                    {
                        onComplete();
                    }
                }
            };

            innerState = LinkState.CheckingLink;
            new Download(playerDatabase.Profile + Fingerprint, _ => { }, onQueryComplete);
        }
예제 #6
0
        public void QueryRemoteMapDetails(IEnumerable <string> uids)
        {
            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 = Game.Settings.Game.MapRepository + "hash/" + string.Join(",", maps.Keys) + "/yaml";

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

                    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);
                    }
                }
                catch
                {
                    Log.Write("debug", "Can't parse remote map search data:\n{0}", data);
                }
            };

            new Download(url, _ => { }, onInfoComplete);
        }
예제 #7
0
        public void RefreshPlayerData(Action onComplete = null)
        {
            if (State != LinkState.Unlinked && State != LinkState.Linked && State != LinkState.ConnectionFailed)
            {
                return;
            }

            Task.Run(async() =>
            {
                try
                {
                    var client = HttpClientFactory.Create();

                    var httpResponseMessage = await client.GetAsync(playerDatabase.Profile + Fingerprint);
                    var result = await httpResponseMessage.Content.ReadAsStringAsync();

                    var yaml = MiniYaml.FromString(result).First();
                    if (yaml.Key == "Player")
                    {
                        innerData = FieldLoader.Load <PlayerProfile>(yaml.Value);
                        if (innerData.KeyRevoked)
                        {
                            Log.Write("debug", "Revoking key with fingerprint {0}", Fingerprint);
                            DeleteKeypair();
                        }
                        else
                        {
                            innerState = LinkState.Linked;
                        }
                    }
                    else
                    {
                        innerState = LinkState.Unlinked;
                    }
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed to parse player data result with exception: {0}", e);
                    innerState = LinkState.ConnectionFailed;
                }
                finally
                {
                    onComplete?.Invoke();
                }
            });

            innerState = LinkState.CheckingLink;
        }
예제 #8
0
        public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action <MapPreview> parseMetadata = null)
        {
            var newData = innerData.Clone();

            newData.Status = status;
            newData.Class  = MapClassification.Remote;

            if (status == MapStatus.DownloadAvailable)
            {
                try
                {
                    var r = FieldLoader.Load <RemoteMapData>(yaml);

                    // Map download has been disabled server side
                    if (!r.downloading)
                    {
                        newData.Status = MapStatus.Unavailable;
                        return;
                    }

                    newData.Title       = r.title;
                    newData.Categories  = r.categories;
                    newData.Author      = r.author;
                    newData.PlayerCount = r.players;
                    newData.Bounds      = r.bounds;
                    newData.TileSet     = r.tileset;
                    newData.MapFormat   = r.mapformat;

                    var spawns = new CPos[r.spawnpoints.Length / 2];
                    for (var j = 0; j < r.spawnpoints.Length; j += 2)
                    {
                        spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]);
                    }
                    newData.SpawnPoints = spawns;
                    newData.GridType    = r.map_grid_type;
                    try
                    {
                        newData.Preview = new Png(new MemoryStream(Convert.FromBase64String(r.minimap)));
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed parsing mapserver minimap response: {0}", e);
                        newData.Preview = null;
                    }

                    var playersString = Encoding.UTF8.GetString(Convert.FromBase64String(r.players_block));
                    newData.Players = new MapPlayers(MiniYaml.FromString(playersString));

                    var rulesString = Encoding.UTF8.GetString(Convert.FromBase64String(r.rules));
                    var rulesYaml   = new MiniYaml("", MiniYaml.FromString(rulesString)).ToDictionary();
                    newData.SetCustomRules(modData, this, rulesYaml);
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed parsing mapserver response: {0}", e);
                }

                // Commit updated data before running the callbacks
                innerData = newData;

                if (innerData.Preview != null)
                {
                    cache.CacheMinimap(this);
                }

                parseMetadata?.Invoke(this);
            }

            // Update the status and class unconditionally
            innerData = newData;
        }
예제 #9
0
        public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action <MapPreview> parseMetadata = null)
        {
            var newData = innerData.Clone();

            newData.Status = status;
            newData.Class  = MapClassification.Remote;

            if (status == MapStatus.DownloadAvailable)
            {
                try
                {
                    var r = FieldLoader.Load <RemoteMapData>(yaml);

                    // Map download has been disabled server side
                    if (!r.downloading)
                    {
                        newData.Status = MapStatus.Unavailable;
                        return;
                    }

                    newData.Title       = r.title;
                    newData.Categories  = r.categories;
                    newData.Author      = r.author;
                    newData.PlayerCount = r.players;
                    newData.Bounds      = r.bounds;
                    newData.TileSet     = r.tileset;

                    var spawns = new CPos[r.spawnpoints.Length / 2];
                    for (var j = 0; j < r.spawnpoints.Length; j += 2)
                    {
                        spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]);
                    }
                    newData.SpawnPoints = spawns;
                    newData.GridType    = r.map_grid_type;
                    try
                    {
                        newData.Preview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap)));
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed parsing mapserver minimap response: {0}", e);
                        newData.Preview = null;
                    }

                    var playersString = Encoding.UTF8.GetString(Convert.FromBase64String(r.players_block));
                    newData.Players = new MapPlayers(MiniYaml.FromString(playersString));

                    newData.SetRulesetGenerator(modData, () =>
                    {
                        var rulesString              = Encoding.UTF8.GetString(Convert.FromBase64String(r.rules));
                        var rulesYaml                = new MiniYaml("", MiniYaml.FromString(rulesString)).ToDictionary();
                        var ruleDefinitions          = LoadRuleSection(rulesYaml, "Rules");
                        var weaponDefinitions        = LoadRuleSection(rulesYaml, "Weapons");
                        var voiceDefinitions         = LoadRuleSection(rulesYaml, "Voices");
                        var musicDefinitions         = LoadRuleSection(rulesYaml, "Music");
                        var notificationDefinitions  = LoadRuleSection(rulesYaml, "Notifications");
                        var sequenceDefinitions      = LoadRuleSection(rulesYaml, "Sequences");
                        var modelSequenceDefinitions = LoadRuleSection(rulesYaml, "ModelSequences");
                        var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
                                                 voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions);
                        var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
                                                                       weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
                        return(Pair.New(rules, flagged));
                    });
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed parsing mapserver response: {0}", e);
                }

                // Commit updated data before running the callbacks
                innerData = newData;

                if (innerData.Preview != null)
                {
                    cache.CacheMinimap(this);
                }

                if (parseMetadata != null)
                {
                    parseMetadata(this);
                }
            }

            // Update the status and class unconditionally
            innerData = newData;
        }