Example #1
0
        public IngameMenuLogic(Widget widget, ModData modData, World world, Action onExit, WorldRenderer worldRenderer,
                               IngameInfoPanel activePanel, Dictionary <string, MiniYaml> logicArgs)
        {
            this.modData       = modData;
            this.world         = world;
            this.worldRenderer = worldRenderer;
            this.onExit        = onExit;

            var buttonHandlers = new Dictionary <string, Action>
            {
                { "ABORT_MISSION", CreateAbortMissionButton },
                { "RESTART", CreateRestartButton },
                { "SURRENDER", CreateSurrenderButton },
                { "LOAD_GAME", CreateLoadGameButton },
                { "SAVE_GAME", CreateSaveGameButton },
                { "MUSIC", CreateMusicButton },
                { "SETTINGS", CreateSettingsButton },
                { "RESUME", CreateResumeButton },
                { "SAVE_MAP", CreateSaveMapButton },
                { "EXIT_EDITOR", CreateExitEditorButton }
            };

            isSinglePlayer = !world.LobbyInfo.GlobalSettings.Dedicated && world.LobbyInfo.NonBotClients.Count() == 1;

            menu = widget.Get("INGAME_MENU");
            mpe  = world.WorldActor.TraitOrDefault <MenuPaletteEffect>();
            if (mpe != null)
            {
                mpe.Fade(mpe.Info.MenuEffect);
            }

            menu.Get <LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Metadata.Version;

            buttonContainer = menu.Get("MENU_BUTTONS");
            buttonTemplate  = buttonContainer.Get <ButtonWidget>("BUTTON_TEMPLATE");
            buttonContainer.RemoveChild(buttonTemplate);
            buttonContainer.IsVisible = () => !hideMenu;

            MiniYaml buttonStrideNode;

            if (logicArgs.TryGetValue("ButtonStride", out buttonStrideNode))
            {
                buttonStride = FieldLoader.GetValue <int2>("ButtonStride", buttonStrideNode.Value);
            }

            var scriptContext = world.WorldActor.TraitOrDefault <LuaScript>();

            hasError = scriptContext != null && scriptContext.FatalErrorOccurred;

            MiniYaml buttonsNode;

            if (logicArgs.TryGetValue("Buttons", out buttonsNode))
            {
                Action createHandler;
                var    buttonIds = FieldLoader.GetValue <string[]>("Buttons", buttonsNode.Value);
                foreach (var button in buttonIds)
                {
                    if (buttonHandlers.TryGetValue(button, out createHandler))
                    {
                        createHandler();
                    }
                }
            }

            // Recenter the button container
            if (buttons.Count > 0)
            {
                var expand = (buttons.Count - 1) * buttonStride;
                buttonContainer.Bounds.X      -= expand.X / 2;
                buttonContainer.Bounds.Y      -= expand.Y / 2;
                buttonContainer.Bounds.Width  += expand.X;
                buttonContainer.Bounds.Height += expand.Y;
            }

            var panelRoot = widget.GetOrNull("PANEL_ROOT");

            if (panelRoot != null && world.Type != WorldType.Editor)
            {
                Action <bool> requestHideMenu = h => hideMenu = h;
                var           gameInfoPanel   = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs()
                {
                    { "activePanel", activePanel },
                    { "hideMenu", requestHideMenu }
                });

                gameInfoPanel.IsVisible = () => !hideMenu;
            }
        }
Example #2
0
        static void Main(string[] args)
        {
            var arguments = new Arguments(args);

            Log.AddChannel("debug", "dedicated-debug.log");
            Log.AddChannel("perf", "dedicated-perf.log");
            Log.AddChannel("server", "dedicated-server.log");
            Log.AddChannel("nat", "dedicated-nat.log");

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

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

            if (modID == null)
            {
                throw new InvalidOperationException("Game.Mod argument missing or mod could not be found.");
            }

            // HACK: The engine code assumes that Game.Settings is set.
            // This isn't nearly as bad as ModData, but is still not very nice.
            Game.InitializeSettings(arguments);
            var settings = Game.Settings.Server;

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

            var mods = new InstalledMods(modSearchPaths, explicitModPaths);

            // HACK: The engine code *still* assumes that Game.ModData is set
            var modData = Game.ModData = new ModData(mods[modID], mods);

            modData.MapCache.LoadMaps();

            settings.Map = modData.MapCache.ChooseInitialMap(settings.Map, new MersenneTwister());

            Console.WriteLine("[{0}] Starting dedicated server for mod: {1}", DateTime.Now.ToString(settings.TimestampFormat), modID);
            while (true)
            {
                var server = new Server(new IPEndPoint(IPAddress.Any, settings.ListenPort), settings, modData, true);

                while (true)
                {
                    Thread.Sleep(1000);
                    if (server.State == ServerState.GameStarted && server.Conns.Count < 1)
                    {
                        Console.WriteLine("[{0}] No one is playing, shutting down...", DateTime.Now.ToString(settings.TimestampFormat));
                        server.Shutdown();
                        break;
                    }
                }

                Console.WriteLine("[{0}] Starting a new server instance...", DateTime.Now.ToString(settings.TimestampFormat));
            }
        }
Example #3
0
 public static T NodeValue <T>(this MiniYamlNode node)
 {
     return(FieldLoader.GetValue <T>(node.Key, node.Value.Value));
 }
