Example #1
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);
                }
            }
        }
Example #2
0
        public static void Main(string[] args)
        {
            bool showHelp = false;
            int width = 500;
            int height = 500;

            var options = new OptionSet()
            {
                {
                    "?|help",
                    "show this message and exit",
                    v => showHelp = v != null
                    },
                {
                    "w|width=",
                    "set level width",
                    v => width = v != null ? int.Parse(v) : width
                    },
                {
                    "h|height=",
                    "set level height",
                    v => height = v != null ? int.Parse(v) : height
                    },
            };

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

            var outputPath = extras.Count > 0 ? extras[0] : "space.map";

            var templates = LoadEntities();

            int cx = width / 2;
            int cy = height / 2;
            // ReSharper disable UnusedVariable
            var radius = (int)(Math.Min(width, height) / 2.0);
            // ReSharper restore UnusedVariable
            var range = Math.Min(width, height) / 2.5;

            var rng = new MersenneTwister();
            var noise = PerlinNoise.Generate(
                width, height, 0.0325f, 1.0f, 0.5f, 16, rng);

            var physics = new bool[width,height];
            var vision = new bool[width,height];

            var entities = new List<Entity>();

            for (int x = 8; x < width - 8; x++)
            {
                for (int y = 8; y < height - 8; y++)
                {
                    var distance = GetDistance(cx, cy, x, y);
                    if (distance > range &&
                        rng.Next(100) > 2)
                    {
                        continue;
                    }

                    var magic = noise[x, y];

                    if (magic >= 200)
                    {
                    }
                    else if (magic >= 180)
                    {
                        if (rng.Next(100) >= 60 &&
                            (x % 2) == 0 &&
                            (y % 2) == 0)
                        {
                            var template = templates
                                .Where(t => t.Category == "asteroid")
                                .OrderBy(t => rng.Next())
                                .FirstOrDefault();

                            if (template != null &&
                                template.CanPlaceWithPhysics(x, y, physics, width, height) == true)
                            {
                                var entity = new Entity(x, y, template);

                                int speed = rng.Next(100);

                                if (speed < 60)
                                {
                                    entity.AnimationTime = 0;
                                }
                                else if (speed < 70)
                                {
                                    entity.AnimationTime = 100;
                                }
                                else if (speed < 80)
                                {
                                    entity.AnimationTime = 200;
                                }
                                else if (speed < 85)
                                {
                                    entity.AnimationTime = 250;
                                }
                                else if (speed < 90)
                                {
                                    entity.AnimationTime = 350;
                                }
                                else if (speed < 95)
                                {
                                    entity.AnimationTime = 400;
                                }
                                else
                                {
                                    entity.AnimationTime = 450;
                                }

                                template.BlockPhysics(x, y, physics);
                                entities.Add(entity);
                            }
                        }
                    }
                    else if (magic >= 100)
                    {
                    }
                    else if (magic >= 15)
                    {
                    }
                    else
                    {
                        if (rng.Next(100) >= 80)
                        {
                            var template = templates
                                .Where(t => t.Category == "nebula")
                                .OrderBy(t => rng.Next())
                                .FirstOrDefault();

                            if (template != null &&
                                template.CanPlaceWithVision(x, y, vision, width, height) == true)
                            {
                                var entity = new Entity(x, y, template)
                                {
                                    AnimationTime = 50
                                };

                                template.BlockVision(x, y, vision);
                                entities.Add(entity);
                            }
                        }
                    }
                }
            }

            var tiles = new Level.Tile[width,height];

            foreach (var entity in entities)
            {
                for (int rx = 0; rx < entity.Template.Width; rx++)
                {
                    for (int ry = 0; ry < entity.Template.Height; ry++)
                    {
                        if (entity.Template.Physics[rx, ry] > 0)
                        {
                            tiles[entity.X + rx, entity.Y + ry].Physics =
                                entity.Template.Physics[rx, ry];
                        }

                        if (entity.Template.Vision[rx, ry] > 0)
                        {
                            tiles[entity.X + rx, entity.Y + ry].Vision =
                                entity.Template.Vision[rx, ry];
                        }
                    }
                }
            }

            var floors = new List<Map.BlobReference>
            {
                new Map.BlobReference()
                {
                    Path = "f_default.blo,default.cfs"
                },
            };
            //floors.Add(new Map.BlobReference() { Path = "f_colors.blo,color3.cfs" });

            using (var output = File.Create(outputPath))
            {
                var header = new Map.Header
                {
                    Version = 9,
                    Width = width,
                    Height = height,
                    EntityCount = entities.Count,
                    LightColorWhite = 0xFFFFFF00u,
                    LightColorRed = 0x0000FF00u,
                    LightColorGreen = 0x00FF0000u,
                    LightColorBlue = 0xFF000000u,
                    PhysicsLow = new short[32],
                    PhysicsHigh = new short[32],
                };

                header.PhysicsHigh[0] = 0;
                header.PhysicsHigh[1] = 1024;
                header.PhysicsHigh[2] = 1024;
                header.PhysicsHigh[3] = 1024;
                header.PhysicsHigh[4] = 1024;
                header.PhysicsHigh[5] = 1024;
                header.PhysicsHigh[6] = 16;
                header.PhysicsHigh[7] = 16;
                header.PhysicsHigh[8] = 16;
                header.PhysicsHigh[9] = 16;
                header.PhysicsHigh[10] = 16;
                header.PhysicsHigh[11] = 32;
                header.PhysicsHigh[12] = 32;
                header.PhysicsHigh[13] = 32;
                header.PhysicsHigh[14] = 32;
                header.PhysicsHigh[15] = 32;
                header.PhysicsHigh[16] = 64;
                header.PhysicsHigh[17] = 64;
                header.PhysicsHigh[18] = 64;
                header.PhysicsHigh[19] = 64;
                header.PhysicsHigh[20] = 64;
                header.PhysicsHigh[21] = 128;
                header.PhysicsHigh[22] = 128;
                header.PhysicsHigh[23] = 128;
                header.PhysicsHigh[24] = 128;
                header.PhysicsHigh[25] = 128;
                header.PhysicsHigh[26] = 1024;
                header.PhysicsHigh[27] = 1024;
                header.PhysicsHigh[29] = 1024;
                header.PhysicsHigh[28] = 1024;
                header.PhysicsHigh[30] = 1024;
                header.PhysicsHigh[31] = 1024;

                output.WriteStructure(header);

                for (int i = 0; i < 8192; i++)
                {
                    if (i < 16)
                    {
                        output.WriteValueU8((byte)i);
                    }
                    else
                    {
                        output.WriteValueU8(0);
                    }
                }

                for (int i = 0; i < 2048; i++)
                {
                    if (i < floors.Count)
                    {
                        output.WriteStructure(floors[i]);
                    }
                    else
                    {
                        output.Seek(64, SeekOrigin.Current);
                    }
                }

                var buffer = new byte[width * height * 4];
                for (int y = 0, offset = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++, offset += 4)
                    {
                        buffer[offset + 0] = tiles[x, y].BitsA;
                        buffer[offset + 1] = 0;
                        buffer[offset + 2] = tiles[x, y].BitsC;
                        buffer[offset + 3] = tiles[x, y].BitsB;
                    }
                }

                using (var rle = new MemoryStream())
                {
                    rle.WriteRLE(buffer, 4, width * height, false);
                    rle.Position = 0;

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

                foreach (var source in entities)
                {
                    var entity = new Level.Entity
                    {
                        X = (short)((source.X - source.Template.OffsetX) * 16),
                        Y = (short)((source.Y - source.Template.OffsetY) * 16),
                        AnimationTime = source.AnimationTime,
                    };
                    output.WriteStructure(entity);

                    var reference = new Map.BlobReference
                    {
                        Path = string.Format("{0},{1}", source.Template.BloName, source.Template.CfsName),
                    };
                    output.WriteStructure(reference);
                }
            }
        }