예제 #1
0
        public void ChildCanBeOverriddenThenRemoved()
        {
            var baseYaml     = @"
^BaseA:
    MockString:
        AString: Base
^BaseB:
    Inherits: ^BaseA
    MockString:
        AString: Override
";
            var overrideYaml = @"
Test:
    Inherits: ^BaseB
    MockString:
        -AString:
";

            var result = MiniYaml.Merge(new[] { baseYaml, overrideYaml }.Select(s => MiniYaml.FromString(s, "")))
                         .First(n => n.Key == "Test").Value.Nodes;

            Assert.IsTrue(result.Any(n => n.Key == "MockString"), "Node should have the MockString child, but does not.");
            Assert.IsFalse(result.First(n => n.Key == "MockString").Value.Nodes.Any(n => n.Key == "AString"),
                           "MockString value should have been removed, but was not.");
        }
예제 #2
0
        public void InheritanceAndRemovalCanBeComposed()
        {
            var baseYaml     = @"
^BaseA:
	MockA2:
^BaseB:
	Inherits@a: ^BaseA
	MockB2:
";
            var extendedYaml = @"
Test:
	Inherits@b: ^BaseB
	-MockA2:
";
            var mapYaml      = @"
^BaseC:
	MockC2:
Test:
	Inherits@c: ^BaseC
";
            var result       = MiniYaml.Merge(new[] { baseYaml, extendedYaml, mapYaml }.Select(s => MiniYaml.FromString(s, "")))
                               .First(n => n.Key == "Test").Value.Nodes;

            Assert.IsFalse(result.Any(n => n.Key == "MockA2"), "Node should not have the MockA2 child, but does.");
            Assert.IsTrue(result.Any(n => n.Key == "MockB2"), "Node should have the MockB2 child, but does not.");
            Assert.IsTrue(result.Any(n => n.Key == "MockC2"), "Node should have the MockC2 child, but does not.");
        }
예제 #3
0
        public void TestSelfMerging()
        {
            var baseYaml = @"
Test:
	Merge: original
		Child: original
	Original:
Test:
	Merge: override
		Child: override
	Override:
";

            var result = MiniYaml.Merge(new[] { baseYaml }.Select(s => MiniYaml.FromString(s, "")));

            Assert.That(result.Count(n => n.Key == "Test"), Is.EqualTo(1), "Result should have exactly one Test node.");

            var testNodes = result.First(n => n.Key == "Test").Value.Nodes;

            Assert.That(testNodes.Select(n => n.Key), Is.EqualTo(new[] { "Merge", "Original", "Override" }), "Merged Test node has incorrect child nodes.");

            var mergeNode = testNodes.First(n => n.Key == "Merge").Value;

            Assert.That(mergeNode.Value, Is.EqualTo("override"), "Merge node has incorrect value.");
            Assert.That(mergeNode.Nodes[0].Value.Value, Is.EqualTo("override"), "Merge node Child value should be 'override', but is not");
        }
예제 #4
0
 public WeaponInfo(string name, MiniYaml content)
 {
     // Resolve any weapon-level yaml inheritance or removals
     // HACK: The "Defaults" sequence syntax prevents us from doing this generally during yaml parsing
     content.Nodes = MiniYaml.Merge(new[] { content.Nodes });
     FieldLoader.Load(this, content);
 }
예제 #5
0
        public void Run(ModData modData, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = modData;

            var failed = false;

            modData.SpriteSequenceLoader.OnMissingSpriteError = s => { Console.WriteLine("\t" + s); failed = true; };

            foreach (var t in modData.Manifest.TileSets)
            {
                var ts = new TileSet(modData.DefaultFileSystem, t);
                Console.WriteLine("Tileset: " + ts.Name);
                var sc    = new SpriteCache(modData.DefaultFileSystem, modData.SpriteLoaders, new SheetBuilder(SheetType.Indexed));
                var nodes = MiniYaml.Merge(modData.Manifest.Sequences.Select(s => MiniYaml.FromStream(modData.DefaultFileSystem.Open(s), s)));
                foreach (var n in nodes)
                {
                    modData.SpriteSequenceLoader.ParseSequences(modData, ts, sc, n);
                }
            }

            if (failed)
            {
                Environment.Exit(1);
            }
        }