Example #4
0
        public D2AssetBrowserLogic(Widget widget, Action onExit, ModData modData, World world, Dictionary <string, MiniYaml> logicArgs)
        {
            this.world   = world;
            this.modData = modData;
            panel        = widget;

            var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER");

            if (ticker != null)
            {
                ticker.OnTick = () =>
                {
                    if (animateFrames)
                    {
                        SelectNextFrame();
                    }
                };
            }

            var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR");

            if (sourceDropdown != null)
            {
                sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown);
                sourceDropdown.GetText     = () =>
                {
                    var name = assetSource != null?Platform.UnresolvePath(assetSource.Name) : "All Packages";

                    if (name.Length > 15)
                    {
                        name = "..." + name.Substring(name.Length - 15);
                    }

                    return(name);
                };
            }

            var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE");

            if (spriteWidget != null)
            {
                spriteWidget.GetSprite  = () => currentSprites != null ? currentSprites[currentFrame] : null;
                currentPalette          = spriteWidget.Palette;
                spriteWidget.GetPalette = () => currentPalette;
                spriteWidget.IsVisible  = () => !isVideoLoaded && !isLoadError;
            }

            var playerWidget = panel.GetOrNull <WsaPlayerWidget>("PLAYER");

            if (playerWidget != null)
            {
                playerWidget.IsVisible = () => isVideoLoaded && !isLoadError;
            }

            var errorLabelWidget = panel.GetOrNull("ERROR");

            if (errorLabelWidget != null)
            {
                errorLabelWidget.IsVisible = () => isLoadError;
            }

            var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR");

            if (paletteDropDown != null)
            {
                paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world);
                paletteDropDown.GetText     = () => currentPalette;
            }

            var colorPreview = panel.GetOrNull <ColorPreviewManagerWidget>("COLOR_MANAGER");

            if (colorPreview != null)
            {
                colorPreview.Color = Game.Settings.Player.Color;
            }

            var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR");

            if (colorDropdown != null)
            {
                colorDropdown.IsDisabled  = () => currentPalette != colorPreview.PaletteName;
                colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, world);
                panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => Game.Settings.Player.Color;
            }

            filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT");
            filenameInput.OnTextEdited = () => ApplyFilter();
            filenameInput.OnEscKey     = filenameInput.YieldKeyboardFocus;

            var frameContainer = panel.GetOrNull("FRAME_SELECTOR");

            if (frameContainer != null)
            {
                frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) ||
                                           (isVideoLoaded && player != null && player.Video != null && player.Video.Length > 1);
            }

            frameSlider = panel.Get <SliderWidget>("FRAME_SLIDER");
            if (frameSlider != null)
            {
                frameSlider.OnChange += x =>
                {
                    if (!isVideoLoaded)
                    {
                        currentFrame = (int)Math.Round(x);
                    }
                };

                frameSlider.GetValue   = () => isVideoLoaded ? player.Video.CurrentFrame : currentFrame;
                frameSlider.IsDisabled = () => isVideoLoaded;
            }

            var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT");

            if (frameText != null)
            {
                frameText.GetText = () =>
                                    isVideoLoaded ?
                                    "{0} / {1}".F(player.Video.CurrentFrame + 1, player.Video.Length) :
                                    "{0} / {1}".F(currentFrame, currentSprites.Length - 1);
            }

            var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY");

            if (playButton != null)
            {
                playButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Play();
                    }
                    else
                    {
                        animateFrames = true;
                    }
                };

                playButton.IsVisible = () => isVideoLoaded ? player.Paused : !animateFrames;
            }

            var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE");

            if (pauseButton != null)
            {
                pauseButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Pause();
                    }
                    else
                    {
                        animateFrames = false;
                    }
                };

                pauseButton.IsVisible = () => isVideoLoaded ? !player.Paused : animateFrames;
            }

            var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP");

            if (stopButton != null)
            {
                stopButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Stop();
                    }
                    else
                    {
                        frameSlider.Value = 0;
                        currentFrame      = 0;
                        animateFrames     = false;
                    }
                };
            }

            var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT");

            if (nextButton != null)
            {
                nextButton.OnClick = () =>
                {
                    if (!isVideoLoaded)
                    {
                        nextButton.OnClick = SelectNextFrame;
                    }
                };

                nextButton.IsVisible = () => !isVideoLoaded;
            }

            var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV");

            if (prevButton != null)
            {
                prevButton.OnClick = () =>
                {
                    if (!isVideoLoaded)
                    {
                        SelectPreviousFrame();
                    }
                };

                prevButton.IsVisible = () => !isVideoLoaded;
            }

            if (logicArgs.ContainsKey("SupportedFormats"))
            {
                allowedExtensions = FieldLoader.GetValue <string[]>("SupportedFormats", logicArgs["SupportedFormats"].Value);
            }
            else
            {
                allowedExtensions = new string[0];
            }

            acceptablePackages = modData.ModFiles.MountedPackages.Where(p =>
                                                                        p.Contents.Any(c => allowedExtensions.Contains(Path.GetExtension(c).ToLowerInvariant())));

            assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST");
            template  = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE");
            PopulateAssetList();

            var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON");

            if (closeButton != null)
            {
                closeButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Stop();
                    }
                    Ui.CloseWindow();
                    onExit();
                }
            }
            ;
        }

        void SelectNextFrame()
        {
            currentFrame++;
            if (currentFrame >= currentSprites.Length)
            {
                currentFrame = 0;
            }
        }

        void SelectPreviousFrame()
        {
            currentFrame--;
            if (currentFrame < 0)
            {
                currentFrame = currentSprites.Length - 1;
            }
        }

        Dictionary <string, bool> assetVisByName = new Dictionary <string, bool>();

        bool FilterAsset(string filename)
        {
            var filter = filenameInput.Text;

            if (string.IsNullOrWhiteSpace(filter))
            {
                return(true);
            }

            if (filename.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)
            {
                return(true);
            }

            return(false);
        }

        void ApplyFilter()
        {
            assetVisByName.Clear();
            assetList.Layout.AdjustChildren();
            assetList.ScrollToTop();

            // Select the first visible
            var firstVisible = assetVisByName.FirstOrDefault(kvp => kvp.Value);
            IReadOnlyPackage package;
            string           filename;

            if (firstVisible.Key != null && modData.DefaultFileSystem.TryGetPackageContaining(firstVisible.Key, out package, out filename))
            {
                LoadAsset(package, filename);
            }
        }

        void AddAsset(ScrollPanelWidget list, string filepath, IReadOnlyPackage package, ScrollItemWidget template)
        {
            var item = ScrollItemWidget.Setup(template,
                                              () => currentFilename == filepath && currentPackage == package,
                                              () => { LoadAsset(package, filepath); });

            item.Get <LabelWidget>("TITLE").GetText = () => filepath;
            item.IsVisible = () =>
            {
                bool visible;
                if (assetVisByName.TryGetValue(filepath, out visible))
                {
                    return(visible);
                }

                visible = FilterAsset(filepath);
                assetVisByName.Add(filepath, visible);
                return(visible);
            };

            list.AddChild(item);
        }

        bool LoadAsset(IReadOnlyPackage package, string filename)
        {
            if (isVideoLoaded)
            {
                player.Stop();
                player        = null;
                isVideoLoaded = false;
            }

            if (string.IsNullOrEmpty(filename))
            {
                return(false);
            }

            if (!package.Contains(filename))
            {
                return(false);
            }

            isLoadError = false;

            try
            {
                currentPackage  = package;
                currentFilename = filename;
                var prefix = "";
                var fs     = modData.DefaultFileSystem as OpenRA.FileSystem.FileSystem;

                if (fs != null)
                {
                    prefix = fs.GetPrefix(package);
                    if (prefix != null)
                    {
                        prefix += "|";
                    }
                }

                if (Path.GetExtension(filename.ToLowerInvariant()) == ".wsa")
                {
                    player = panel.Get <WsaPlayerWidget>("PLAYER");
                    player.Load(prefix + filename);
                    isVideoLoaded            = true;
                    frameSlider.MaximumValue = (float)player.Video.Length - 1;
                    frameSlider.Ticks        = 0;
                    return(true);
                }

                currentSprites           = world.Map.Rules.Sequences.SpriteCache[prefix + filename];
                currentFrame             = 0;
                frameSlider.MaximumValue = (float)currentSprites.Length - 1;
                frameSlider.Ticks        = currentSprites.Length;
            }
            catch (Exception ex)
            {
                isLoadError = true;
                Log.AddChannel("assetbrowser", "assetbrowser.log");
                Log.Write("assetbrowser", "Error reading {0}:{3} {1}{3}{2}", filename, ex.Message, ex.StackTrace, Environment.NewLine);

                return(false);
            }

            return(true);
        }

        bool ShowSourceDropdown(DropDownButtonWidget dropdown)
        {
            Func <IReadOnlyPackage, ScrollItemWidget, ScrollItemWidget> setupItem = (source, itemTemplate) =>
            {
                var item = ScrollItemWidget.Setup(itemTemplate,
                                                  () => assetSource == source,
                                                  () => { assetSource = source; PopulateAssetList(); });
                item.Get <LabelWidget>("LABEL").GetText = () => source != null?Platform.UnresolvePath(source.Name) : "All Packages";

                return(item);
            };

            var sources = new[] { (IReadOnlyPackage)null }.Concat(acceptablePackages);

            dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, sources, setupItem);
            return(true);
        }

        void PopulateAssetList()
        {
            assetList.RemoveChildren();

            var files = new SortedList <string, List <IReadOnlyPackage> >();

            if (assetSource != null)
            {
                foreach (var content in assetSource.Contents)
                {
                    files.Add(content, new List <IReadOnlyPackage> {
                        assetSource
                    });
                }
            }
            else
            {
                foreach (var mountedPackage in modData.ModFiles.MountedPackages)
                {
                    foreach (var content in mountedPackage.Contents)
                    {
                        if (!files.ContainsKey(content))
                        {
                            files.Add(content, new List <IReadOnlyPackage> {
                                mountedPackage
                            });
                        }
                        else
                        {
                            files[content].Add(mountedPackage);
                        }
                    }
                }
            }

            foreach (var file in files.OrderBy(s => s.Key))
            {
                if (!allowedExtensions.Any(ext => file.Key.EndsWith(ext, true, CultureInfo.InvariantCulture)))
                {
                    continue;
                }

                foreach (var package in file.Value)
                {
                    AddAsset(assetList, file.Key, package, template);
                }
            }
        }

        bool ShowPaletteDropdown(DropDownButtonWidget dropdown, World world)
        {
            Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (name, itemTemplate) =>
            {
                var item = ScrollItemWidget.Setup(itemTemplate,
                                                  () => currentPalette == name,
                                                  () => currentPalette = name);
                item.Get <LabelWidget>("LABEL").GetText = () => name;

                return(item);
            };

            var palettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserPalettes>()
                           .SelectMany(p => p.PaletteNames);

            dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, palettes, setupItem);
            return(true);
        }
    }
