Пример #1
0
        public void Read(BinaryReader reader, AoeVersion version)
        {
            if (version >= AoeVersion.AOE2TC)
            {
                // aitype
                reader.ReadInt32();
            }

            width   = reader.ReadUInt32();
            height  = reader.ReadUInt32();
            terrain = new Terrain[width, height];

            for (uint x = 0; x < width; x++)
            {
                for (uint y = 0; y < height; y++)
                {
                    terrain[x, y].cnst = (AoeTerrainType)reader.ReadByte();
                    terrain[x, y].elev = reader.ReadByte();
                    var unk = reader.ReadByte(); // always 0?
                }
            }
        }
Пример #2
0
        public Scenario(string path)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException("File not found.", path);
            }

            MemoryStream decompressedData;

            using (var fileStream = File.Open(path, FileMode.Open, FileAccess.Read))
            {
                using (var binaryReader = new BinaryReader(fileStream))
                {
                    var version = Encoding.ASCII.GetString(binaryReader.ReadBytes(4));
                    FileVersion = version switch
                    {
                        "1.10" => AoeVersion.AOE1,
                        "1.11" => AoeVersion.AOE1,
                        "1.18" => AoeVersion.AOE2,
                        "1.21" => AoeVersion.AOE2TC,
                        _ => throw new Exception("Unknown scenario version: " + version),
                    };

                    var headerLength       = binaryReader.ReadInt32();
                    var checkSum           = binaryReader.ReadInt32();
                    var timeStamp          = binaryReader.ReadInt32();
                    var instructionsLength = binaryReader.ReadInt32();
                    var instructions       = binaryReader.ReadBytes(instructionsLength);
                    binaryReader.ReadInt32();
                    PlayerCount = binaryReader.ReadInt32();

                    // var compressedlength = binaryReader.BaseStream.Length - (headerLength + 8);

                    decompressedData          = Decompress(binaryReader);
                    decompressedData.Position = 0;
                }
            }

            using var reader = new BinaryReader(decompressedData);

            long next_uid = reader.ReadInt32();

            SubVersion = reader.ReadSingle();

            for (var i = 0; i < PlayerSlotCount; i++)
            {
                var name = reader.ReadBytes(256); // player name
            }

            if (FileVersion != AoeVersion.AOE1)
            {
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    reader.ReadInt32(); // string table
                }
            }

            PlayerData = new PlayerSlotData[PlayerSlotCount];
            for (var i = 0; i < PlayerSlotCount; i++)
            {
                PlayerData[i] = new PlayerSlotData(i, reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32());
            }

            reader.ReadInt32();
            reader.ReadByte();
            reader.ReadSingle();

            ScenarioName = Encoding.ASCII.GetString(reader.ReadBytes(reader.ReadUInt16()));

            var messageCount = (FileVersion != AoeVersion.AOE1 ? 6 : 5);

            long[]   mstrings = new long[6];
            string[] messages = new string[messageCount];
            string[] cinem    = new string[4];
            string[] unk      = new string[32];
            string[] ai       = new string[PlayerSlotCount];

            if (FileVersion != AoeVersion.AOE1)
            {
                for (int i = 0; i < 6; i++)
                {
                    mstrings[i] = reader.ReadInt32();
                }
            }

            for (var i = 0; i < messageCount; i++)
            {
                messages[i] = Encoding.ASCII.GetString(reader.ReadBytes(reader.ReadUInt16()));
            }

            for (var i = 0; i < 4; i++)
            {
                cinem[i] = Encoding.ASCII.GetString(reader.ReadBytes(reader.ReadUInt16()));
            }

            Messages = messages.ToImmutableArray();

            // bitmap
            var bitmap    = reader.ReadInt32();
            var bitmapx   = reader.ReadInt32();
            var bitmapy   = reader.ReadInt32();
            var bitmapunk = reader.ReadInt16();

            if (bitmap != 0)
            {
                // read some big ass bitmap file if bitmap != 0
                throw new NotSupportedException();
            }

            for (var i = 0; i < 32; i++)
            {
                unk[i] = Encoding.ASCII.GetString(reader.ReadBytes(reader.ReadUInt16()));
            }

            for (var i = 0; i < PlayerSlotCount; i++)
            {
                ai[i] = Encoding.ASCII.GetString(reader.ReadBytes(reader.ReadUInt16()));
            }

            for (var i = 0; i < PlayerSlotCount; i++)
            {
                var part1len    = reader.ReadInt32();
                var part2len    = reader.ReadInt32();
                var part3len    = reader.ReadUInt32();
                var totalLength = part1len + part2len + part3len;
                var text        = Encoding.ASCII.GetString(reader.ReadBytes((int)totalLength));
            }

            if (FileVersion != AoeVersion.AOE1)
            {
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    Console.WriteLine(i + ": aimode=" + reader.ReadByte());
                }
            }

            if (reader.ReadUInt32() != Sect)
            {
                throw new InvalidDataException();
            }

            // Resources
            for (var i = 0; i < PlayerSlotCount; i++)
            {
                PlayerData[i].SetStartingResources(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32());

                if (FileVersion != AoeVersion.AOE1)
                {
                    Console.WriteLine("\tOrex: " + reader.ReadInt32());
                    Console.WriteLine("\tUnknown: " + reader.ReadInt32());
                }
            }

            if (reader.ReadUInt32() != Sect)
            {
                throw new InvalidDataException();
            }

            reader.ReadBytes(40); // victory stuff

            for (var i = 0; i < PlayerSlotCount; i++)
            {
                for (var j = 0; j < PlayerSlotCount; j++)
                {
                    var diplomacy = reader.ReadInt32(); // 0=ally?, 3=enemy?

                    /*Console.Write(diplomacy);
                     * if (j != (PlayerSlotCount - 1))
                     * {
                     *  Console.Write(" ");
                     * }
                     * else
                     * {
                     *  Console.WriteLine();
                     * }*/
                }
            }

            reader.ReadBytes(0x2D00); // idc

            if (reader.ReadUInt32() != Sect)
            {
                throw new InvalidDataException();
            }

            if (FileVersion == AoeVersion.AOE1)
            {
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    for (var j = 0; j < 21; j++)
                    {
                        reader.ReadInt32();
                    }
                }
            }
            else
            {
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    reader.ReadInt32();
                }
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    reader.ReadInt32();
                }
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    for (var j = 0; j < 30; j++)
                    {
                        reader.ReadInt32();
                    }
                }
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    reader.ReadInt32();
                }
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    for (var j = 0; j < 30; j++)
                    {
                        reader.ReadInt32();
                    }
                }
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    reader.ReadInt32();
                }
                for (var i = 0; i < PlayerSlotCount; i++)
                {
                    for (var j = 0; j < 20; j++)
                    {
                        reader.ReadInt32();
                    }
                }

                Console.WriteLine(reader.ReadInt32());
                Console.WriteLine(reader.ReadInt32());
            }

            var alltech = reader.ReadInt32() != 0;

            for (var i = 0; i < PlayerSlotCount; i++)
            {
                PlayerData[i].SetStartingAge(reader.ReadInt32());
            }

            var unk1 = reader.ReadUInt32();
            var unk2 = reader.ReadUInt32();

            if (reader.ReadUInt32() != Sect)
            {
                throw new InvalidDataException();
            }

            // Map
            Map = new ScenarioMap();
            Map.Read(reader, FileVersion);

            // Units
            // https://github.com/dderevjanik/agescx-js/blob/master/packages/io/Structures/UnitsStruct.ts
            var unitSections = reader.ReadInt32();

            if (unitSections != 9)
            {
                throw new Exception();
            }

            for (var i = 0; i < unitSections - 1; i++)
            {
                reader.ReadSingle();
                reader.ReadSingle();
                reader.ReadSingle();
                reader.ReadSingle();
            }

            Entities = new Dictionary <int, ImmutableArray <Entity> >();
            for (var i = 0; i < unitSections; i++)
            {
                var unitCount = reader.ReadUInt32();
                var units     = new Entity[unitCount];
                for (var j = 0; j < unitCount; j++)
                {
                    // var x = reader.ReadSingle();
                    var y = reader.ReadSingle();
                    var x = reader.ReadSingle();
                    if (x < 0 || x > Map.width || y < 0 || y > Map.height)
                    {
                        throw new InvalidDataException();
                    }

                    var unitunk    = reader.ReadSingle();
                    var identifier = reader.ReadUInt32();
                    var unittype   = (AoeEntityType)reader.ReadUInt16();
                    var status     = reader.ReadByte();
                    if (status != 2 && status != 7)
                    {
                        throw new InvalidDataException();
                    }

                    var rotation = reader.ReadSingle();
                    if (rotation < 0 || rotation > 23)
                    {
                        throw new InvalidDataException();
                    }

                    if (FileVersion != AoeVersion.AOE1)
                    {
                        var initialFrame = reader.ReadUInt16();
                        var garissonid   = reader.ReadInt32();
                    }

                    units[j] = new Entity(unittype, x, y, rotation, status, identifier);
                }

                Entities.Add(i, units.ToImmutableArray());
            }

            // more data...
        }