예제 #6
0
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            var modData = Game.ModData = utility.ModData;

            var failed = false;

            modData.SpriteSequenceLoader.OnMissingSpriteError = s => { Console.WriteLine("\t" + s); failed = true; };

            foreach (var t in modData.Manifest.TileSets)
            {
                var ts = new TileSet(modData.DefaultFileSystem, t);
                Console.WriteLine("Tileset: " + ts.Name);
                var sc    = new SpriteCache(modData.DefaultFileSystem, modData.SpriteLoaders);
                var nodes = MiniYaml.Merge(modData.Manifest.Sequences.Select(s => MiniYaml.FromStream(modData.DefaultFileSystem.Open(s), s)));
                foreach (var n in nodes.Where(node => !node.Key.StartsWith(ActorInfo.AbstractActorPrefix, StringComparison.Ordinal)))
                {
                    modData.SpriteSequenceLoader.ParseSequences(modData, ts, sc, n);
                }
            }

            if (failed)
            {
                Environment.Exit(1);
            }
        }
예제 #7
0
        public static void Initialize(ModData modData)
        {
            if (Initialized)
            {
                return;
            }

            Deinitialize();

            fileSystem   = modData.DefaultFileSystem;
            collections  = new Dictionary <string, Collection>();
            cachedSheets = new Dictionary <string, Sheet>();

            cachedSheets2d = new Dictionary <string, SheetCache>();
            cachedSprites  = new Dictionary <string, Dictionary <string, Sprite> >();

            var chrome = MiniYaml.Merge(modData.Manifest.Chrome
                                        .Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)));

            foreach (var c in chrome)
            {
                LoadCollection(c.Key, c.Value);
            }
            Initialized = true;
        }
예제 #8
0
        public IReadOnlyDictionary <string, ISpriteSequence> ParseSequences(ModData modData, TileSet tileSet, SpriteCache cache, MiniYamlNode node)
        {
            var sequences = new Dictionary <string, ISpriteSequence>();
            var nodes     = node.Value.ToDictionary();

            MiniYaml defaults;

            if (nodes.TryGetValue("Defaults", out defaults))
            {
                nodes.Remove("Defaults");
                foreach (var n in nodes)
                {
                    n.Value.Nodes = MiniYaml.Merge(new[] { defaults.Nodes, n.Value.Nodes });
                    n.Value.Value = n.Value.Value ?? defaults.Value;
                }
            }

            foreach (var kvp in nodes)
            {
                using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
                {
                    try
                    {
                        sequences.Add(kvp.Key, CreateSequence(modData, tileSet, cache, node.Key, kvp.Key, kvp.Value));
                    }
                    catch (FileNotFoundException ex)
                    {
                        // Eat the FileNotFound exceptions from missing sprites
                        OnMissingSpriteError(ex.Message);
                    }
                }
            }

            return(new ReadOnlyDictionary <string, ISpriteSequence>(sequences));
        }
예제 #9
0
        public static void Initialize(ModData modData)
        {
            Deinitialize();

            // Load higher resolution images if available on HiDPI displays
            if (Game.Renderer != null)
            {
                dpiScale = Game.Renderer.WindowScale;
            }

            fileSystem             = modData.DefaultFileSystem;
            collections            = new Dictionary <string, Collection>();
            cachedSheets           = new Dictionary <string, Pair <Sheet, int> >();
            cachedSprites          = new Dictionary <string, Dictionary <string, Sprite> >();
            cachedPanelSprites     = new Dictionary <string, Sprite[]>();
            cachedCollectionSheets = new Dictionary <Collection, Pair <Sheet, int> >();

            Collections = new ReadOnlyDictionary <string, Collection>(collections);

            var chrome = MiniYaml.Merge(modData.Manifest.Chrome
                                        .Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)));

            foreach (var c in chrome)
            {
                if (!c.Key.StartsWith("^", StringComparison.Ordinal))
                {
                    LoadCollection(c.Key, c.Value);
                }
            }
        }
예제 #10
0
        public void MergeYamlA()
        {
            var a = MiniYaml.FromString(mixedMergeA, "mixedMergeA");
            var b = MiniYaml.FromString(mixedMergeB, "mixedMergeB");

            // Merge order should not matter
            // Note: All the Merge* variants are different plumbing over the same
            // Internal logic.  Testing only Merge is sufficient.
            TestMixedMerge(MiniYaml.Merge(a, b).First().Value);
            TestMixedMerge(MiniYaml.Merge(b, a).First().Value);
        }