Example #5
0
        public ButtonTooltipWithDescHighlightLogic(Widget widget, ButtonWidget button, Dictionary <string, MiniYaml> logicArgs)
        {
            var label      = widget.Get <LabelWidget>("LABEL");
            var font       = Game.Renderer.Fonts[label.Font];
            var text       = button.GetTooltipText();
            var labelWidth = font.Measure(text).X;
            var key        = button.Key.GetValue();

            label.GetText       = () => text;
            label.Bounds.Width  = labelWidth;
            widget.Bounds.Width = 2 * label.Bounds.X + labelWidth;

            if (key.IsValid())
            {
                var hotkey = widget.Get <LabelWidget>("HOTKEY");
                hotkey.Visible = true;

                var hotkeyLabel = "({0})".F(key.DisplayString());
                hotkey.GetText  = () => hotkeyLabel;
                hotkey.Bounds.X = labelWidth + 2 * label.Bounds.X;

                widget.Bounds.Width = hotkey.Bounds.X + label.Bounds.X + font.Measure(hotkeyLabel).X;
            }

            var desc = button.GetTooltipDesc();

            if (!string.IsNullOrEmpty(desc))
            {
                var descTemplate   = widget.Get <LabelWidget>("DESC");
                var highlightColor = FieldLoader.GetValue <Color>("Highlight", logicArgs["Highlight"].Value);
                widget.RemoveChild(descTemplate);

                var descFont   = Game.Renderer.Fonts[descTemplate.Font];
                var descWidth  = 0;
                var descOffset = descTemplate.Bounds.Y;

                foreach (var l in desc.Split(new[] { "\\n" }, StringSplitOptions.None))
                {
                    var line      = l;
                    var lineWidth = 0;
                    var xOffset   = descTemplate.Bounds.X;

                    while (line.Length > 0)
                    {
                        var highlightStart = line.IndexOf('{');
                        var highlightEnd   = line.IndexOf('}', 0);

                        if (highlightStart > 0 && highlightEnd > highlightStart)
                        {
                            if (highlightStart > 0)
                            {
                                // Normal line segment before highlight
                                var lineNormal      = line.Substring(0, highlightStart);
                                var lineNormalWidth = descFont.Measure(lineNormal).X;
                                var lineNormalLabel = (LabelWidget)descTemplate.Clone();
                                lineNormalLabel.GetText      = () => lineNormal;
                                lineNormalLabel.Bounds.X     = descTemplate.Bounds.X + lineWidth;
                                lineNormalLabel.Bounds.Y     = descOffset;
                                lineNormalLabel.Bounds.Width = lineNormalWidth;
                                widget.AddChild(lineNormalLabel);

                                lineWidth += lineNormalWidth;
                            }

                            // Highlight line segment
                            var lineHighlight      = line.Substring(highlightStart + 1, highlightEnd - highlightStart - 1);
                            var lineHighlightWidth = descFont.Measure(lineHighlight).X;
                            var lineHighlightLabel = (LabelWidget)descTemplate.Clone();
                            lineHighlightLabel.GetText      = () => lineHighlight;
                            lineHighlightLabel.GetColor     = () => highlightColor;
                            lineHighlightLabel.Bounds.X     = descTemplate.Bounds.X + lineWidth;
                            lineHighlightLabel.Bounds.Y     = descOffset;
                            lineHighlightLabel.Bounds.Width = lineHighlightWidth;
                            widget.AddChild(lineHighlightLabel);

                            lineWidth += lineHighlightWidth;
                            line       = line.Substring(highlightEnd + 1);
                        }
                        else
                        {
                            // Final normal line segment
                            var lineLabel = (LabelWidget)descTemplate.Clone();
                            var width     = descFont.Measure(line).X;
                            lineLabel.GetText  = () => line;
                            lineLabel.Bounds.X = descTemplate.Bounds.X + lineWidth;
                            lineLabel.Bounds.Y = descOffset;
                            widget.AddChild(lineLabel);

                            lineWidth += width;
                            break;
                        }
                    }

                    descWidth = Math.Max(descWidth, lineWidth);

                    descOffset += descTemplate.Bounds.Height;
                }

                widget.Bounds.Width   = Math.Max(widget.Bounds.Width, descTemplate.Bounds.X * 2 + descWidth);
                widget.Bounds.Height += descOffset - descTemplate.Bounds.Y + descTemplate.Bounds.X;
            }
        }
