Пример #1
0
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = utility.ModData;

            var filename   = args[1];
            var file       = new IniFile(File.Open(args[1], FileMode.Open));
            var basic      = file.GetSection("Basic");
            var mapSection = file.GetSection("Map");
            var tileset    = mapSection.GetValue("Theater", "");
            var iniSize    = mapSection.GetValue("Size", "0, 0, 0, 0").Split(',').Select(int.Parse).ToArray();
            var iniBounds  = mapSection.GetValue("LocalSize", "0, 0, 0, 0").Split(',').Select(int.Parse).ToArray();
            var size       = new Size(iniSize[2], 2 * iniSize[3]);
            var author     = args.Length > 2
                                ? args[2]
                                : "Westwood Studios";

            if (!utility.ModData.DefaultTerrainInfo.TryGetValue(tileset, out var terrainInfo))
            {
                throw new InvalidDataException("Unknown tileset {0}".F(tileset));
            }

            var map = new Map(Game.ModData, terrainInfo, size.Width, size.Height)
            {
                Title       = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename)),
                Author      = author,
                Bounds      = new Rectangle(iniBounds[0], iniBounds[1], iniBounds[2], 2 * iniBounds[3] + 2 * iniBounds[1]),
                RequiresMod = utility.ModData.Manifest.Id
            };

            var fullSize = new int2(iniSize[2], iniSize[3]);

            ReadTiles(map, file, fullSize);
            ReadActors(map, file, "Structures", fullSize);
            ReadActors(map, file, "Units", fullSize);
            ReadActors(map, file, "Infantry", fullSize);
            ReadTerrainActors(map, file, fullSize);
            ReadWaypoints(map, file, fullSize);
            ReadOverlay(map, file, fullSize);
            ReadLighting(map, file);
            ReadLamps(map, file);

            var spawnCount = map.ActorDefinitions.Count(n => n.Value.Value == "mpspawn");
            var mapPlayers = new MapPlayers(map.Rules, spawnCount);

            map.PlayerDefinitions = mapPlayers.ToMiniYaml();

            var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";

            map.Save(ZipFileLoader.Create(dest));
            Console.WriteLine(dest + " saved.");
        }
Пример #2
0
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = utility.ModData;

            var map = MapImporter.Import(args[1], utility.ModData.Manifest.Id, args[2]);

            if (map == null)
            {
                return;
            }

            var filename = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";

            map.Save(ZipFileLoader.Create(filename));
            Console.WriteLine(filename + " saved.");
        }
Пример #3
0
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = utility.ModData;

            var rules = Ruleset.LoadDefaultsForTileSet(utility.ModData, "ARRAKIS");
            var map   = D2kMapImporter.Import(args[1], utility.ModData.Manifest.Id, args[2], rules);

            if (map == null)
            {
                return;
            }

            var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";

            map.Save(ZipFileLoader.Create(dest));
            Console.WriteLine(dest + " saved.");
        }