예제 #11
0
        public static void Initialize(ModData modData)
        {
            data = new Dictionary <string, string>();
            var metrics = MiniYaml.Merge(modData.Manifest.ChromeMetrics.Select(
                                             y => MiniYaml.FromStream(modData.DefaultFileSystem.Open(y), y)));

            foreach (var m in metrics)
            {
                foreach (var n in m.Value.Nodes)
                {
                    data[n.Key] = n.Value.Value;
                }
            }
        }
예제 #12
0
        public IReadOnlyDictionary <string, ISpriteSequence> ParseSequences(ModData modData, TileSet tileSet, SpriteCache cache, MiniYamlNode node)
        {
            var sequences = new Dictionary <string, ISpriteSequence>();
            var nodes     = node.Value.ToDictionary();

            MiniYaml defaults;

            if (nodes.TryGetValue("Defaults", out defaults))
            {
                nodes.Remove("Defaults");
                nodes = nodes.ToDictionary(kv => kv.Key, kv => MiniYaml.Merge(kv.Value, defaults));

                // Merge 'Defaults' animation image value. An example follows.
                //
                // - Before -
                // stand:
                //  Facings: 8
                //
                // - After -
                // stand: e1
                //  Facings: 8
                foreach (var n in nodes)
                {
                    n.Value.Value = n.Value.Value ?? defaults.Value;
                }
            }

            foreach (var kvp in nodes)
            {
                using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
                {
                    try
                    {
                        sequences.Add(kvp.Key, CreateSequence(modData, tileSet, cache, node.Key, kvp.Key, kvp.Value));
                    }
                    catch (FileNotFoundException ex)
                    {
                        // Eat the FileNotFound exceptions from missing sprites
                        OnMissingSpriteError(ex.Message);
                    }
                }
            }

            return(new ReadOnlyDictionary <string, ISpriteSequence>(sequences));
        }
예제 #13
0
        void Run(Action <string> emitError, ModData modData, Ruleset rules)
        {
            var fileSystem   = modData.DefaultFileSystem;
            var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)));
            var nodesDict    = new MiniYaml(null, sequenceYaml).ToDictionary();

            // Avoid using CursorProvider as it attempts to load palettes from the file system.
            var cursors = new List <string>();

            foreach (var s in nodesDict["Cursors"].Nodes)
            {
                foreach (var sequence in s.Value.Nodes)
                {
                    cursors.Add(sequence.Key);
                }
            }

            foreach (var actorInfo in rules.Actors)
            {
                foreach (var traitInfo in actorInfo.Value.TraitInfos <TraitInfo>())
                {
                    var fields = traitInfo.GetType().GetFields();
                    foreach (var field in fields)
                    {
                        var cursorReference = field.GetCustomAttributes <CursorReferenceAttribute>(true).FirstOrDefault();
                        if (cursorReference == null)
                        {
                            continue;
                        }

                        var cursor = LintExts.GetFieldValues(traitInfo, field, emitError, cursorReference.DictionaryReference).FirstOrDefault();
                        if (string.IsNullOrEmpty(cursor))
                        {
                            continue;
                        }

                        if (!cursors.Contains(cursor))
                        {
                            emitError("Undefined cursor {0} for actor {1} with trait {2}.".F(cursor, actorInfo.Value.Name, traitInfo));
                        }
                    }
                }
            }
        }
예제 #14
0
        public void ChildCanBeRemovedAfterMultipleInheritance()
        {
            var baseYaml     = @"
^BaseA:
	MockA2:
Test:
	Inherits: ^BaseA
	MockA2:
";
            var overrideYaml = @"
Test:
	-MockA2
";

            var result = MiniYaml.Merge(new[] { baseYaml, overrideYaml }.Select(s => MiniYaml.FromString(s, "")))
                         .First(n => n.Key == "Test").Value.Nodes;

            Assert.IsFalse(result.Any(n => n.Key == "MockA2"), "Node should not have the MockA2 child, but does.");
        }