Example #6
0
        static void Run(string[] args)
        {
            var arguments = new Arguments(args);

            var engineDirArg = arguments.GetValue("Engine.EngineDir", null);

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

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

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

            Log.AddChannel("debug", "dedicated-debug.log", true);
            Log.AddChannel("perf", "dedicated-perf.log", true);
            Log.AddChannel("server", "dedicated-server.log", true);
            Log.AddChannel("nat", "dedicated-nat.log", true);
            Log.AddChannel("geoip", "dedicated-geoip.log", true);

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

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

            if (modID == null)
            {
                throw new InvalidOperationException("Game.Mod argument missing or mod could not be found.");
            }

            // HACK: The engine code assumes that Game.Settings is set.
            // This isn't nearly as bad as ModData, but is still not very nice.
            Game.InitializeSettings(arguments);
            var settings = Game.Settings.Server;

            Nat.Initialize();

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

            var mods = new InstalledMods(modSearchPaths, explicitModPaths);

            WriteLineWithTimeStamp($"Starting dedicated server for mod: {modID}");
            while (true)
            {
                // HACK: The engine code *still* assumes that Game.ModData is set
                var modData = Game.ModData = new ModData(mods[modID], mods);
                modData.MapCache.LoadMaps();

                settings.Map = modData.MapCache.ChooseInitialMap(settings.Map, new MersenneTwister());

                var endpoints = new List <IPEndPoint> {
                    new IPEndPoint(IPAddress.IPv6Any, settings.ListenPort), new IPEndPoint(IPAddress.Any, settings.ListenPort)
                };
                var server = new Server(endpoints, settings, modData, ServerType.Dedicated);

                GC.Collect();
                while (true)
                {
                    Thread.Sleep(1000);
                    if (server.State == ServerState.GameStarted && server.Conns.Count < 1)
                    {
                        WriteLineWithTimeStamp("No one is playing, shutting down...");
                        server.Shutdown();
                        break;
                    }
                }

                modData.Dispose();
                WriteLineWithTimeStamp("Starting a new server instance...");
            }
        }
