示例#1
0
        private void MenuItemFileOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog open = new OpenFileDialog();

            open.Title  = "Open File";
            open.Filter = "Map File (*.map)|*.map|Level file (*.lvl)|*.lvl";
            if (!String.IsNullOrEmpty(mainController.CurrentWorkingDirectory))
            {
                open.InitialDirectory = mainController.CurrentWorkingDirectory;
            }
            if (open.ShowDialog() == DialogResult.OK)
            {
                if (open.InitialDirectory != mainController.CurrentWorkingDirectory)
                {
                    mainController.CurrentWorkingDirectory = Directory.GetCurrentDirectory();
                }

                var    level = new LevelFile();
                Stream input;
                if ((input = open.OpenFile()) != null)
                {
                    level.Deserialize(input);
                    FileName = open.SafeFileName;

                    input.Close();

                    //Strip duplicated blobs
                    for (int i = 0; i < level.Floors.Count; i++)
                    {
                        var floor = level.Floors[i];
                        if (floor.FileName != null &&
                            floor.FileName.EndsWith(".lvb.blo") == true)
                        {
                            floor.FileName  = null;
                            level.Floors[i] = floor;
                        }
                    }

                    for (int i = 0; i < level.Objects.Count; i++)
                    {
                        var obj = level.Objects[i];
                        if (obj.FileName != null &&
                            obj.FileName.EndsWith(".lvb.blo") == true)
                        {
                            obj.FileName     = null;
                            level.Objects[i] = obj;
                        }
                    }
                }

                mainController.LoadLevel(level);
            }
            open.Dispose();
        }
示例#2
0
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dialog = new OpenFileDialog();

            dialog.Filter = "Infantry Online Level File (*.lvl)|*.lvl";

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                var file = new LevelFile();

                var fileName = dialog.SafeFileName;
                var filePath = dialog.FileName;

                var stream = dialog.OpenFile();

                file.Deserialize(stream);

                // Initialize the tiles and objects.


                // Most tiles will only have a handful of atlas lookups, so rather than going through the whole thing,
                // use a dictionary and make quick work of it.
                Dictionary <string, Tuple <int, int> > atlasLookup = new Dictionary <string, Tuple <int, int> >();

                for (int i = 0; i < file.Width; i++)
                {
                    for (int j = 0; j < file.Height; j++)
                    {
                        // TODO: Deal with this. Why are some maps so bloody large?

                        if (i >= 2048 || j >= 2048)
                        {
                            continue;
                        }

                        // Map across the floor array and into the atlas, because we don't care where the data really comes from.

                        var tile = file.Tiles[j * file.Width + i];

                        var blobName = file.Floors[tile.TerrainLookup].FileName.ToLower().Trim();
                        var cfsName  = file.Floors[tile.TerrainLookup].Id.ToLower().Trim();

                        if (blobName == null)
                        {
                            // Dealing with a shady file. Deal with this later.
                            throw new NotImplementedException("Deal with this later.");
                        }

                        var dictKey = $"{blobName}#{cfsName}";

                        var atlasIndex      = -1;
                        var atlasEntryIndex = -1;

                        if (!atlasLookup.ContainsKey(dictKey))
                        {
                            foreach (var atlas in Renderer.FloorAtlasses)
                            {
                                var foundCfs = atlas.Entries.FirstOrDefault(entry => entry.CfsBitmap.BloFilename == blobName && entry.CfsBitmap.CfsFilename == cfsName);

                                if (foundCfs != null)
                                {
                                    atlasIndex      = Renderer.FloorAtlasses.IndexOf(atlas);
                                    atlasEntryIndex = atlas.Entries.IndexOf(foundCfs);

                                    break;
                                }
                            }

                            atlasLookup[dictKey] = new Tuple <int, int>(atlasIndex, atlasEntryIndex);
                        }
                        else
                        {
                            atlasIndex      = atlasLookup[dictKey].Item1;
                            atlasEntryIndex = atlasLookup[dictKey].Item2;
                        }

                        if (atlasIndex == -1 || atlasEntryIndex == -1)
                        {
                            throw new NotImplementedException("Atlas entry not found!");
                        }

                        Renderer.FloorRenderer.UpdateTileAtGlobalCoordinate(i, j, atlasIndex, atlasEntryIndex);
                    }
                }


                // TODO: Code below works,but get the tiles to render first.

                //foreach(var entity in file.Entities)
                //{
                //    // Map across the Objects array and into the atlas, because we don't care where the data really comes from.

                //    var obj = file.Objects[entity.ObjectId];

                //    var blobName = obj.FileName.ToLower().Trim();
                //    var cfsName = obj.Id.ToLower().Trim();

                //    if (blobName == null)
                //    {
                //        // Dealing with a shady file. Deal with this later.
                //        throw new NotImplementedException("Deal with this later.");
                //    }

                //    CfsBitmap cfs = null;

                //    foreach (var atlas in Renderer.ObjectAtlasses)
                //    {
                //        var foundCfs = atlas.Entries
                //            .FirstOrDefault(entry => entry.CfsBitmap.BloFilename == blobName
                //            && entry.CfsBitmap.CfsFilename == cfsName
                //            && entry.CfsBitmap.FrameIndex == entity.FrameIndex);

                //        if (foundCfs != null)
                //        {
                //            cfs = foundCfs.CfsBitmap;
                //            break;
                //        }
                //    }

                //    if (cfs == null)
                //    {
                //        throw new NotImplementedException("What do we do here?");
                //    }
                //}
            }
        }