예제 #15
0
        /// <summary>
        /// 解析序列
        /// </summary>
        /// <param name="modData"></param>
        /// <param name="tileSet"></param>
        /// <param name="cache"></param>
        /// <param name=""></param>
        /// <returns></returns>
        public IReadOnlyDictionary <string, ISpriteSequence> ParseSequences(ModData modData, TileSet tileSet, SpriteCache cache, MiniYamlNode node)
        {
            var sequences = new Dictionary <string, ISpriteSequence>();
            var nodes     = node.Value.ToDictionary();

            MiniYaml defaults;

            try
            {
                if (nodes.TryGetValue("Defaults", out defaults))
                {
                    nodes.Remove("Defaults");

                    foreach (var n in nodes)
                    {
                        n.Value.Nodes = MiniYaml.Merge(new[] { defaults.Nodes, n.Value.Nodes });
                        n.Value.Value = n.Value.Value ?? defaults.Value;
                    }
                }
            }
            catch (Exception e)
            {
                throw new InvalidDataException("Error occurred while parsing {0} ".F(node.Key), e);
            }

            foreach (var kvp in nodes)
            {
                using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
                {
                    try
                    {
                        //Console.WriteLine("Parse sequence:node key:" + node.Key + "   animation:" + kvp.Key + " count:"+kvp.Value.Nodes.Count);
                        sequences.Add(kvp.Key, CreateSequence(modData, tileSet, cache, node.Key, kvp.Key, kvp.Value));
                    }
                    catch (FileNotFoundException ex)
                    {
                        OnMissingSpriteError(ex.Message);
                    }
                }
            }
            return(new ReadOnlyDictionary <string, ISpriteSequence>(sequences));
        }
예제 #16
0
        public IReadOnlyDictionary <string, ISpriteSequence> ParseSequences(ModData modData, string tileSet, SpriteCache cache, MiniYamlNode node)
        {
            var sequences = new Dictionary <string, ISpriteSequence>();
            var nodes     = node.Value.ToDictionary();

            try
            {
                if (nodes.TryGetValue("Defaults", out var defaults))
                {
                    nodes.Remove("Defaults");
                    foreach (var n in nodes)
                    {
                        n.Value.Nodes = MiniYaml.Merge(new[] { defaults.Nodes, n.Value.Nodes });
                        n.Value.Value = n.Value.Value ?? defaults.Value;
                    }
                }
            }
            catch (Exception e)
            {
                throw new InvalidDataException($"Error occurred while parsing {node.Key}", e);
            }

            foreach (var kvp in nodes)
            {
                using (new Support.PerfTimer($"new Sequence(\"{node.Key}\")", 20))
                {
                    try
                    {
                        sequences.Add(kvp.Key, CreateSequence(modData, tileSet, cache, node.Key, kvp.Key, kvp.Value));
                    }
                    catch (FileNotFoundException ex)
                    {
                        // Defer exception until something tries to access the sequence
                        // This allows the asset installer and OpenRA.Utility to load the game without having the actor assets
                        sequences.Add(kvp.Key, new FileNotFoundSequence(ex));
                    }
                }
            }

            return(new ReadOnlyDictionary <string, ISpriteSequence>(sequences));
        }
예제 #17
0
        public CursorProvider(ModData modData)
        {
            var fileSystem   = modData.DefaultFileSystem;
            var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select(
                                                  s => MiniYaml.FromStream(fileSystem.Open(s), s)));

            var shadowIndex = new int[] { };

            var nodesDict = new MiniYaml(null, sequenceYaml).ToDictionary();

            if (nodesDict.ContainsKey("ShadowIndex"))
            {
                Array.Resize(ref shadowIndex, shadowIndex.Length + 1);
                Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value,
                                              out shadowIndex[shadowIndex.Length - 1]);
            }

            var palettes = new Dictionary <string, ImmutablePalette>();

            foreach (var p in nodesDict["Palettes"].Nodes)
            {
                palettes.Add(p.Key, new ImmutablePalette(fileSystem.Open(p.Value.Value), shadowIndex));
            }

            Palettes = palettes.AsReadOnly();

            var frameCache = new FrameCache(fileSystem, modData.SpriteLoaders);
            var cursors    = new Dictionary <string, CursorSequence>();

            foreach (var s in nodesDict["Cursors"].Nodes)
            {
                foreach (var sequence in s.Value.Nodes)
                {
                    cursors.Add(sequence.Key, new CursorSequence(frameCache, sequence.Key, s.Key, s.Value.Value, sequence.Value));
                }
            }

            Cursors = cursors.AsReadOnly();
        }