Example #7
0
        internal static void UpgradeMapFormat(ModData modData, IReadWritePackage package)
        {
            if (package == null)
            {
                return;
            }

            var yamlStream = package.GetStream("map.yaml");

            if (yamlStream == null)
            {
                return;
            }

            var yaml      = new MiniYaml(null, MiniYaml.FromStream(yamlStream, package.Name));
            var nd        = yaml.ToDictionary();
            var mapFormat = FieldLoader.GetValue <int>("MapFormat", nd["MapFormat"].Value);

            if (mapFormat < 6)
            {
                throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, package.Name));
            }

            // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum
            if (mapFormat < 7)
            {
                MiniYaml useAsShellmap;
                if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value))
                {
                    yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("Shellmap")));
                }
                else if (nd["Type"].Value == "Mission" || nd["Type"].Value == "Campaign")
                {
                    yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("MissionSelector")));
                }
            }

            // Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors
            if (mapFormat < 8)
            {
                var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players");
                if (players != null)
                {
                    bool noteHexColors = false;
                    bool noteColorRamp = false;
                    foreach (var player in players.Value.Nodes)
                    {
                        var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp");
                        if (colorRampNode != null)
                        {
                            Color dummy;
                            var   parts = colorRampNode.Value.Value.Split(',');
                            if (parts.Length == 3 || parts.Length == 4)
                            {
                                // Try to convert old normalized HSL value to a rgb hex color
                                try
                                {
                                    HSLColor color = new HSLColor(
                                        (byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255),
                                        (byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255),
                                        (byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255));
                                    colorRampNode.Value.Value = FieldSaver.FormatValue(color);
                                    noteHexColors             = true;
                                }
                                catch (Exception)
                                {
                                    throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name);
                                }
                            }
                            else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy))
                            {
                                throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name);
                            }

                            colorRampNode.Key = "Color";
                            noteColorRamp     = true;
                        }
                    }

                    if (noteHexColors)
                    {
                        Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa].");
                    }
                    else if (noteColorRamp)
                    {
                        Console.WriteLine("ColorRamp is now called Color.");
                    }
                }
            }

            // Format 8 -> 9 moved map options and videos from the map file itself to traits
            if (mapFormat < 9)
            {
                var rules     = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
                var worldNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "World");
                if (worldNode == null)
                {
                    worldNode = new MiniYamlNode("World", new MiniYaml("", new List <MiniYamlNode>()));
                }

                var playerNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "Player");
                if (playerNode == null)
                {
                    playerNode = new MiniYamlNode("Player", new MiniYaml("", new List <MiniYamlNode>()));
                }

                var visibilityNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Visibility");
                if (visibilityNode != null)
                {
                    var visibility = FieldLoader.GetValue <MapVisibility>("Visibility", visibilityNode.Value.Value);
                    if (visibility.HasFlag(MapVisibility.MissionSelector))
                    {
                        var missionData = new MiniYamlNode("MissionData", new MiniYaml("", new List <MiniYamlNode>()));
                        worldNode.Value.Nodes.Add(missionData);

                        var description = yaml.Nodes.FirstOrDefault(n => n.Key == "Description");
                        if (description != null)
                        {
                            missionData.Value.Nodes.Add(new MiniYamlNode("Briefing", description.Value.Value));
                        }

                        var videos = yaml.Nodes.FirstOrDefault(n => n.Key == "Videos");
                        if (videos != null && videos.Value.Nodes.Any())
                        {
                            var backgroundVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "BackgroundInfo");
                            if (backgroundVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("BackgroundVideo", backgroundVideo.Value.Value));
                            }

                            var briefingVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "Briefing");
                            if (briefingVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("BriefingVideo", briefingVideo.Value.Value));
                            }

                            var startVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameStart");
                            if (startVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("StartVideo", startVideo.Value.Value));
                            }

                            var winVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameWon");
                            if (winVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("WinVideo", winVideo.Value.Value));
                            }

                            var lossVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameLost");
                            if (lossVideo != null)
                            {
                                missionData.Value.Nodes.Add(new MiniYamlNode("LossVideo", lossVideo.Value.Value));
                            }
                        }
                    }
                }

                var mapOptions = yaml.Nodes.FirstOrDefault(n => n.Key == "Options");
                if (mapOptions != null)
                {
                    var cheats = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Cheats");
                    if (cheats != null)
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("DeveloperMode", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("Locked", "True"),
                            new MiniYamlNode("Enabled", cheats.Value.Value)
                        })));
                    }

                    var crates = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Crates");
                    if (crates != null && !worldNode.Value.Nodes.Any(n => n.Key == "-CrateSpawner"))
                    {
                        if (!FieldLoader.GetValue <bool>("crates", crates.Value.Value))
                        {
                            worldNode.Value.Nodes.Add(new MiniYamlNode("-CrateSpawner", new MiniYaml("")));
                        }
                    }

                    var creeps = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Creeps");
                    if (creeps != null)
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("MapCreeps", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("Locked", "True"),
                            new MiniYamlNode("Enabled", creeps.Value.Value)
                        })));
                    }

                    var fog    = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Fog");
                    var shroud = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Shroud");
                    if (fog != null || shroud != null)
                    {
                        var shroudNode = new MiniYamlNode("Shroud", new MiniYaml("", new List <MiniYamlNode>()));
                        playerNode.Value.Nodes.Add(shroudNode);

                        if (fog != null)
                        {
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("FogLocked", "True"));
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("FogEnabled", fog.Value.Value));
                        }

                        if (shroud != null)
                        {
                            var enabled = FieldLoader.GetValue <bool>("shroud", shroud.Value.Value);
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapLocked", "True"));
                            shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapEnabled", FieldSaver.FormatValue(!enabled)));
                        }
                    }

                    var allyBuildRadius = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "AllyBuildRadius");
                    if (allyBuildRadius != null)
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("MapBuildRadius", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("AllyBuildRadiusLocked", "True"),
                            new MiniYamlNode("AllyBuildRadiusEnabled", allyBuildRadius.Value.Value)
                        })));
                    }

                    var startingCash = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "StartingCash");
                    if (startingCash != null)
                    {
                        playerNode.Value.Nodes.Add(new MiniYamlNode("PlayerResources", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("DefaultCashLocked", "True"),
                            new MiniYamlNode("DefaultCash", startingCash.Value.Value)
                        })));
                    }

                    var startingUnits = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ConfigurableStartingUnits");
                    if (startingUnits != null && !worldNode.Value.Nodes.Any(n => n.Key == "-SpawnMPUnits"))
                    {
                        worldNode.Value.Nodes.Add(new MiniYamlNode("SpawnMPUnits", new MiniYaml("", new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("Locked", "True"),
                        })));
                    }

                    var techLevel    = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "TechLevel");
                    var difficulties = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Difficulties");
                    var shortGame    = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ShortGame");
                    if (techLevel != null || difficulties != null || shortGame != null)
                    {
                        var optionsNode = new MiniYamlNode("MapOptions", new MiniYaml("", new List <MiniYamlNode>()));
                        worldNode.Value.Nodes.Add(optionsNode);

                        if (techLevel != null)
                        {
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevelLocked", "True"));
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevel", techLevel.Value.Value));
                        }

                        if (difficulties != null)
                        {
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("Difficulties", difficulties.Value.Value));
                        }

                        if (shortGame != null)
                        {
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameLocked", "True"));
                            optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameEnabled", shortGame.Value.Value));
                        }
                    }
                }

                if (worldNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(worldNode))
                {
                    rules.Value.Nodes.Add(worldNode);
                }

                if (playerNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(playerNode))
                {
                    rules.Value.Nodes.Add(playerNode);
                }
            }

            // Format 9 -> 10 moved smudges to SmudgeLayer, and uses map.png for all maps
            if (mapFormat < 10)
            {
                ExtractSmudges(yaml);
                if (package.Contains("map.png"))
                {
                    yaml.Nodes.Add(new MiniYamlNode("LockPreview", new MiniYaml("True")));
                }
            }

            // Format 10 -> 11 replaced the single map type field with a list of categories
            if (mapFormat < 11)
            {
                var type = yaml.Nodes.First(n => n.Key == "Type");
                yaml.Nodes.Add(new MiniYamlNode("Categories", type.Value));
                yaml.Nodes.Remove(type);
            }

            if (mapFormat < Map.SupportedMapFormat)
            {
                yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString());
                Console.WriteLine("Converted {0} to MapFormat {1}.", package.Name, Map.SupportedMapFormat);
            }

            package.Update("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString()));
        }