Пример #4
0
        public static int ImportOriginalMaps(ModData modData, Dictionary <string, string> info)
        {
            string[] files = { };
            var      unpackedFilesCount = 0;

            if (info.ContainsKey("OriginalMaps"))
            {
                files = info["OriginalMaps"].Split(',');
            }

            if (files.Length == 0)
            {
                return(0);
            }

            var path = Platform.ResolvePath(Platform.SupportDir);

            var contentPath = Path.Combine(path, "maps");

            if (!Directory.Exists(contentPath))
            {
                Directory.CreateDirectory(contentPath);
            }

            var d2Path = Path.Combine(contentPath, "d2");

            if (!Directory.Exists(d2Path))
            {
                Directory.CreateDirectory(d2Path);
            }

            var originalPath = Path.Combine(d2Path, "original");

            if (!Directory.Exists(originalPath))
            {
                Directory.CreateDirectory(originalPath);
            }

            foreach (var s in files)
            {
                var filename    = s.Trim();
                var mapFilename = Path.Combine(originalPath, Path.GetFileNameWithoutExtension(filename) + ".oramap");
                try
                {
                    if (!File.Exists(mapFilename))
                    {
                        if (modData.DefaultFileSystem.Exists(filename))
                        {
                            var rules = Ruleset.LoadDefaults(modData);
                            var map   = D2MapImporter.Import(filename, modData.Manifest.Id, "arrakis2", rules);

                            if (map != null)
                            {
                                map.Save(ZipFileLoader.Create(mapFilename));
                                Console.WriteLine("Original map {0} saved to {1}", filename, mapFilename);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }

            return(unpackedFilesCount);
        }
Пример #5
0
        public SaveMapLogic(Widget widget, ModData modData, Action <string> onSave, Action onExit,
                            Map map, List <MiniYamlNode> playerDefinitions, List <MiniYamlNode> actorDefinitions)
        {
            var title = widget.Get <TextFieldWidget>("TITLE");

            title.Text = map.Title;

            var author = widget.Get <TextFieldWidget>("AUTHOR");

            author.Text = map.Author;

            var visibilityPanel   = Ui.LoadWidget("MAP_SAVE_VISIBILITY_PANEL", null, new WidgetArgs());
            var visOptionTemplate = visibilityPanel.Get <CheckboxWidget>("VISIBILITY_TEMPLATE");

            visibilityPanel.RemoveChildren();

            foreach (MapVisibility visibilityOption in Enum.GetValues(typeof(MapVisibility)))
            {
                // To prevent users from breaking the game only show the 'Shellmap' option when it is already set.
                if (visibilityOption == MapVisibility.Shellmap && !map.Visibility.HasFlag(visibilityOption))
                {
                    continue;
                }

                var checkbox = (CheckboxWidget)visOptionTemplate.Clone();
                checkbox.GetText   = () => visibilityOption.ToString();
                checkbox.IsChecked = () => map.Visibility.HasFlag(visibilityOption);
                checkbox.OnClick   = () => map.Visibility ^= visibilityOption;
                visibilityPanel.AddChild(checkbox);
            }

            var visibilityDropdown = widget.Get <DropDownButtonWidget>("VISIBILITY_DROPDOWN");

            visibilityDropdown.OnMouseDown = _ =>
            {
                visibilityDropdown.RemovePanel();
                visibilityDropdown.AttachPanel(visibilityPanel);
            };

            var           writableDirectories = new List <SaveDirectory>();
            SaveDirectory selectedDirectory   = null;

            var directoryDropdown = widget.Get <DropDownButtonWidget>("DIRECTORY_DROPDOWN");
            {
                Func <SaveDirectory, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
                {
                    var item = ScrollItemWidget.Setup(template,
                                                      () => selectedDirectory == option,
                                                      () => selectedDirectory = option);
                    item.Get <LabelWidget>("LABEL").GetText = () => option.DisplayName;
                    return(item);
                };

                foreach (var kv in modData.MapCache.MapLocations)
                {
                    var folder = kv.Key as Folder;
                    if (folder == null)
                    {
                        continue;
                    }

                    try
                    {
                        using (var fs = File.Create(Path.Combine(folder.Name, ".testwritable"), 1, FileOptions.DeleteOnClose))
                        {
                            // Do nothing: we just want to test whether we can create the file
                        }

                        writableDirectories.Add(new SaveDirectory(folder, kv.Value.ToString(), kv.Value));
                    }
                    catch
                    {
                        // Directory is not writable
                    }
                }

                if (map.Package != null)
                {
                    selectedDirectory = writableDirectories.FirstOrDefault(k => k.Folder.Contains(map.Package.Name));
                    if (selectedDirectory == null)
                    {
                        selectedDirectory = writableDirectories.FirstOrDefault(k => Directory.GetDirectories(k.Folder.Name).Any(f => f.Contains(map.Package.Name)));
                    }
                }

                // Prioritize MapClassification.User directories over system directories
                if (selectedDirectory == null)
                {
                    selectedDirectory = writableDirectories.OrderByDescending(kv => kv.Classification).First();
                }

                directoryDropdown.GetText = () => selectedDirectory?.DisplayName ?? "";
                directoryDropdown.OnClick = () =>
                                            directoryDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, writableDirectories, setupItem);
            }

            var mapIsUnpacked = map.Package != null && map.Package is Folder;

            var filename = widget.Get <TextFieldWidget>("FILENAME");

            filename.Text = map.Package == null ? "" : mapIsUnpacked?Path.GetFileName(map.Package.Name) : Path.GetFileNameWithoutExtension(map.Package.Name);

            var fileType = mapIsUnpacked ? MapFileType.Unpacked : MapFileType.OraMap;

            var fileTypes = new Dictionary <MapFileType, MapFileTypeInfo>()
            {
                { MapFileType.OraMap, new MapFileTypeInfo {
                      Extension = ".oramap", UiLabel = ".oramap"
                  } },
                { MapFileType.Unpacked, new MapFileTypeInfo {
                      Extension = "", UiLabel = "(unpacked)"
                  } }
            };

            var typeDropdown = widget.Get <DropDownButtonWidget>("TYPE_DROPDOWN");
            {
                Func <KeyValuePair <MapFileType, MapFileTypeInfo>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
                {
                    var item = ScrollItemWidget.Setup(template,
                                                      () => fileType == option.Key,
                                                      () => { typeDropdown.Text = option.Value.UiLabel; fileType = option.Key; });
                    item.Get <LabelWidget>("LABEL").GetText = () => option.Value.UiLabel;
                    return(item);
                };

                typeDropdown.Text = fileTypes[fileType].UiLabel;

                typeDropdown.OnClick = () =>
                                       typeDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, fileTypes, setupItem);
            }

            var close = widget.Get <ButtonWidget>("BACK_BUTTON");

            close.OnClick = () => { Ui.CloseWindow(); onExit(); };

            var save = widget.Get <ButtonWidget>("SAVE_BUTTON");

            save.OnClick = () =>
            {
                if (string.IsNullOrEmpty(filename.Text))
                {
                    return;
                }

                map.Title  = title.Text;
                map.Author = author.Text;

                if (actorDefinitions != null)
                {
                    map.ActorDefinitions = actorDefinitions;
                }

                if (playerDefinitions != null)
                {
                    map.PlayerDefinitions = playerDefinitions;
                }

                map.RequiresMod = modData.Manifest.Id;

                var combinedPath = Platform.ResolvePath(Path.Combine(selectedDirectory.Folder.Name, filename.Text + fileTypes[fileType].Extension));

                try
                {
                    if (!(map.Package is IReadWritePackage package) || package.Name != combinedPath)
                    {
                        selectedDirectory.Folder.Delete(combinedPath);
                        if (fileType == MapFileType.OraMap)
                        {
                            package = ZipFileLoader.Create(combinedPath);
                        }
                        else
                        {
                            package = new Folder(combinedPath);
                        }
                    }

                    map.Save(package);

                    Console.WriteLine("Saved current map at {0}", combinedPath);
                    Ui.CloseWindow();

                    onSave(map.Uid);
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed to save map at {0}: {1}", combinedPath, e.Message);
                    Log.Write("debug", "{0}", e.StackTrace);

                    ConfirmationDialogs.ButtonPrompt(
                        title: "Failed to save map",
                        text: "See debug.log for details.",
                        onConfirm: () => { },
                        confirmText: "OK");
                }
            };
        }
Пример #6
0
        protected void Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = ModData = utility.ModData;

            var filename = args[1];

            using (var stream = File.OpenRead(filename))
            {
                var file  = new IniFile(stream);
                var basic = file.GetSection("Basic");

                var player = basic.GetValue("Player", string.Empty);
                if (!string.IsNullOrEmpty(player))
                {
                    singlePlayer = !player.StartsWith("Multi");
                }

                var mapSection = file.GetSection("Map");

                var format = GetMapFormatVersion(basic);
                ValidateMapFormat(format);

                // The original game isn't case sensitive, but we are.
                var tileset = GetTileset(mapSection).ToUpperInvariant();
                if (!ModData.DefaultTileSets.ContainsKey(tileset))
                {
                    throw new InvalidDataException("Unknown tileset {0}".F(tileset));
                }

                Map = new Map(ModData, ModData.DefaultTileSets[tileset], MapSize, MapSize)
                {
                    Title  = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename)),
                    Author = "Westwood Studios",
                };

                Map.RequiresMod = ModData.Manifest.Id;

                SetBounds(Map, mapSection);

                ReadPacks(file, filename);
                ReadTrees(file);

                LoadVideos(file, "BASIC");
                LoadBriefing(file);

                ReadActors(file);

                LoadSmudges(file, "SMUDGE");

                var waypoints = file.GetSection("Waypoints");
                LoadWaypoints(waypoints);

                // Create default player definitions only if there are no players to import
                MapPlayers = new MapPlayers(Map.Rules, Players.Count == 0 ? spawnCount : 0);
                foreach (var p in Players)
                {
                    LoadPlayer(file, p);
                }

                Map.PlayerDefinitions = MapPlayers.ToMiniYaml();
            }

            Map.FixOpenAreas();

            var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";

            Map.Save(ZipFileLoader.Create(dest));
            Console.WriteLine(dest + " saved.");
        }