예제 #18
0
        public CursorProvider(ModData modData)
        {
            var fileSystem   = modData.DefaultFileSystem;
            var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select(
                                                  s => MiniYaml.FromStream(fileSystem.Open(s), s)));

            var nodesDict = new MiniYaml(null, sequenceYaml).ToDictionary();

            // Overwrite previous definitions if there are duplicates
            var pals = new Dictionary <string, IProvidesCursorPaletteInfo>();

            foreach (var p in modData.DefaultRules.Actors["world"].TraitInfos <IProvidesCursorPaletteInfo>())
            {
                if (p.Palette != null)
                {
                    pals[p.Palette] = p;
                }
            }

            Palettes = nodesDict["Cursors"].Nodes.Select(n => n.Value.Value)
                       .Where(p => p != null)
                       .Distinct()
                       .ToDictionary(p => p, p => pals[p].ReadPalette(modData.DefaultFileSystem))
                       .AsReadOnly();

            var frameCache = new FrameCache(fileSystem, modData.SpriteLoaders);
            var cursors    = new Dictionary <string, CursorSequence>();

            foreach (var s in nodesDict["Cursors"].Nodes)
            {
                foreach (var sequence in s.Value.Nodes)
                {
                    cursors.Add(sequence.Key, new CursorSequence(frameCache, sequence.Key, s.Key, s.Value.Value, sequence.Value));
                }
            }

            Cursors = cursors.AsReadOnly();
        }
예제 #19
0
        public void ChildCanBeRemovedAndLaterOverridden()
        {
            var baseYaml     = @"
^BaseA:
    MockString:
        AString: Base
Test:
    Inherits: ^BaseA
    -MockString:
";
            var overrideYaml = @"
Test:
    MockString:
        AString: Override
";

            var result = MiniYaml.Merge(new[] { baseYaml, overrideYaml }.Select(s => MiniYaml.FromString(s, "")))
                         .First(n => n.Key == "Test").Value.Nodes;

            Assert.IsTrue(result.Any(n => n.Key == "MockString"), "Node should have the MockString child, but does not.");
            Assert.IsTrue(result.First(n => n.Key == "MockString").Value.ToDictionary()["AString"].Value == "Override",
                          "MockString value has not been set with the correct override value for AString.");
        }
예제 #20
0
        public static void Initialize(ModData modData)
        {
            Deinitialize();

            fileSystem = modData.DefaultFileSystem;

            collections = new Dictionary <string, D2Collection>();
            Collections = new ReadOnlyDictionary <string, D2Collection>(collections);

            cachedCollectionSheets = new Dictionary <D2Collection, Sheet>();
            cachedSheets           = new Dictionary <string, Sheet>();
            cachedSprites          = new Dictionary <string, Sprite>();

            var chrome = MiniYaml.Merge(modData.Manifest.Chrome
                                        .Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)));

            foreach (var c in chrome)
            {
                if (!c.Key.StartsWith("^", StringComparison.Ordinal))
                {
                    LoadCollection(c.Key, c.Value);
                }
            }
        }