Example #8
0
 public static T Get <T>(string key)
 {
     return(FieldLoader.GetValue <T>(key, data[key]));
 }
Example #9
0
        internal static void UpgradeWeaponRules(ModData modData, int engineVersion, ref List <MiniYamlNode> nodes, MiniYamlNode parent, int depth)
        {
            foreach (var node in nodes)
            {
                // Refactor Missile RangeLimit from ticks to WDist
                if (engineVersion < 20160509)
                {
                    var weapRange  = node.Value.Nodes.FirstOrDefault(n => n.Key == "Range");
                    var projectile = node.Value.Nodes.FirstOrDefault(n => n.Key == "Projectile");

                    if (projectile != null && weapRange != null && projectile.Value.Value == "Missile")
                    {
                        var oldWDist       = FieldLoader.GetValue <WDist>("Range", weapRange.Value.Value);
                        var rangeLimitNode = projectile.Value.Nodes.FirstOrDefault(x => x.Key == "RangeLimit");

                        // RangeLimit is now a WDist value, so for the conversion, we take weapon range and add 20% on top.
                        // Overly complicated calculations using Range, Speed and the old RangeLimit value would be rather pointless,
                        // because currently most mods have somewhat arbitrary, usually too high and in a few cases too low RangeLimits anyway.
                        var newValue    = oldWDist.Length * 120 / 100;
                        var newCells    = newValue / 1024;
                        var newCellPart = newValue % 1024;

                        if (rangeLimitNode != null)
                        {
                            rangeLimitNode.Value.Value = newCells.ToString() + "c" + newCellPart.ToString();
                        }
                        else
                        {
                            // Since the old default was 'unlimited', we're using weapon range * 1.2 for missiles not defining a custom RangeLimit as well
                            projectile.Value.Nodes.Add(new MiniYamlNode("RangeLimit", newCells.ToString() + "c" + newCellPart.ToString()));
                        }
                    }
                }

                // Streamline some projectile property names and functionality
                if (engineVersion < 20160601)
                {
                    if (node.Key == "Sequence")
                    {
                        node.Key = "Sequences";
                    }

                    if (node.Key == "TrailSequence")
                    {
                        node.Key = "TrailSequences";
                    }

                    if (node.Key == "Trail")
                    {
                        node.Key = "TrailImage";
                    }

                    if (node.Key == "Velocity")
                    {
                        node.Key = "Speed";
                    }
                }

                UpgradeWeaponRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
            }
        }