Пример #7
0
        protected void Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = ModData = utility.ModData;

            var filename = args[1];
            var flag     = args[2];

            if (string.IsNullOrWhiteSpace(flag))
            {
                flag = "VH";
            }

            bool flipHorizontal = flag.Contains("H");
            bool flipVertical   = flag.Contains("V");

            MirrorType mirrorType = MirrorType.Horizontal;

            if (flipVertical)
            {
                mirrorType = MirrorType.Vertical;
            }
            if (flipHorizontal && flipVertical)
            {
                mirrorType = MirrorType.HorizontalAndVertical;
            }

            var targetPath = "..\\mods\\dr\\maps";

            var package = new Folder(targetPath).OpenPackage(filename, ModData.ModFiles);

            if (package == null)
            {
                Console.WriteLine("Couldn't find map file: " + filename);
                return;
            }

            Map = new Map(ModData, package);
            var size = Map.MapSize;

            switch (mirrorType)
            {
            case MirrorType.Horizontal:
                size = size.WithX(size.X / 2);
                break;

            case MirrorType.Vertical:
                size = size.WithY(size.Y / 2);
                break;

            case MirrorType.HorizontalAndVertical:
                size = size / 2;
                break;
            }

            // Tiles
            for (int x = 0; x < size.X; x++)
            {
                for (int y = 0; y < size.Y; y++)
                {
                    var pos           = new CPos(x, y);
                    var transformTile = new TileTransform()
                    {
                        Tile       = Map.Tiles[pos],
                        MirrorType = mirrorType,
                        Position   = pos
                    };

                    foreach (var tt in transformTile.GetTransforms(Map))
                    {
                        var newPos = tt.Position;
                        Map.Tiles[newPos] = tt.Tile;
                    }
                }
            }

            // Actors
            actorIndex = GetHighestActorIndex();
            int multiCount = 0;

            var actorDefs    = new List <ActorReference>();
            var removeActors = new List <MiniYamlNode>();

            foreach (var a in Map.ActorDefinitions)
            {
                var existing = new ActorReference(a.Value.Value, a.Value.ToDictionary());
                var pos      = existing.GetOrDefault <LocationInit>().Value;
                var owner    = existing.Get <OwnerInit>();

                if (pos.X < 0 || pos.X >= size.X ||
                    pos.Y < 0 || pos.Y >= size.Y)
                {
                    removeActors.Add(a);
                    continue;
                }

                var actor = new ActorTransform()
                {
                    Actor      = existing,
                    Position   = pos,
                    MirrorType = mirrorType,
                };

                if (actor.Actor.Type == "mpspawn")
                {
                    multiCount++;
                }

                foreach (var at in actor.GetTransforms(Map))
                {
                    var ar = new ActorReference(actor.Actor.Type)
                    {
                        new LocationInit(at.Position),
                        owner
                    };

                    actorDefs.Add(ar);

                    if (at.Actor.Type == "mpspawn")
                    {
                        multiCount++;
                    }
                }
            }

            foreach (var a in actorDefs)
            {
                Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + ++actorIndex, a.Save()));
            }

            foreach (var a in removeActors)
            {
                Map.ActorDefinitions.Remove(a);
            }

            if (multiCount > 0)
            {
                var mapPlayers = new MapPlayers(Map.Rules, multiCount);
                Map.PlayerDefinitions = mapPlayers.ToMiniYaml();
            }

            // Resources
            for (int x = 0; x < size.X; x++)
            {
                for (int y = 0; y < size.Y; y++)
                {
                    var pos      = new CPos(x, y);
                    var resource = new ResourceTransform()
                    {
                        Tile       = Map.Resources[pos],
                        MirrorType = mirrorType,
                        Position   = pos
                    };

                    foreach (var rt in resource.GetTransforms(Map))
                    {
                        var newPos = rt.Position;
                        Map.Resources[newPos] = rt.Tile;
                    }
                }
            }

            var dest = Path.Combine(targetPath, Path.GetFileNameWithoutExtension(filename) + ".oramap");

            Map.Save(ZipFileLoader.Create(dest));
            Console.WriteLine(dest + " saved.");
        }
        protected void Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = ModData = utility.ModData;

            var filename = args[1];

            using (var stream = File.OpenRead(filename))
            {
                var headerString = stream.ReadASCII(4);
                var headerVers   = stream.ReadInt32();

                if (headerString != "MAP_")
                {
                    throw new ArgumentException("Map file did not start with MAP_");
                }

                if (headerVers < 0x300)
                {
                    throw new ArgumentException("Map version was too low.");
                }

                var width  = stream.ReadInt32();
                var height = stream.ReadInt32();
                stream.ReadInt32();                 // Tileset num???
                var tilesetName = "BARREN";

                filename = filename.ToLowerInvariant();

                var scnFilename = filename.Replace(".map", ".scn");
                using (var scn = File.OpenRead(scnFilename))
                {
                    var scnFile = new ScnFile(scn);
                    foreach (var scnSection in scnFile.Entries)
                    {
                        if (scnSection.Name != "SetDefaultTerrain")
                        {
                            continue;
                        }

                        tilesetName = scnSection.ValuesStr.ToUpperInvariant();
                    }
                }

                Map = new Map(ModData, ModData.DefaultTileSets[tilesetName], width + 2, height + 2)
                {
                    Title  = Path.GetFileNameWithoutExtension(filename),
                    Author = "Dark Reign",
                };

                Map.RequiresMod = ModData.Manifest.Id;

                SetBounds(Map, width + 2, height + 2);

                var byte1Hash           = new HashSet <byte>();
                var byte2Hash           = new HashSet <byte>();
                var byte3Hash           = new HashSet <byte>();
                var byte4Hash           = new HashSet <byte>();
                var byte5Hash           = new HashSet <byte>();
                var byte6Hash           = new HashSet <byte>();
                var unknownTileTypeHash = new HashSet <int>();

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        var byte1 = stream.ReadUInt8();                         // Tile type 0-63, with art variations repeated 1-4
                        var byte2 = stream.ReadUInt8();                         // Which art variation to use. 0 = 1-4, 1 = 5-8
                        var byte3 = stream.ReadUInt8();                         // Base elevation, defaults to 2.
                        var byte4 = stream.ReadUInt8();                         // Unknown, defaults to 36. Seems to be elevation related.
                        var byte5 = stream.ReadUInt8();                         // Unknown, defaults to 73. Seems to be elevation related.
                        var byte6 = stream.ReadUInt8();                         // Unknown, defaults to 146. Seems to be elevation related.

                        if (!byte1Hash.Contains(byte1))
                        {
                            byte1Hash.Add(byte1);
                        }
                        if (!byte2Hash.Contains(byte2))
                        {
                            byte2Hash.Add(byte2);
                        }
                        if (!byte3Hash.Contains(byte3))
                        {
                            byte3Hash.Add(byte3);
                        }
                        if (!byte4Hash.Contains(byte4))
                        {
                            byte4Hash.Add(byte4);
                        }
                        if (!byte5Hash.Contains(byte5))
                        {
                            byte5Hash.Add(byte5);
                        }
                        if (!byte6Hash.Contains(byte6))
                        {
                            byte6Hash.Add(byte6);
                        }

                        var  subindex  = (byte)(byte1 / 64);
                        byte variation = (byte)(subindex * (byte2 + 1));
                        int  tileType  = byte1 % 64;

                        if (tileType >= 16)
                        {
                            unknownTileTypeHash.Add(tileType);
                            tileType = 1;                             // TODO: Handle edge sprites
                        }

                        Map.Tiles[new CPos(x + 1, y + 1)] = new TerrainTile((ushort)tileType, variation);                         // types[i, j], byte1
                    }
                }

                // What's after the tiles? Water/Taelon?
                stream.ReadInt32();                 // Always one
                stream.ReadInt32();                 // Always 256
                int length = stream.ReadInt32();    // Byte length of remaining data

                byte1Hash = new HashSet <byte>();
                var byteList = new List <byte>();
                for (int i = 0; i < length; i++)
                {
                    var byte1 = stream.ReadUInt8();
                    if (!byte1Hash.Contains(byte1))
                    {
                        byte1Hash.Add(byte1);
                    }

                    byteList.Add(byte1);
                }

                using (var scn = File.OpenRead(scnFilename))
                {
                    var scnFile = new ScnFile(scn);

                    MapPlayers = new MapPlayers(Map.Rules, 0);
                    SetMapPlayers(scnFile, Players, MapPlayers);

                    // Place start locations
                    int i = 0;
                    foreach (var scnSection in scnFile.Entries)
                    {
                        if (scnSection.Name != "SetStartLocation")
                        {
                            continue;
                        }

                        int divisor = 24;
                        int x       = Convert.ToInt32(scnSection.Values[0]) / divisor;
                        int y       = Convert.ToInt32(scnSection.Values[1]) / divisor;
                        if (x != 0 && y != 0)
                        {
                            var ar = new ActorReference("mpspawn")
                            {
                                new LocationInit(new CPos(x + 1, y + 1)),
                                new OwnerInit("Neutral")
                            };

                            Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + i++, ar.Save()));
                        }
                    }

                    // Parse map thingies
                    foreach (var scnSection in scnFile.Entries)
                    {
                        if (scnSection.Name != "AddThingAt")
                        {
                            continue;
                        }

                        string type = scnSection.Values[1];
                        int    x    = Convert.ToInt32(scnSection.Values[2]);
                        int    y    = Convert.ToInt32(scnSection.Values[3]);

                        var matchingActor = string.Empty;

                        if (thingNames.ContainsKey(type))
                        {
                            matchingActor = thingNames[type];
                        }
                        else if (!knownUnknownThings.Contains(type))
                        {
                            throw new Exception("Unknown thing name: " + type);
                        }

                        if (x >= 0 && y >= 0 && !string.IsNullOrEmpty(matchingActor))
                        {
                            var ar = new ActorReference(matchingActor)
                            {
                                new LocationInit(new CPos(x + 1, y + 1)),
                                new OwnerInit("Neutral")
                            };

                            Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + i++, ar.Save()));
                        }
                    }

                    int currentTeam = 0;

                    if (!skipActors)
                    {
                        // Units
                        foreach (var scnSection in scnFile.Entries)
                        {
                            if (scnSection.Name == "SetDefaultTeam")
                            {
                                currentTeam = Convert.ToInt32(scnSection.ValuesStr);
                                continue;
                            }

                            if (scnSection.Name != "PutUnitAt")
                            {
                                continue;
                            }

                            int playerIndex = GetMatchingPlayerIndex(currentTeam);                             // to skip creeps and neutral if necessary

                            string type = scnSection.Values[1];
                            int    x    = Convert.ToInt32(scnSection.Values[2]);
                            int    y    = Convert.ToInt32(scnSection.Values[3]);

                            var matchingActor = string.Empty;

                            if (unitNames.ContainsKey(type))
                            {
                                matchingActor = unitNames[type];
                            }
                            else if (!knownUnknownUnits.Contains(type))
                            {
                                throw new Exception("Unknown unit name: " + type);
                            }

                            if (x >= 0 && y >= 0 && !string.IsNullOrEmpty(matchingActor))
                            {
                                var ar = new ActorReference(matchingActor)
                                {
                                    new LocationInit(new CPos(x + 1, y + 1)),
                                    new OwnerInit(MapPlayers.Players.Values.First(p => p.Team == playerIndex).Name)
                                };

                                Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + i++, ar.Save()));
                            }
                        }

                        // Do buildings
                        foreach (var scnSection in scnFile.Entries)
                        {
                            if (scnSection.Name == "SetDefaultTeam")
                            {
                                currentTeam = Convert.ToInt32(scnSection.ValuesStr);
                                continue;
                            }

                            if (scnSection.Name != "AddBuildingAt")
                            {
                                continue;
                            }

                            int playerIndex = GetMatchingPlayerIndex(currentTeam);                             // to skip creeps and neutral if necessary

                            string type = scnSection.Values[1];
                            int    x    = Convert.ToInt32(scnSection.Values[2]);
                            int    y    = Convert.ToInt32(scnSection.Values[3]);

                            var matchingActor = string.Empty;

                            if (buildingNames.ContainsKey(type))
                            {
                                matchingActor = buildingNames[type];
                            }
                            else if (!knownUnknownBuildings.Contains(type))
                            {
                                throw new Exception("Unknown building name: " + type);
                            }

                            var isResource = type == "impww" || type == "impmn";
                            var ownerName  = isResource
                                                                ? "Neutral"
                                                                : MapPlayers.Players.Values.First(p => p.Team == playerIndex).Name;

                            if (isResource == true)
                            {
                                throw new ArgumentException("FART");
                            }

                            if (x >= 0 && y >= 0 && !string.IsNullOrEmpty(matchingActor))
                            {
                                var ar = new ActorReference(matchingActor)
                                {
                                    new LocationInit(new CPos(x + 1, y + 1)),
                                    new OwnerInit(ownerName)
                                };

                                Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + i++, ar.Save()));
                            }
                        }
                    }

                    // Do resources
                    foreach (var scnSection in scnFile.Entries)
                    {
                        if (scnSection.Name != "AddBuildingAt")
                        {
                            continue;
                        }

                        string type = scnSection.Values[1];
                        int    x    = Convert.ToInt32(scnSection.Values[2]);
                        int    y    = Convert.ToInt32(scnSection.Values[3]);

                        var isResource = type == "impww" || type == "impmn";
                        if (!isResource)
                        {
                            continue;
                        }

                        var matchingActor = string.Empty;

                        if (buildingNames.ContainsKey(type))
                        {
                            matchingActor = buildingNames[type];
                        }

                        if (x >= 0 && y >= 0 && !string.IsNullOrEmpty(matchingActor))
                        {
                            var ar = new ActorReference(matchingActor)
                            {
                                new LocationInit(new CPos(x + 1, y + 1)),
                                new OwnerInit("Neutral")
                            };

                            Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + i++, ar.Save()));
                        }
                    }
                }

                // Reset teams var
                foreach (var playersValue in MapPlayers.Players.Values)
                {
                    playersValue.Team = 0;
                }

                Map.PlayerDefinitions = MapPlayers.ToMiniYaml();
            }

            Map.FixOpenAreas();

            var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";

            Map.Save(ZipFileLoader.Create(dest));
            Console.WriteLine(dest + " saved.");
        }