예제 #21
0
        public MissionBrowserLogic(Widget widget, ModData modData, World world, Action onStart, Action onExit)
        {
            this.modData          = modData;
            this.onStart          = onStart;
            Game.BeforeGameStart += OnGameStart;

            missionList = widget.Get <ScrollPanelWidget>("MISSION_LIST");

            headerTemplate = widget.Get <ScrollItemWidget>("HEADER");
            template       = widget.Get <ScrollItemWidget>("TEMPLATE");

            var title = widget.GetOrNull <LabelWidget>("MISSIONBROWSER_TITLE");

            if (title != null)
            {
                title.GetText = () => playingVideo != PlayingVideo.None ? selectedMap.Title : title.Text;
            }

            widget.Get("MISSION_INFO").IsVisible = () => selectedMap != null;

            var previewWidget = widget.Get <MapPreviewWidget>("MISSION_PREVIEW");

            previewWidget.Preview   = () => selectedMap;
            previewWidget.IsVisible = () => playingVideo == PlayingVideo.None;

            videoPlayer = widget.Get <VideoPlayerWidget>("MISSION_VIDEO");
            widget.Get("MISSION_BIN").IsVisible = () => playingVideo != PlayingVideo.None;
            fullscreenVideoPlayer = Ui.LoadWidget <BackgroundWidget>("FULLSCREEN_PLAYER", Ui.Root, new WidgetArgs {
                { "world", world }
            });

            descriptionPanel = widget.Get <ScrollPanelWidget>("MISSION_DESCRIPTION_PANEL");

            description     = descriptionPanel.Get <LabelWidget>("MISSION_DESCRIPTION");
            descriptionFont = Game.Renderer.Fonts[description.Font];

            difficultyButton = widget.Get <DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");
            gameSpeedButton  = widget.GetOrNull <DropDownButtonWidget>("GAMESPEED_DROPDOWNBUTTON");

            startBriefingVideoButton          = widget.Get <ButtonWidget>("START_BRIEFING_VIDEO_BUTTON");
            stopBriefingVideoButton           = widget.Get <ButtonWidget>("STOP_BRIEFING_VIDEO_BUTTON");
            stopBriefingVideoButton.IsVisible = () => playingVideo == PlayingVideo.Briefing;
            stopBriefingVideoButton.OnClick   = () => StopVideo(videoPlayer);

            startInfoVideoButton          = widget.Get <ButtonWidget>("START_INFO_VIDEO_BUTTON");
            stopInfoVideoButton           = widget.Get <ButtonWidget>("STOP_INFO_VIDEO_BUTTON");
            stopInfoVideoButton.IsVisible = () => playingVideo == PlayingVideo.Info;
            stopInfoVideoButton.OnClick   = () => StopVideo(videoPlayer);

            var allPreviews = new List <MapPreview>();

            missionList.RemoveChildren();

            // Add a group for each campaign
            if (modData.Manifest.Missions.Any())
            {
                var yaml = MiniYaml.Merge(modData.Manifest.Missions.Select(
                                              m => MiniYaml.FromStream(modData.DefaultFileSystem.Open(m), m)));

                foreach (var kv in yaml)
                {
                    var missionMapPaths = kv.Value.Nodes.Select(n => n.Key).ToList();

                    var previews = modData.MapCache
                                   .Where(p => p.Class == MapClassification.System && p.Status == MapStatus.Available)
                                   .Select(p => new
                    {
                        Preview = p,
                        Index   = missionMapPaths.IndexOf(Path.GetFileName(p.Package.Name))
                    })
                                   .Where(x => x.Index != -1)
                                   .OrderBy(x => x.Index)
                                   .Select(x => x.Preview);

                    if (previews.Any())
                    {
                        CreateMissionGroup(kv.Key, previews);
                        allPreviews.AddRange(previews);
                    }
                }
            }

            // Add an additional group for loose missions
            var loosePreviews = modData.MapCache
                                .Where(p => p.Status == MapStatus.Available && p.Visibility.HasFlag(MapVisibility.MissionSelector) && !allPreviews.Any(a => a.Uid == p.Uid));

            if (loosePreviews.Any())
            {
                CreateMissionGroup("Missions", loosePreviews);
                allPreviews.AddRange(loosePreviews);
            }

            if (allPreviews.Any())
            {
                SelectMap(allPreviews.First());
            }

            // Preload map preview to reduce jank
            new Thread(() =>
            {
                foreach (var p in allPreviews)
                {
                    p.GetMinimap();
                }
            }).Start();

            var startButton = widget.Get <ButtonWidget>("STARTGAME_BUTTON");

            startButton.OnClick    = StartMissionClicked;
            startButton.IsDisabled = () => selectedMap == null;

            widget.Get <ButtonWidget>("BACK_BUTTON").OnClick = () =>
            {
                StopVideo(videoPlayer);
                Game.Disconnect();
                Ui.CloseWindow();
                onExit();
            };
        }