Example #10
0
        internal static void UpgradeActorRules(ModData modData, int engineVersion, ref List <MiniYamlNode> nodes, MiniYamlNode parent, int depth)
        {
            var addNodes = new List <MiniYamlNode>();

            foreach (var node in nodes)
            {
                if (engineVersion < 20160515)
                {
                    // Use generic naming for building demolition using explosives.
                    if (node.Key == "C4Demolition")
                    {
                        node.Key = "Demolition";
                    }

                    foreach (var n in node.Value.Nodes)
                    {
                        if (n.Key == "C4Delay")
                        {
                            n.Key = "DetonationDelay";
                        }
                    }
                }

                // WithSmoke was refactored to become more generic and Sequence/Image notation has been unified.
                if (engineVersion < 20160528)
                {
                    if (depth == 1 && node.Key.StartsWith("WithSmoke"))
                    {
                        var s = node.Value.Nodes.FirstOrDefault(n => n.Key == "Sequence");
                        if (s != null)
                        {
                            s.Key = "Image";
                        }

                        var parts = node.Key.Split('@');
                        node.Key = "WithDamageOverlay";
                        if (parts.Length > 1)
                        {
                            node.Key += "@" + parts[1];
                        }
                    }
                }

                if (engineVersion < 20160604 && node.Key.StartsWith("ProvidesTechPrerequisite"))
                {
                    var name = node.Value.Nodes.First(n => n.Key == "Name");
                    var id   = name.Value.Value.ToLowerInvariant().Replace(" ", "");
                    node.Value.Nodes.Add(new MiniYamlNode("Id", id));
                }

                if (engineVersion < 20160611)
                {
                    // Deprecated WithSpriteRotorOverlay
                    if (depth == 1 && node.Key.StartsWith("WithSpriteRotorOverlay"))
                    {
                        var parts = node.Key.Split('@');
                        node.Key = "WithIdleOverlay";
                        if (parts.Length > 1)
                        {
                            node.Key += "@" + parts[1];
                        }

                        Console.WriteLine("The 'WithSpriteRotorOverlay' trait has been removed.");
                        Console.WriteLine("Its functionality can be fully replicated with 'WithIdleOverlay' + upgrades.");
                        Console.WriteLine("Look at the helicopters in our RA / C&C1  mods for implementation details.");
                    }
                }

                // Map difficulty configuration was split to a generic trait
                if (engineVersion < 20160614 && node.Key.StartsWith("MapOptions"))
                {
                    var difficultiesNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Difficulties");
                    if (difficultiesNode != null)
                    {
                        var difficulties = FieldLoader.GetValue <string[]>("Difficulties", difficultiesNode.Value.Value)
                                           .ToDictionary(d => d.Replace(" ", "").ToLowerInvariant(), d => d);
                        node.Value.Nodes.Remove(difficultiesNode);

                        var childNodes = new List <MiniYamlNode>()
                        {
                            new MiniYamlNode("ID", "difficulty"),
                            new MiniYamlNode("Label", "Difficulty"),
                            new MiniYamlNode("Values", new MiniYaml("", difficulties.Select(kv => new MiniYamlNode(kv.Key, kv.Value)).ToList()))
                        };

                        var difficultyNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Difficulty");
                        if (difficultyNode != null)
                        {
                            childNodes.Add(new MiniYamlNode("Default", difficultyNode.Value.Value.Replace(" ", "").ToLowerInvariant()));
                            node.Value.Nodes.Remove(difficultyNode);
                        }
                        else
                        {
                            childNodes.Add(new MiniYamlNode("Default", difficulties.Keys.First()));
                        }

                        var lockedNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "DifficultyLocked");
                        if (lockedNode != null)
                        {
                            childNodes.Add(new MiniYamlNode("Locked", lockedNode.Value.Value));
                            node.Value.Nodes.Remove(lockedNode);
                        }

                        addNodes.Add(new MiniYamlNode("ScriptLobbyDropdown@difficulty", new MiniYaml("", childNodes)));
                    }
                }

                if (engineVersion < 20160702)
                {
                    if (node.Key.StartsWith("GivesExperience"))
                    {
                        var ff     = "FriendlyFire";
                        var ffNode = node.Value.Nodes.FirstOrDefault(n => n.Key == ff);
                        if (ffNode != null)
                        {
                            var newStanceStr = "";
                            if (FieldLoader.GetValue <bool>(ff, ffNode.Value.Value))
                            {
                                newStanceStr = "Neutral, Enemy, Ally";
                            }
                            else
                            {
                                newStanceStr = "Neutral, Enemy";
                            }

                            node.Value.Nodes.Add(new MiniYamlNode("ValidStances", newStanceStr));
                        }

                        node.Value.Nodes.Remove(ffNode);
                    }
                    else if (node.Key.StartsWith("GivesBounty"))
                    {
                        var stancesNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Stances");
                        if (stancesNode != null)
                        {
                            stancesNode.Key = "ValidStances";
                        }
                    }
                }

                if (engineVersion < 20160703)
                {
                    if (node.Key.StartsWith("WithDecoration") || node.Key.StartsWith("WithRankDecoration") || node.Key.StartsWith("WithDecorationCarryable"))
                    {
                        var stancesNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Stances");
                        if (stancesNode != null)
                        {
                            stancesNode.Key = "ValidStances";
                        }
                    }
                }

                if (engineVersion < 20160704)
                {
                    if (node.Key.Contains("PoisonedByTiberium"))
                    {
                        node.Key = node.Key.Replace("PoisonedByTiberium", "DamagedByTerrain");
                        if (!node.Key.StartsWith("-"))
                        {
                            if (node.Value.Nodes.Any(a => a.Key == "Resources"))
                            {
                                node.Value.Nodes.Where(n => n.Key == "Resources").Do(n => n.Key = "Terrain");
                            }
                            else
                            {
                                node.Value.Nodes.Add(new MiniYamlNode("Terrain", new MiniYaml("Tiberium, BlueTiberium")));
                            }

                            Console.WriteLine("PoisonedByTiberium: Weapon isn't converted. Copy out the appropriate");
                            Console.WriteLine("weapon's Damage, ReloadDelay and DamageTypes to DamagedByTerrain's Damage,");
                            Console.WriteLine("DamageInterval and DamageTypes, respectively, then remove the Weapon tag.");
                        }
                    }

                    if (node.Key.Contains("DamagedWithoutFoundation"))
                    {
                        node.Key = node.Key.Replace("DamagedWithoutFoundation", "DamagedByTerrain");
                        if (!node.Key.StartsWith("-"))
                        {
                            Console.WriteLine("DamagedWithoutFoundation: Weapon isn't converted. Copy out the appropriate");
                            Console.WriteLine("weapon's Damage, ReloadDelay and DamageTypes to DamagedByTerrain's Damage,");
                            Console.WriteLine("DamageInterval and DamageTypes, respectively, then remove the Weapon tag.");

                            Console.WriteLine("SafeTerrain isn't converted. Setup an inverted check using Terrain.");

                            node.Value.Nodes.Add(new MiniYamlNode("StartOnThreshold", new MiniYaml("true")));
                            if (!node.Value.Nodes.Any(a => a.Key == "DamageThreshold"))
                            {
                                node.Value.Nodes.Add(new MiniYamlNode("DamageThreshold", new MiniYaml("50")));
                            }
                        }
                    }
                }

                // ParticleDensityFactor was converted from a float to an int
                if (engineVersion < 20160713 && node.Key == "WeatherOverlay")
                {
                    var density = node.Value.Nodes.FirstOrDefault(n => n.Key == "ParticleDensityFactor");
                    if (density != null)
                    {
                        var value = float.Parse(density.Value.Value, CultureInfo.InvariantCulture);
                        value = (int)Math.Round(value * 10000, 0);
                        density.Value.Value = value.ToString();
                    }
                }

                UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
            }

            foreach (var a in addNodes)
            {
                nodes.Add(a);
            }
        }
        void IGameSaveTraitData.ResolveTraitData(Actor self, List <MiniYamlNode> data)
        {
            if (self.World.IsReplay)
            {
                return;
            }

            var initialBaseCenterNode = data.FirstOrDefault(n => n.Key == "InitialBaseCenter");

            if (initialBaseCenterNode != null)
            {
                initialBaseCenter = FieldLoader.GetValue <CPos>("InitialBaseCenter", initialBaseCenterNode.Value.Value);
            }

            var unitsHangingAroundTheBaseNode = data.FirstOrDefault(n => n.Key == "UnitsHangingAroundTheBase");

            if (unitsHangingAroundTheBaseNode != null)
            {
                unitsHangingAroundTheBase.Clear();
                unitsHangingAroundTheBase.AddRange(FieldLoader.GetValue <uint[]>("UnitsHangingAroundTheBase", unitsHangingAroundTheBaseNode.Value.Value)
                                                   .Select(a => self.World.GetActorById(a)).Where(a => a != null));
            }

            var activeUnitsNode = data.FirstOrDefault(n => n.Key == "ActiveUnits");

            if (activeUnitsNode != null)
            {
                activeUnits.Clear();
                activeUnits.AddRange(FieldLoader.GetValue <uint[]>("ActiveUnits", activeUnitsNode.Value.Value)
                                     .Select(a => self.World.GetActorById(a)).Where(a => a != null));
            }

            var rushTicksNode = data.FirstOrDefault(n => n.Key == "RushTicks");

            if (rushTicksNode != null)
            {
                rushTicks = FieldLoader.GetValue <int>("RushTicks", rushTicksNode.Value.Value);
            }

            var assignRolesTicksNode = data.FirstOrDefault(n => n.Key == "AssignRolesTicks");

            if (assignRolesTicksNode != null)
            {
                assignRolesTicks = FieldLoader.GetValue <int>("AssignRolesTicks", assignRolesTicksNode.Value.Value);
            }

            var attackForceTicksNode = data.FirstOrDefault(n => n.Key == "AttackForceTicks");

            if (attackForceTicksNode != null)
            {
                attackForceTicks = FieldLoader.GetValue <int>("AttackForceTicks", attackForceTicksNode.Value.Value);
            }

            var minAttackForceDelayTicksNode = data.FirstOrDefault(n => n.Key == "MinAttackForceDelayTicks");

            if (minAttackForceDelayTicksNode != null)
            {
                minAttackForceDelayTicks = FieldLoader.GetValue <int>("MinAttackForceDelayTicks", minAttackForceDelayTicksNode.Value.Value);
            }

            var squadsNode = data.FirstOrDefault(n => n.Key == "Squads");

            if (squadsNode != null)
            {
                Squads.Clear();
                foreach (var n in squadsNode.Value.Nodes)
                {
                    Squads.Add(Squad.Deserialize(bot, this, n.Value));
                }
            }
        }