Пример #9
0
        private void Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = modData = utility.ModData;

            var filename = args[1];

            if (!Game.ModData.DefaultFileSystem.Exists(filename))
            {
                throw new IOException($"Couldn't find map {filename} in maps.vol or filesystem.");
            }

            using (var stream = Game.ModData.DefaultFileSystem.Open(filename))
            {
                var tag         = stream.ReadUInt32();         // always 4113
                var unknown     = stream.ReadUInt32();         // always 0
                var lgTileWidth = stream.ReadInt32();
                var tileHeight  = stream.ReadInt32();          // always 64
                var numTileSets = stream.ReadInt32();          // always 512

                // Update map header fields
                // Round height up to nearest power of 2
                var newHeight = tileHeight;
                newHeight -= 1;
                newHeight |= (newHeight >> 1);
                newHeight |= (newHeight >> 2);
                newHeight |= (newHeight >> 4);
                newHeight |= (newHeight >> 8);
                newHeight |= (newHeight >> 16);
                newHeight++;
                var width  = 1 << lgTileWidth;                // Calculate map width
                var height = newHeight;

                map = new Map(modData, modData.DefaultTileSets["default"], width + 2, (int)height + 2)
                {
                    Title       = Path.GetFileNameWithoutExtension(filename),
                    Author      = "OpenOP2",
                    RequiresMod = modData.Manifest.Id,
                };

                var tiles = new List <int>();
                for (var i = 0; i < width * height; i++)
                {
                    var tile = stream.ReadInt32();
                    tiles.Add(tile);
                }

                var clipRect = new ClipRect()
                {
                    X1 = stream.ReadInt32(),
                    Y1 = stream.ReadInt32(),
                    X2 = stream.ReadInt32(),
                    Y2 = stream.ReadInt32(),
                };

                SetBounds(map, width, height);

                // map.SetBounds(new PPos(clipRect.X1, clipRect.Y1), new PPos(width - clipRect.X2, (int)height - clipRect.Y2));
                // map.SetBounds(new PPos(clipRect.X1, clipRect.Y1), new PPos(clipRect.X1 + clipRect.X2, clipRect.Y1 - clipRect.Y2));
                // Read in tileset mappings
                var tileIds             = new List <TileSetInfo>();
                var tilesetStartIndices = new List <uint>();
                var tilesetTileIndex    = 0;
                for (int i = 0; i < numTileSets; i++)
                {
                    var stringLength = stream.ReadInt32();
                    if (stringLength <= 0)
                    {
                        continue;
                    }

                    var tilesetMapping = new TileSetInfo()
                    {
                        TileSetName = stream.ReadASCII(stringLength),
                        NumTiles    = stream.ReadInt32(),
                    };

                    tilesetStartIndices.Add((uint)tilesetTileIndex);
                    tilesetTileIndex += tilesetMapping.NumTiles;

                    tileIds.Add(tilesetMapping);
                }

                var testString = stream.ReadASCII(10);
                if (!testString.StartsWith("TILE SET"))
                {
                    throw new IOException("Couldn't find TILE SET tag.");
                }

                var numMappings = stream.ReadInt32();
                var mappings    = new TileSetMapping[numMappings];
                for (var i = 0; i < numMappings; i++)
                {
                    mappings[i] = new TileSetMapping
                    {
                        TileSetIndex        = stream.ReadInt16(),
                        TileIndex           = stream.ReadInt16(),
                        NumTileReplacements = stream.ReadInt16(),
                        CycleDelay          = stream.ReadInt16(),
                    };
                }

                var numTerrainTypes = stream.ReadInt32();
                var terrains        = new TerrainType[numTerrainTypes];

                stream.Seek(numTerrainTypes * 264, SeekOrigin.Current);

                var checkTag = stream.ReadUInt32();
                if (checkTag != tag)
                {
                    throw new IOException("Format error: Tag did not match header tag.");
                }

                var checkTag2 = stream.ReadInt32();                 // the same all the time?
                var numActors = stream.ReadInt32();                 // I think?

                // TODO: The rest of the tiles
                // Actually place the tiles
                for (var y = 0; y < height; y++)
                {
                    for (var x = 0; x < width; x++)
                    {
                        var tileXUpper = x >> 5;
                        var tileXLower = x & 0x1F;
                        var tileOffset = (((tileXUpper * height) + y) << 5) + tileXLower;
                        var tile       = tiles[tileOffset];

                        var tile2XUpper = tile >> 5;
                        var tile2XLower = tile & 0x1F;

                        // Get the tile mapping index
                        var cellType          = (tile & 0x1F);
                        var tileMappingIndex  = (tile & 0xFFE0) >> 5;
                        var actorMappingIndex = (tile & 0x7FF0000) >> 11;
                        var lava           = (tile & 0x00000001) >> 27;
                        var lavaPossible   = (tile & 0x00000001) >> 28;
                        var expand         = (tile & 0x00000001) >> 29;
                        var microbe        = (tile & 0x00000001) >> 30;
                        var wallOrBuilding = (tile & 0x00000001) >> 31;
                        if (actorMappingIndex != 0 || lavaPossible != 0 || wallOrBuilding != 0)
                        {
                            throw new Exception("Actor mapping was " + actorMappingIndex);
                        }

                        var thisMapping = mappings[tileMappingIndex];
                        var startIndex  = tilesetStartIndices[thisMapping.TileSetIndex];

                        map.Tiles[new CPos(x + 1, y + 1)] = new TerrainTile((ushort)(startIndex + thisMapping.TileIndex), 0);
                    }
                }
            }

            mapPlayers            = new MapPlayers(map.Rules, 0);
            map.PlayerDefinitions = mapPlayers.ToMiniYaml();
            map.FixOpenAreas();

            var dest         = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
            var mapLocations = Game.ModData.Manifest.MapFolders;
            var userMapPath  = mapLocations.First(mapLocation => mapLocation.Value == "User");
            var targetPath   = Path.Combine(Platform.ResolvePath(userMapPath.Key.Substring(1)), dest);

            map.Save(ZipFileLoader.Create(targetPath));

            Console.WriteLine(targetPath + " saved.");
        }