示例#3
0
        public static void Main(string[] args)
        {
            bool showHelp        = false;
            bool resourceMapping = true;
            bool generateBlobs   = false;
            bool stripDumbBlobs  = false;

            var options = new OptionSet()
            {
                {
                    "no-resource-mapping",
                    "don't do resource mapping for older level files",
                    v => resourceMapping = v == null
                },
                {
                    "g|generate-blobs",
                    "generate blobs for older level files when resource mapping fails",
                    v => generateBlobs = v != null
                },
                {
                    "s|strip-lvb-blob-references",
                    "strip references to .lvb.blo blob files",
                    v => stripDumbBlobs = v != null
                },
                {
                    "h|help",
                    "show this message and exit",
                    v => showHelp = v != null
                },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_lvl [output_map]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            string inputPath  = extras[0];
            string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".map");
            string lvbPath    = Path.ChangeExtension(inputPath, ".lvb");
            string lvbName    = Path.GetFileName(lvbPath);

            var level = new LevelFile();

            using (var input = File.OpenRead(inputPath))
            {
                level.Deserialize(input);
            }

            if (stripDumbBlobs == true)
            {
                for (int i = 0; i < level.Floors.Count; i++)
                {
                    var floor = level.Floors[i];
                    if (floor.FileName != null &&
                        floor.FileName.EndsWith(".lvb.blo") == true)
                    {
                        floor.FileName  = null;
                        level.Floors[i] = floor;
                    }
                }

                for (int i = 0; i < level.Objects.Count; i++)
                {
                    var obj = level.Objects[i];
                    if (obj.FileName != null &&
                        obj.FileName.EndsWith(".lvb.blo") == true)
                    {
                        obj.FileName     = null;
                        level.Objects[i] = obj;
                    }
                }
            }

            var hasLevelBlob =
                level.Floors.Any(f => f.FileName == null) == true ||
                level.Objects.Any(o => o.FileName == null) == true;

            var remap =
                new Dictionary <string, string>();

            if (hasLevelBlob == true)
            {
                // TODO: decrap this block of code

                var resources = resourceMapping == true
                                    ? LoadBloTable()
                                    : new SortedDictionary <string, string>();

                if (File.Exists(lvbPath) == false)
                {
                    Console.WriteLine("Could not open '{0}'!", lvbPath);
                    Console.WriteLine();
                    Console.WriteLine("Mapping of LVB resources to real locations isn't going to happen.");
                }
                else
                {
                    using (var lvb = File.OpenRead(lvbPath))
                    {
                        var levelBlob = new BlobFile();
                        levelBlob.Deserialize(lvb);

                        var md5 = MD5.Create();

                        var unknownEntries = new List <BlobFile.Entry>();

                        foreach (var entry in levelBlob.Entries)
                        {
                            lvb.Seek(entry.Offset, SeekOrigin.Begin);

                            var data = new byte[entry.Size];
                            if (lvb.Read(data, 0, data.Length) != data.Length)
                            {
                                throw new FormatException();
                            }

                            var hash         = md5.ComputeHash(data);
                            var friendlyHash = BitConverter
                                               .ToString(hash)
                                               .Replace("-", "")
                                               .ToLowerInvariant();

                            if (resources.ContainsKey(friendlyHash) == true)
                            {
                                remap[entry.Name] = resources[friendlyHash];
                            }
                            else
                            {
                                Console.WriteLine("Could not find real location for '{0},{1}'.", lvbName, entry.Name);
                                unknownEntries.Add(entry);
                            }
                        }

                        if (unknownEntries.Count > 0)
                        {
                            Console.WriteLine("Could not find all of the level blob resources.");

                            if (generateBlobs == true)
                            {
                                // ReSharper disable JoinDeclarationAndInitializer
                                string floorBlobName;
                                // ReSharper restore JoinDeclarationAndInitializer

                                floorBlobName  = "f_!";
                                floorBlobName += Path.GetFileNameWithoutExtension(inputPath);
                                floorBlobName  = Path.ChangeExtension(floorBlobName, ".blo");

                                // ReSharper disable JoinDeclarationAndInitializer
                                string floorBlobPath;
                                // ReSharper restore JoinDeclarationAndInitializer

                                floorBlobPath = Path.GetDirectoryName(inputPath);
                                if (floorBlobPath == null)
                                {
                                    throw new InvalidOperationException();
                                }

                                floorBlobPath = Path.Combine(floorBlobPath, floorBlobName);

                                Console.WriteLine("Creating '{0}'...", floorBlobPath);

                                using (var output = File.Create(floorBlobPath))
                                {
                                    var floorBlob = new BlobFile
                                    {
                                        Version = 2,
                                    };

                                    // generate fake entries
                                    var floors = unknownEntries
                                                 .Where(f => f.Name.StartsWith("f"))
                                                 .ToArray();

                                    foreach (var floor in floors)
                                    {
                                        floorBlob.Entries.Add(new BlobFile.Entry()
                                        {
                                            Name = floor.Name,
                                        });
                                    }
                                    floorBlob.Serialize(output);

                                    // generate real entries
                                    floorBlob.Entries.Clear();
                                    foreach (var floor in floors)
                                    {
                                        Console.WriteLine("  adding '{0}'", floor.Name);

                                        lvb.Seek(floor.Offset, SeekOrigin.Begin);

                                        floorBlob.Entries.Add(new BlobFile.Entry()
                                        {
                                            Name   = floor.Name,
                                            Offset = output.Position,
                                            Size   = floor.Size,
                                        });

                                        output.WriteFromStream(lvb, floor.Size);

                                        remap[floor.Name] = string.Format("{0},{1}", floorBlobName, floor.Name);
                                    }

                                    output.Seek(0, SeekOrigin.Begin);
                                    floorBlob.Serialize(output);
                                }

                                // ReSharper disable JoinDeclarationAndInitializer
                                string objectBlobName;
                                // ReSharper restore JoinDeclarationAndInitializer

                                objectBlobName  = "o_!";
                                objectBlobName += Path.GetFileNameWithoutExtension(inputPath);
                                objectBlobName  = Path.ChangeExtension(objectBlobName, ".blo");

                                // ReSharper disable JoinDeclarationAndInitializer
                                string objectBlobPath;
                                // ReSharper restore JoinDeclarationAndInitializer

                                objectBlobPath = Path.GetDirectoryName(inputPath);
                                if (objectBlobPath == null)
                                {
                                    throw new InvalidOperationException();
                                }

                                objectBlobPath = Path.Combine(objectBlobPath, objectBlobName);

                                Console.WriteLine("Creating '{0}'...", objectBlobPath);

                                using (var output = File.Create(objectBlobPath))
                                {
                                    var objectBlob = new BlobFile
                                    {
                                        Version = 2,
                                    };

                                    // generate fake entries
                                    var objects = unknownEntries
                                                  .Where(o => o.Name.StartsWith("o"))
                                                  .ToArray();
                                    foreach (var obj in objects)
                                    {
                                        objectBlob.Entries.Add(new BlobFile.Entry()
                                        {
                                            Name = obj.Name,
                                        });
                                    }
                                    objectBlob.Serialize(output);

                                    // generate real entries
                                    objectBlob.Entries.Clear();
                                    foreach (var obj in objects)
                                    {
                                        Console.WriteLine("  adding '{0}'", obj.Name);

                                        lvb.Seek(obj.Offset, SeekOrigin.Begin);

                                        objectBlob.Entries.Add(new BlobFile.Entry()
                                        {
                                            Name   = obj.Name,
                                            Offset = output.Position,
                                            Size   = obj.Size,
                                        });

                                        output.WriteFromStream(lvb, obj.Size);

                                        remap[obj.Name] = string.Format("{0},{1}", objectBlobName, obj.Name);
                                    }

                                    output.Seek(0, SeekOrigin.Begin);
                                    objectBlob.Serialize(output);
                                }
                            }
                        }
                    }
                }
            }

            using (var output = File.Create(outputPath))
            {
                var header = new Map.Header
                {
                    Version     = 9,
                    Width       = level.Width,
                    Height      = level.Height,
                    EntityCount = level.Entities.Count,
                    PhysicsLow  = new short[32],
                };

                // not right? DERP
                //header.OffsetX = level.OffsetX;
                //header.OffsetY = level.OffsetY;

                Array.Copy(level.PhysicsLow, header.PhysicsLow, level.PhysicsLow.Length);
                header.PhysicsHigh = new short[32];
                Array.Copy(level.PhysicsHigh, header.PhysicsHigh, level.PhysicsHigh.Length);

                header.LightColorWhite = level.LightColorWhite;
                header.LightColorRed   = level.LightColorRed;
                header.LightColorGreen = level.LightColorGreen;
                header.LightColorBlue  = level.LightColorBlue;

                output.WriteStructure(header);

                for (int i = 0; i < 8192; i++)
                {
                    if (i < level.TerrainIds.Length)
                    {
                        output.WriteValueU8((byte)level.TerrainIds[i]);
                    }
                    else
                    {
                        output.WriteValueU8(0);
                    }
                }

                for (int i = 0; i < 2048; i++)
                {
                    var reference = new Map.BlobReference();

                    if (i < level.Floors.Count)
                    {
                        var floor = level.Floors[i];

                        if (floor.FileName == null)
                        {
                            if (remap.ContainsKey(floor.Id) == true)
                            {
                                reference.Path = remap[floor.Id];
                            }
                            else
                            {
                                reference.Path = string.Format("{0},{1}",
                                                               lvbName,
                                                               floor.Id);
                            }
                        }
                        else
                        {
                            reference.Path = string.Format("{0},{1}",
                                                           floor.FileName,
                                                           floor.Id);
                        }
                    }

                    output.WriteStructure(reference);
                }

                var tiles = new byte[level.Width * level.Height * 4];
                // ReSharper disable UnusedVariable
                int offset = 0;
                // ReSharper restore UnusedVariable

                for (int i = 0, j = 0; i < level.Tiles.Length; i++, j += 4)
                {
                    tiles[j + 0]  = level.Tiles[i].BitsA;
                    tiles[j + 0] &= 0x7F;
                    tiles[j + 1]  = 0;
                    tiles[j + 2]  = level.Tiles[i].BitsC;
                    tiles[j + 3]  = level.Tiles[i].BitsB;
                }

                using (var rle = new MemoryStream())
                {
                    rle.WriteRLE(tiles, 4, level.Tiles.Length, false);
                    rle.Position = 0;

                    output.WriteValueS32((int)rle.Length);
                    output.WriteFromStream(rle, rle.Length);
                }

                foreach (var t in level.Entities)
                {
                    output.WriteStructure(t);

                    var obj = level.Objects[t.ObjectId];

                    var reference = new Map.BlobReference();

                    if (obj.FileName == null)
                    {
                        if (remap.ContainsKey(obj.Id) == true)
                        {
                            reference.Path = remap[obj.Id];
                        }
                        else
                        {
                            reference.Path = string.Format("{0},{1}",
                                                           lvbName,
                                                           obj.Id);
                        }
                    }
                    else
                    {
                        reference.Path = string.Format("{0},{1}",
                                                       obj.FileName,
                                                       obj.Id);
                    }

                    output.WriteStructure(reference);
                }
            }
        }