Example #12
0
        static void ExtractFromISCab(string path, MiniYaml actionYaml, List <string> extractedFiles, Action <string> updateMessage)
        {
            // Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path
            var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value);

            var volumeNode = actionYaml.Nodes.FirstOrDefault(n => n.Key == "Volumes");

            if (volumeNode == null)
            {
                throw new InvalidDataException("extract-iscab entry doesn't define a Volumes node");
            }

            var extractNode = actionYaml.Nodes.FirstOrDefault(n => n.Key == "Extract");

            if (extractNode == null)
            {
                throw new InvalidDataException("extract-iscab entry doesn't define an Extract node");
            }

            var volumes = new Dictionary <int, Stream>();

            try
            {
                foreach (var node in volumeNode.Value.Nodes)
                {
                    var volume = FieldLoader.GetValue <int>("(key)", node.Key);
                    var stream = File.OpenRead(Path.Combine(path, node.Value.Value));
                    volumes.Add(volume, stream);
                }

                using (var source = File.OpenRead(sourcePath))
                {
                    var reader = new InstallShieldCABCompression(source, volumes);
                    foreach (var node in extractNode.Value.Nodes)
                    {
                        var targetPath = Platform.ResolvePath(node.Key);

                        if (File.Exists(targetPath))
                        {
                            Log.Write("install", "Skipping installed file " + targetPath);
                            continue;
                        }

                        extractedFiles.Add(targetPath);
                        Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
                        using (var target = File.OpenWrite(targetPath))
                        {
                            Log.Write("install", $"Extracting {sourcePath} -> {targetPath}");
                            var          displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
                            Action <int> onProgress      = percent => updateMessage($"Extracting {displayFilename} ({percent}%)");
                            reader.ExtractFile(node.Value.Value, target, onProgress);
                        }
                    }
                }
            }
            finally
            {
                foreach (var kv in volumes)
                {
                    kv.Value.Dispose();
                }
            }
        }
Example #13
0
        static void ExtractFromPackage(ExtractionType type, string path, MiniYaml actionYaml, List <string> extractedFiles, Action <string> updateMessage)
        {
            // Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path
            var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value);

            using (var source = File.OpenRead(sourcePath))
            {
                foreach (var node in actionYaml.Nodes)
                {
                    var targetPath = Platform.ResolvePath(node.Key);

                    if (File.Exists(targetPath))
                    {
                        Log.Write("install", "Skipping installed file " + targetPath);
                        continue;
                    }

                    var offsetNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Offset");
                    if (offsetNode == null)
                    {
                        Log.Write("install", "Skipping entry with missing Offset definition " + targetPath);
                        continue;
                    }

                    var lengthNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Length");
                    if (lengthNode == null)
                    {
                        Log.Write("install", "Skipping entry with missing Length definition " + targetPath);
                        continue;
                    }

                    var length = FieldLoader.GetValue <int>("Length", lengthNode.Value.Value);
                    source.Position = FieldLoader.GetValue <int>("Offset", offsetNode.Value.Value);

                    extractedFiles.Add(targetPath);
                    Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
                    var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));

                    Action <long> onProgress = null;
                    if (length < ShowPercentageThreshold)
                    {
                        updateMessage("Extracting " + displayFilename);
                    }
                    else
                    {
                        onProgress = b => updateMessage($"Extracting {displayFilename} ({100 * b / length}%)");
                    }

                    using (var target = File.OpenWrite(targetPath))
                    {
                        Log.Write("install", $"Extracting {sourcePath} -> {targetPath}");
                        if (type == ExtractionType.Blast)
                        {
                            Blast.Decompress(source, target, (read, _) => onProgress?.Invoke(read));
                        }
                        else
                        {
                            CopyStream(source, target, length, onProgress);
                        }
                    }
                }
            }
        }