예제 #22
0
        public void Run(Action <string> emitError, Action <string> emitWarning, Map map)
        {
            if (map != null && !map.SequenceDefinitions.Any())
            {
                return;
            }

            this.emitError = emitError;

            var sequenceSource = map != null ? map.SequenceDefinitions : new List <MiniYamlNode>();
            var partial        = Game.ModData.Manifest.Sequences
                                 .Select(MiniYaml.FromFile)
                                 .Aggregate(MiniYaml.MergePartial);

            sequenceDefinitions = MiniYaml.Merge(sequenceSource, partial);

            var rules             = map == null ? Game.ModData.DefaultRules : map.Rules;
            var factions          = rules.Actors["world"].TraitInfos <FactionInfo>().Select(f => f.InternalName).ToArray();
            var sequenceProviders = map == null ? rules.Sequences.Values : new[] { rules.Sequences[map.Tileset] };

            foreach (var actorInfo in rules.Actors)
            {
                foreach (var renderInfo in actorInfo.Value.TraitInfos <RenderSpritesInfo>())
                {
                    foreach (var faction in factions)
                    {
                        foreach (var sequenceProvider in sequenceProviders)
                        {
                            var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, faction);
                            if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^"))
                            {
                                emitError("Sprite image {0} from actor {1} using faction {2} has no sequence definition."
                                          .F(image, actorInfo.Value.Name, faction));
                            }
                        }
                    }
                }

                foreach (var traitInfo in actorInfo.Value.TraitInfos <ITraitInfo>())
                {
                    var fields = traitInfo.GetType().GetFields();
                    foreach (var field in fields)
                    {
                        if (field.HasAttribute <SequenceReferenceAttribute>())
                        {
                            var sequences = LintExts.GetFieldValues(traitInfo, field, emitError);
                            foreach (var sequence in sequences)
                            {
                                if (string.IsNullOrEmpty(sequence))
                                {
                                    continue;
                                }

                                var renderInfo = actorInfo.Value.TraitInfos <RenderSpritesInfo>().FirstOrDefault();
                                if (renderInfo == null)
                                {
                                    continue;
                                }

                                foreach (var faction in factions)
                                {
                                    var sequenceReference = field.GetCustomAttributes <SequenceReferenceAttribute>(true).FirstOrDefault();
                                    if (sequenceReference != null && !string.IsNullOrEmpty(sequenceReference.ImageReference))
                                    {
                                        var imageField = fields.FirstOrDefault(f => f.Name == sequenceReference.ImageReference);
                                        if (imageField != null)
                                        {
                                            foreach (var imageOverride in LintExts.GetFieldValues(traitInfo, imageField, emitError))
                                            {
                                                if (!string.IsNullOrEmpty(imageOverride) && sequenceDefinitions.All(s => s.Key != imageOverride.ToLowerInvariant()))
                                                {
                                                    emitError("Custom sprite image {0} from actor {1} has no sequence definition.".F(imageOverride, actorInfo.Value.Name));
                                                }
                                                else
                                                {
                                                    CheckDefintions(imageOverride, sequenceReference, actorInfo, sequence, faction, field, traitInfo);
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        foreach (var sequenceProvider in sequenceProviders)
                                        {
                                            var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, faction);
                                            CheckDefintions(image, sequenceReference, actorInfo, sequence, faction, field, traitInfo);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                foreach (var weaponInfo in rules.Weapons)
                {
                    var projectileInfo = weaponInfo.Value.Projectile;
                    if (projectileInfo == null)
                    {
                        continue;
                    }

                    var fields = projectileInfo.GetType().GetFields();
                    foreach (var field in fields)
                    {
                        if (field.HasAttribute <SequenceReferenceAttribute>())
                        {
                            var sequences = LintExts.GetFieldValues(projectileInfo, field, emitError);
                            foreach (var sequence in sequences)
                            {
                                if (string.IsNullOrEmpty(sequence))
                                {
                                    continue;
                                }

                                var sequenceReference = field.GetCustomAttributes <SequenceReferenceAttribute>(true).FirstOrDefault();
                                if (sequenceReference != null && !string.IsNullOrEmpty(sequenceReference.ImageReference))
                                {
                                    var imageField = fields.FirstOrDefault(f => f.Name == sequenceReference.ImageReference);
                                    if (imageField != null)
                                    {
                                        foreach (var imageOverride in LintExts.GetFieldValues(projectileInfo, imageField, emitError))
                                        {
                                            if (!string.IsNullOrEmpty(imageOverride))
                                            {
                                                var definitions = sequenceDefinitions.FirstOrDefault(n => n.Key == imageOverride.ToLowerInvariant());
                                                if (definitions == null)
                                                {
                                                    emitError("Can't find sequence definition for projectile image {0} at weapon {1}.".F(imageOverride, weaponInfo.Key));
                                                }
                                                else if (!definitions.Value.Nodes.Any(n => n.Key == sequence))
                                                {
                                                    emitError("Projectile sprite image {0} from weapon {1} does not define sequence {2} from field {3} of {4}"
                                                              .F(imageOverride, weaponInfo.Key, sequence, field.Name, projectileInfo));
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }