Beispiel #1
0
        public bool Initialize()
        {
            Logger.Info("Initializing theater of type {0}", _theaterType);

            if (!ModConfig.SetActiveTheater(_theaterType))
            {
                return(false);
            }
            Active = this;

            // load palettes and additional mix files for this theater
            _palettes             = new PaletteCollection();
            _palettes.IsoPalette  = new Palette(VFS.Open <PalFile>(ModConfig.ActiveTheater.IsoPaletteName));
            _palettes.OvlPalette  = new Palette(VFS.Open <PalFile>(ModConfig.ActiveTheater.OverlayPaletteName));
            _palettes.UnitPalette = new Palette(VFS.Open <PalFile>(ModConfig.ActiveTheater.UnitPaletteName), ModConfig.ActiveTheater.UnitPaletteName, true);

            foreach (string mix in ModConfig.ActiveTheater.Mixes)
            {
                VFS.Add(mix, CacheMethod.Cache);                 // we wish for these to be cached as they're gonna be hit often
            }
            _palettes.AnimPalette = new Palette(VFS.Open <PalFile>("anim.pal"));

            _animations = new ObjectCollection(CollectionType.Animation, _theaterType, _engine, _rules, _art,
                                               _rules.GetSection("Animations"), _palettes);

            _tileTypes = new TileCollection(CollectionType.Tiles, _theaterType, _engine, _rules, _art, ModConfig.ActiveTheater);

            _buildingTypes = new ObjectCollection(CollectionType.Building, _theaterType, _engine, _rules, _art,
                                                  _rules.GetSection("BuildingTypes"), _palettes);

            _aircraftTypes = new ObjectCollection(CollectionType.Aircraft, _theaterType, _engine, _rules, _art,
                                                  _rules.GetSection("AircraftTypes"), _palettes);

            _infantryTypes = new ObjectCollection(CollectionType.Infantry, _theaterType, _engine, _rules, _art,
                                                  _rules.GetSection("InfantryTypes"), _palettes);

            _overlayTypes = new ObjectCollection(CollectionType.Overlay, _theaterType, _engine, _rules, _art,
                                                 _rules.GetSection("OverlayTypes"), _palettes);

            _terrainTypes = new ObjectCollection(CollectionType.Terrain, _theaterType, _engine, _rules, _art,
                                                 _rules.GetSection("TerrainTypes"), _palettes);

            _smudgeTypes = new ObjectCollection(CollectionType.Smudge, _theaterType, _engine, _rules, _art,
                                                _rules.GetSection("SmudgeTypes"), _palettes);

            _vehicleTypes = new ObjectCollection(CollectionType.Vehicle, _theaterType, _engine, _rules, _art,
                                                 _rules.GetSection("VehicleTypes"), _palettes);

            _tileTypes.InitTilesets();
            _tileTypes.InitAnimations(_animations);

            return(true);
        }
Beispiel #2
0
        public static int Main(string[] args)
        {
            InitLoggerConfig();
            InitSettings(args);

            // DumpTileProperties();

            if (!ValidateSettings())
            {
                return(2);
            }

            try {
                Logger.Info("Initializing virtual filesystem");

                var         mapStream = File.Open(Settings.InputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                VirtualFile vmapFile;
                var         mixMap = new MixFile(mapStream, Settings.InputFile, 0, mapStream.Length, false, false);
                if (mixMap.IsValid())                   // input max is a mix
                {
                    var mapArchive = new MixFile(mapStream, Path.GetFileName(Settings.InputFile), true);
                    // grab the largest file in the archive
                    var mixEntry = mapArchive.Index.OrderByDescending(me => me.Value.Length).First();
                    vmapFile = mapArchive.OpenFile(mixEntry.Key);
                }
                else
                {
                    vmapFile = new VirtualFile(mapStream, Path.GetFileName(Settings.InputFile), true);
                }
                var mapFile = new MapFile(vmapFile, Path.GetFileName(Settings.InputFile));

                if (!string.IsNullOrEmpty(Settings.ModConfig))
                {
                    if (File.Exists(Settings.ModConfig))
                    {
                        ModConfig cfg;
                        try {
                            using (FileStream f = File.OpenRead(Settings.ModConfig))
                                cfg = ModConfig.Deserialize(f);
                            ModConfig.ActiveConfig = cfg;
                            if (Settings.Engine != EngineType.AutoDetect)
                            {
                                if (Settings.Engine != cfg.Engine)
                                {
                                    Logger.Warn("Provided engine override does not match mod config.");
                                }
                            }
                            else
                            {
                                Settings.Engine = ModConfig.ActiveConfig.Engine;
                            }
                        }
                        catch (IOException) {
                            Logger.Error("IOException while loading mod config");
                        }
                        catch (XmlException) {
                            Logger.Error("XmlException while loading mod config");
                        }
                        catch (SerializationException) {
                            Logger.Error("Serialization exception while loading mod config");
                        }
                    }
                    else
                    {
                        Logger.Error("Invalid mod config file specified");
                    }
                }

                if (Settings.Engine == EngineType.AutoDetect)
                {
                    Settings.Engine = EngineDetector.DetectEngineType(mapFile);
                    Logger.Info("Engine autodetect result: {0}", Settings.Engine);
                }

                // ---------------------------------------------------------------
                // Code to organize moving of maps in a directory for themselves

                /*
                 * string mapName = DetermineMapName(mapFile, Settings.Engine);
                 * string ndir = Path.Combine(Path.GetDirectoryName(Settings.InputFile), mapName);
                 * if (!Directory.Exists(ndir)) Directory.CreateDirectory(ndir);
                 * mapFile.Close();
                 * mapFile.Dispose();
                 * File.Move(Settings.InputFile, Path.Combine(ndir, Path.GetFileName(mapFile.FileName)));
                 * return 0;*/
                // ---------------------------------------------------------------

                // enginetype is now definitive, load mod config
                if (ModConfig.ActiveConfig == null)
                {
                    ModConfig.LoadDefaultConfig(Settings.Engine);
                }

                // first add the dirs, then load the extra mixes, then scan the dirs
                foreach (string modDir in ModConfig.ActiveConfig.Directories)
                {
                    VFS.Add(modDir);
                }

                // add mixdir to VFS (if it's not included in the mod config)
                if (!ModConfig.ActiveConfig.Directories.Any())
                {
                    string mixDir = VFS.DetermineMixDir(Settings.MixFilesDirectory, Settings.Engine);
                    VFS.Add(mixDir);
                }
                foreach (string mixFile in ModConfig.ActiveConfig.ExtraMixes)
                {
                    VFS.Add(mixFile);
                }
                foreach (var dir in VFS.Instance.AllArchives.OfType <DirArchive>().Select(d => d.Directory).ToList())
                {
                    VFS.Instance.ScanMixDir(dir, Settings.Engine);
                }

                var map = new Map {
                    IgnoreLighting  = Settings.IgnoreLighting,
                    StartPosMarking = Settings.StartPositionMarking,
                    MarkOreFields   = Settings.MarkOreFields
                };

                if (!map.Initialize(mapFile, Settings.Engine))
                {
                    Logger.Error("Could not successfully load this map. Try specifying the engine type manually.");
                    return(1);
                }

                if (!map.LoadTheater())
                {
                    Logger.Error("Could not successfully load all required components for this map. Aborting.");
                    return(1);
                }

                if (Settings.StartPositionMarking == StartPositionMarking.Tiled)
                {
                    map.MarkTiledStartPositions();
                }

                if (Settings.MarkOreFields)
                {
                    map.MarkOreAndGems();
                }

                map.Draw();

#if DEBUG
                // ====================================================================================
                using (var form = new DebugDrawingSurfaceWindow(map.GetDrawingSurface(), map.GetTiles(), map.GetTheater(), map)) {
                    form.RequestTileEvaluate += map.DebugDrawTile; form.ShowDialog();
                }
                // ====================================================================================
#endif

                if (Settings.StartPositionMarking == StartPositionMarking.Squared)
                {
                    map.DrawSquaredStartPositions();
                }

                if (Settings.OutputFile == "")
                {
                    Settings.OutputFile = DetermineMapName(mapFile, Settings.Engine);
                }

                if (Settings.OutputDir == "")
                {
                    Settings.OutputDir = Path.GetDirectoryName(Settings.InputFile);
                }

                // free up as much memory as possible before saving the large images
                Rectangle      saveRect = map.GetSizePixels(Settings.SizeMode);
                DrawingSurface ds       = map.GetDrawingSurface();
                // if we don't need this data anymore, we can try to save some memory
                if (!Settings.GeneratePreviewPack)
                {
                    ds.FreeNonBitmap();
                    map.FreeUseless();
                    GC.Collect();
                }

                if (Settings.SaveJPEG)
                {
                    ds.SaveJPEG(Path.Combine(Settings.OutputDir, Settings.OutputFile + ".jpg"), Settings.JPEGCompression, saveRect);
                }

                if (Settings.SavePNG)
                {
                    ds.SavePNG(Path.Combine(Settings.OutputDir, Settings.OutputFile + ".png"), Settings.PNGQuality, saveRect);
                }

                Regex reThumb = new Regex(@"(\+)?\((\d+),(\d+)\)");
                var   match   = reThumb.Match(Settings.ThumbnailSettings);
                if (match.Success)
                {
                    Size dimensions = new Size(
                        int.Parse(match.Groups[2].Captures[0].Value),
                        int.Parse(match.Groups[3].Captures[0].Value));
                    var cutRect = map.GetSizePixels(Settings.SizeMode);

                    if (match.Groups[1].Captures[0].Value == "+")
                    {
                        // + means maintain aspect ratio
                        double aspectRatio = cutRect.Width / (double)cutRect.Height;
                        if (dimensions.Width / (double)dimensions.Height > aspectRatio)
                        {
                            dimensions.Height = (int)(dimensions.Width / aspectRatio);
                        }
                        else
                        {
                            dimensions.Width = (int)(dimensions.Height / aspectRatio);
                        }
                    }
                    Logger.Info("Saving thumbnail with dimensions {0}x{1}", dimensions.Width, dimensions.Height);
                    ds.SaveThumb(dimensions, cutRect, Path.Combine(Settings.OutputDir, "thumb_" + Settings.OutputFile + ".jpg"));
                }

                if (Settings.GeneratePreviewPack)
                {
                    if (mapFile.BaseStream is MixFile)
                    {
                        Logger.Error("Cannot inject thumbnail into an archive (.mmx/.yro/.mix)!");
                    }
                    else
                    {
                        map.GeneratePreviewPack(Settings.OmitPreviewPackMarkers, Settings.SizeMode, mapFile);
                        Logger.Info("Saving map");
                        mapFile.Save(Settings.InputFile);
                    }
                }
            }
            catch (Exception exc) {
                Logger.Error(string.Format("An unknown fatal exception occured: {0}", exc), exc);
#if DEBUG
                throw;
#else
                return(1);
#endif
            }

            LogManager.Configuration = null;             // required for mono release to flush possible targets
            return(0);
        }
        public EngineResult Execute()
        {
            try {
                _logger.Info("Initializing virtual filesystem");

                var         mapStream = File.Open(Settings.InputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                VirtualFile vmapFile;
                var         mixMap = new MixFile(mapStream, Settings.InputFile, 0, mapStream.Length, false, false);
                if (mixMap.IsValid())                   // input max is a mix
                {
                    var mapArchive = new MixFile(mapStream, Path.GetFileName(Settings.InputFile), true);
                    // grab the largest file in the archive
                    var mixEntry = mapArchive.Index.OrderByDescending(me => me.Value.Length).First();
                    vmapFile = mapArchive.OpenFile(mixEntry.Key);
                }
                else
                {
                    vmapFile = new VirtualFile(mapStream, Path.GetFileName(Settings.InputFile), true);
                }
                var mapFile = new MapFile(vmapFile, Path.GetFileName(Settings.InputFile));

                if (!string.IsNullOrEmpty(Settings.ModConfig))
                {
                    if (File.Exists(Settings.ModConfig))
                    {
                        ModConfig cfg;
                        try {
                            using (FileStream f = File.OpenRead(Settings.ModConfig))
                                cfg = ModConfig.Deserialize(f);
                            ModConfig.ActiveConfig = cfg;
                            if (Settings.Engine != EngineType.AutoDetect)
                            {
                                if (Settings.Engine != cfg.Engine)
                                {
                                    _logger.Warn("Provided engine override does not match mod config.");
                                }
                            }
                            else
                            {
                                Settings.Engine = ModConfig.ActiveConfig.Engine;
                            }
                        }
                        catch (IOException) {
                            _logger.Fatal("IOException while loading mod config");
                        }
                        catch (XmlException) {
                            _logger.Fatal("XmlException while loading mod config");
                        }
                        catch (SerializationException) {
                            _logger.Fatal("Serialization exception while loading mod config");
                        }
                    }
                    else
                    {
                        _logger.Fatal("Invalid mod config file specified");
                    }
                }

                if (Settings.Engine == EngineType.AutoDetect)
                {
                    Settings.Engine = EngineDetector.DetectEngineType(mapFile);
                    _logger.Info("Engine autodetect result: {0}", Settings.Engine);
                }

                // ---------------------------------------------------------------
                // Code to organize moving of maps in a directory for themselves

                /*
                 * string mapName = DetermineMapName(mapFile, Settings.Engine);
                 * string ndir = Path.Combine(Path.GetDirectoryName(Settings.InputFile), mapName);
                 * if (!Directory.Exists(ndir)) Directory.CreateDirectory(ndir);
                 * mapFile.Close();
                 * mapFile.Dispose();
                 * File.Move(Settings.InputFile, Path.Combine(ndir, Path.GetFileName(mapFile.FileName)));
                 * return 0;*/
                // ---------------------------------------------------------------

                // enginetype is now definitive, load mod config
                if (ModConfig.ActiveConfig == null)
                {
                    ModConfig.LoadDefaultConfig(Settings.Engine);
                }

                // first add the dirs, then load the extra mixes, then scan the dirs
                foreach (string modDir in ModConfig.ActiveConfig.Directories)
                {
                    VFS.Add(modDir);
                }

                // add mixdir to VFS (if it's not included in the mod config)
                if (!ModConfig.ActiveConfig.Directories.Any())
                {
                    string mixDir = VFS.DetermineMixDir(Settings.MixFilesDirectory, Settings.Engine);
                    VFS.Add(mixDir);
                }
                foreach (string mixFile in ModConfig.ActiveConfig.ExtraMixes)
                {
                    VFS.Add(mixFile);
                }

                VFS.Instance.LoadMixes(Settings.Engine);

                double markerStartSize = 4.0;
                if (double.TryParse(Settings.MarkStartSize, NumberStyles.Number, CultureInfo.CreateSpecificCulture("en-US"), out markerStartSize))
                {
                    markerStartSize = Math.Abs(markerStartSize);
                }

                var map = new Map.Map {
                    IgnoreLighting  = Settings.IgnoreLighting,
                    StartPosMarking = Settings.StartPositionMarking,
                    StartMarkerSize = markerStartSize,
                    MarkOreFields   = Settings.MarkOreFields
                };

                if (!map.Initialize(mapFile, Settings.Engine, ModConfig.ActiveConfig.CustomRulesIniFiles, ModConfig.ActiveConfig.CustomArtIniFiles))
                {
                    _logger.Error("Could not successfully load this map. Try specifying the engine type manually.");
                    return(EngineResult.LoadRulesFailed);
                }

                if (!map.LoadTheater())
                {
                    _logger.Error("Could not successfully load all required components for this map. Aborting.");
                    return(EngineResult.LoadTheaterFailed);
                }

                if (Settings.MarkStartPos && Settings.StartPositionMarking == StartPositionMarking.Tiled)
                {
                    map.MarkTiledStartPositions();
                }

                if (Settings.MarkOreFields)
                {
                    map.MarkOreAndGems();
                }

                if ((Settings.GeneratePreviewPack || Settings.FixupTiles || Settings.FixOverlays || Settings.CompressTiles) && Settings.Backup)
                {
                    if (mapFile.BaseStream is MixFile)
                    {
                        _logger.Error("Cannot generate a map file backup into an archive (.mmx/.yro/.mix)!");
                    }
                    else
                    {
                        try {
                            string timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
                            string fileInput = Path.Combine(Path.GetDirectoryName(Settings.InputFile), Path.GetFileName(Settings.InputFile));
                            fileInput = fileInput.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                            string fileInputNoExtn = Path.Combine(Path.GetDirectoryName(Settings.InputFile), Path.GetFileNameWithoutExtension(Settings.InputFile));
                            fileInputNoExtn = fileInputNoExtn.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                            string fileBackup = fileInputNoExtn + "_" + timestamp + ".bkp";
                            File.Copy(fileInput, fileBackup, true);
                            _logger.Info("Creating map backup: " + fileBackup);
                        }
                        catch (Exception) {
                            _logger.Error("Unable to generate a map file backup!");
                        }
                    }
                }

                if (Settings.FixupTiles)
                {
                    map.FixupTileLayer();
                }

                map.Draw();

                if (Settings.MarkIceGrowth)
                {
                    map.MarkIceGrowth();
                }

                if (Settings.TunnelPaths)
                {
                    map.PlotTunnels(Settings.TunnelPosition);
                }

                if (Settings.MarkStartPos && (Settings.StartPositionMarking == StartPositionMarking.Squared ||
                                              Settings.StartPositionMarking == StartPositionMarking.Circled ||
                                              Settings.StartPositionMarking == StartPositionMarking.Diamond ||
                                              Settings.StartPositionMarking == StartPositionMarking.Ellipsed ||
                                              Settings.StartPositionMarking == StartPositionMarking.Starred))
                {
                    map.DrawStartPositions();
                }

                if (Settings.DiagnosticWindow)
                {
                    using (var form = new DebugDrawingSurfaceWindow(map.GetDrawingSurface(), map.GetTiles(), map.GetTheater(), map)) {
                        form.RequestTileEvaluate += map.DebugDrawTile; form.ShowDialog();
                    }
                }

                if (Settings.OutputFile == "")
                {
                    Settings.OutputFile = DetermineMapName(mapFile, Settings.Engine);
                }

                if (Settings.OutputDir == "")
                {
                    Settings.OutputDir = Path.GetDirectoryName(Settings.InputFile);
                }

                // free up as much memory as possible before saving the large images
                Rectangle      saveRect = map.GetSizePixels(Settings.SizeMode);
                DrawingSurface ds       = map.GetDrawingSurface();
                saveRect.Intersect(new Rectangle(0, 0, ds.Width, ds.Height));
                // if we don't need this data anymore, we can try to save some memory
                if (!Settings.GeneratePreviewPack)
                {
                    ds.FreeNonBitmap();
                    map.FreeUseless();
                    GC.Collect();
                }

                if (Settings.SaveJPEG)
                {
                    ds.SaveJPEG(Path.Combine(Settings.OutputDir, Settings.OutputFile + ".jpg"), Settings.JPEGCompression, saveRect);
                }

                if (Settings.SavePNG)
                {
                    ds.SavePNG(Path.Combine(Settings.OutputDir, Settings.OutputFile + ".png"), Settings.PNGQuality, saveRect);
                }

                Regex reThumb = new Regex(@"(\+|)?\((\d+),(\d+)\)");
                var   match   = reThumb.Match(Settings.ThumbnailConfig);
                if (match.Success)
                {
                    Size dimensions = new Size(
                        int.Parse(match.Groups[2].Captures[0].Value),
                        int.Parse(match.Groups[3].Captures[0].Value));
                    var cutRect = map.GetSizePixels(Settings.SizeMode);

                    if (match.Groups[1].Captures[0].Value == "+")
                    {
                        // + means maintain aspect ratio

                        if (dimensions.Width > 0 && dimensions.Height > 0)
                        {
                            float scaleHeight = (float)dimensions.Height / (float)cutRect.Height;
                            float scaleWidth  = (float)dimensions.Width / (float)cutRect.Width;
                            float scale       = Math.Min(scaleHeight, scaleWidth);
                            dimensions.Width  = Math.Max((int)(cutRect.Width * scale), 1);
                            dimensions.Height = Math.Max((int)(cutRect.Height * scale), 1);
                        }
                        else
                        {
                            double aspectRatio = cutRect.Width / (double)cutRect.Height;
                            if (dimensions.Width / (double)dimensions.Height > aspectRatio)
                            {
                                dimensions.Height = (int)(dimensions.Width / aspectRatio);
                            }
                            else
                            {
                                dimensions.Width = (int)(dimensions.Height * aspectRatio);
                            }
                        }
                    }
                    _logger.Info("Saving thumbnail with dimensions {0}x{1}", dimensions.Width, dimensions.Height);

                    if (!Settings.SavePNGThumbnails)
                    {
                        ds.SaveThumb(dimensions, cutRect, Path.Combine(Settings.OutputDir, "thumb_" + Settings.OutputFile + ".jpg"));
                    }
                    else
                    {
                        ds.SaveThumb(dimensions, cutRect, Path.Combine(Settings.OutputDir, "thumb_" + Settings.OutputFile + ".png"), true);
                    }
                }

                if (Settings.GeneratePreviewPack || Settings.FixupTiles || Settings.FixOverlays || Settings.CompressTiles)
                {
                    if (mapFile.BaseStream is MixFile)
                    {
                        _logger.Error("Cannot fix tile layer or inject thumbnail into an archive (.mmx/.yro/.mix)!");
                    }
                    else
                    {
                        if (Settings.GeneratePreviewPack)
                        {
                            map.GeneratePreviewPack(Settings.PreviewMarkers, Settings.SizeMode, mapFile, Settings.FixPreviewDimensions);
                        }

                        if (Settings.FixOverlays)
                        {
                            map.FixupOverlays();                             // fixing is done earlier, it now creates overlay and its data pack
                        }
                        // Keep this last in tiles manipulation
                        if (Settings.CompressTiles)
                        {
                            map.CompressIsoMapPack5();
                        }

                        _logger.Info("Saving map to " + Settings.InputFile);
                        mapFile.Save(Settings.InputFile);
                    }
                }
            }
            catch (Exception exc) {
                _logger.Error(string.Format("An unknown fatal exception occured: {0}", exc), exc);
#if DEBUG
                throw;
#endif
                return(EngineResult.Exception);
            }
            return(EngineResult.RenderedOk);
        }