示例#1
0
        private void WriteMapDataTo(BinaryWriter writer, AssetNameCollection assetNames)
        {
            writer.Write(assetNames.GetOrCreateAssetIndex(HeightMapData.AssetName));
            HeightMapData.WriteTo(writer);

            writer.Write(assetNames.GetOrCreateAssetIndex(BlendTileData.AssetName));
            BlendTileData.WriteTo(writer);

            writer.Write(assetNames.GetOrCreateAssetIndex(WorldInfo.AssetName));
            WorldInfo.WriteTo(writer, assetNames);

            writer.Write(assetNames.GetOrCreateAssetIndex(SidesList.AssetName));
            SidesList.WriteTo(writer, assetNames);

            writer.Write(assetNames.GetOrCreateAssetIndex(ObjectsList.AssetName));
            ObjectsList.WriteTo(writer, assetNames);

            writer.Write(assetNames.GetOrCreateAssetIndex(PolygonTriggers.AssetName));
            PolygonTriggers.WriteTo(writer);

            writer.Write(assetNames.GetOrCreateAssetIndex(GlobalLighting.AssetName));
            GlobalLighting.WriteTo(writer);

            writer.Write(assetNames.GetOrCreateAssetIndex(WaypointsList.AssetName));
            WaypointsList.WriteTo(writer);
        }
示例#2
0
        private static MapFile ParseMapData(BinaryReader reader)
        {
            var assetNames = AssetNameCollection.Parse(reader);

            var result = new MapFile();

            var context = new MapParseContext(assetNames);

            context.PushAsset(nameof(MapFile), reader.BaseStream.Length);

            Asset.ParseAssets(reader, context, assetName =>
            {
                switch (assetName)
                {
                case HeightMapData.AssetName:
                    result.HeightMapData = HeightMapData.Parse(reader, context);
                    break;

                case BlendTileData.AssetName:
                    result.BlendTileData = BlendTileData.Parse(reader, context, result.HeightMapData);
                    break;

                case WorldInfo.AssetName:
                    result.WorldInfo = WorldInfo.Parse(reader, context);
                    break;

                case SidesList.AssetName:
                    result.SidesList = SidesList.Parse(reader, context);
                    break;

                case ObjectsList.AssetName:
                    result.ObjectsList = ObjectsList.Parse(reader, context);
                    break;

                case PolygonTriggers.AssetName:
                    result.PolygonTriggers = PolygonTriggers.Parse(reader, context);
                    break;

                case GlobalLighting.AssetName:
                    result.GlobalLighting = GlobalLighting.Parse(reader, context);
                    break;

                case WaypointsList.AssetName:
                    result.WaypointsList = WaypointsList.Parse(reader, context);
                    break;

                default:
                    throw new NotImplementedException(assetName);
                }
            });

            context.PopAsset();

            return(result);
        }
示例#3
0
        internal static HeightMapData Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var result = new HeightMapData
                {
                    Width = reader.ReadUInt32(),
                    Height = reader.ReadUInt32(),

                    BorderWidth = reader.ReadUInt32()
                };

                var borderCount = reader.ReadUInt32();
                result.Borders = new HeightMapBorder[borderCount];

                for (var i = 0; i < borderCount; i++)
                {
                    result.Borders[i] = HeightMapBorder.Parse(reader, version);
                }

                result.Area = reader.ReadUInt32();
                if (result.Width * result.Height != result.Area)
                {
                    throw new InvalidDataException();
                }

                result.Elevations = new ushort[result.Width, result.Height];
                for (var y = 0; y < result.Height; y++)
                {
                    for (var x = 0; x < result.Width; x++)
                    {
                        result.Elevations[x, y] = version >= 5
                            ? reader.ReadUInt16()
                            : reader.ReadByte();
                    }
                }

                return result;
            }));
        }
示例#4
0
        private void WriteMapDataTo(BinaryWriter writer, AssetNameCollection assetNames)
        {
            if (AssetList != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(AssetList.AssetName));
                AssetList.WriteTo(writer);
            }

            if (GlobalVersion != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(GlobalVersion.AssetName));
                GlobalVersion.WriteTo(writer);
            }

            writer.Write(assetNames.GetOrCreateAssetIndex(HeightMapData.AssetName));
            HeightMapData.WriteTo(writer);

            writer.Write(assetNames.GetOrCreateAssetIndex(BlendTileData.AssetName));
            BlendTileData.WriteTo(writer);

            writer.Write(assetNames.GetOrCreateAssetIndex(WorldInfo.AssetName));
            WorldInfo.WriteTo(writer, assetNames);

            if (MPPositionList != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(MPPositionList.AssetName));
                MPPositionList.WriteTo(writer, assetNames);
            }

            writer.Write(assetNames.GetOrCreateAssetIndex(SidesList.AssetName));
            SidesList.WriteTo(writer, assetNames, AssetList != null);

            if (LibraryMapLists != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(LibraryMapLists.AssetName));
                LibraryMapLists.WriteTo(writer, assetNames);
            }

            if (Teams != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(Teams.AssetName));
                Teams.WriteTo(writer, assetNames);
            }

            if (PlayerScriptsList != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(PlayerScriptsList.AssetName));
                PlayerScriptsList.WriteTo(writer, assetNames);
            }

            if (BuildLists != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(BuildLists.AssetName));
                BuildLists.WriteTo(writer, assetNames, AssetList != null);
            }

            writer.Write(assetNames.GetOrCreateAssetIndex(ObjectsList.AssetName));
            ObjectsList.WriteTo(writer, assetNames);

            if (PolygonTriggers != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(PolygonTriggers.AssetName));
                PolygonTriggers.WriteTo(writer);
            }

            if (TriggerAreas != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(TriggerAreas.AssetName));
                TriggerAreas.WriteTo(writer);
            }

            if (GlobalWaterSettings != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(GlobalWaterSettings.AssetName));
                GlobalWaterSettings.WriteTo(writer);
            }

            if (FogSettings != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(FogSettings.AssetName));
                FogSettings.WriteTo(writer);
            }

            if (MissionHotSpots != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(MissionHotSpots.AssetName));
                MissionHotSpots.WriteTo(writer);
            }

            if (MissionObjectives != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(MissionObjectives.AssetName));
                MissionObjectives.WriteTo(writer);
            }

            if (StandingWaterAreas != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(StandingWaterAreas.AssetName));
                StandingWaterAreas.WriteTo(writer);
            }

            if (RiverAreas != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(RiverAreas.AssetName));
                RiverAreas.WriteTo(writer);
            }

            if (StandingWaveAreas != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(StandingWaveAreas.AssetName));
                StandingWaveAreas.WriteTo(writer);
            }

            writer.Write(assetNames.GetOrCreateAssetIndex(GlobalLighting.AssetName));
            GlobalLighting.WriteTo(writer);

            if (PostEffectsChunk != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(PostEffectsChunk.AssetName));
                PostEffectsChunk.WriteTo(writer);
            }

            if (EnvironmentData != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(EnvironmentData.AssetName));
                EnvironmentData.WriteTo(writer);
            }

            if (NamedCameras != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(NamedCameras.AssetName));
                NamedCameras.WriteTo(writer);
            }

            if (CameraAnimationList != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(CameraAnimationList.AssetName));
                CameraAnimationList.WriteTo(writer);
            }

            if (CastleTemplates != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(CastleTemplates.AssetName));
                CastleTemplates.WriteTo(writer, assetNames);
            }

            writer.Write(assetNames.GetOrCreateAssetIndex(WaypointsList.AssetName));
            WaypointsList.WriteTo(writer);

            if (SkyboxSettings != null)
            {
                writer.Write(assetNames.GetOrCreateAssetIndex(SkyboxSettings.AssetName));
                SkyboxSettings.WriteTo(writer);
            }
        }
示例#5
0
        private static MapFile ParseMapData(BinaryReader reader)
        {
            var assetNames = AssetNameCollection.Parse(reader);

            var result = new MapFile();

            var context = new MapParseContext(assetNames);

            context.PushAsset(nameof(MapFile), reader.BaseStream.Length);

            Asset.ParseAssets(reader, context, assetName =>
            {
                switch (assetName)
                {
                case AssetList.AssetName:
                    result.AssetList = AssetList.Parse(reader, context);
                    break;

                case GlobalVersion.AssetName:
                    result.GlobalVersion = GlobalVersion.Parse(reader, context);
                    break;

                case HeightMapData.AssetName:
                    result.HeightMapData = HeightMapData.Parse(reader, context);
                    break;

                case BlendTileData.AssetName:
                    result.BlendTileData = BlendTileData.Parse(reader, context, result.HeightMapData);
                    break;

                case WorldInfo.AssetName:
                    result.WorldInfo = WorldInfo.Parse(reader, context);
                    break;

                case MPPositionList.AssetName:
                    result.MPPositionList = MPPositionList.Parse(reader, context);
                    break;

                case SidesList.AssetName:
                    result.SidesList = SidesList.Parse(reader, context, result.AssetList != null);
                    break;

                case LibraryMapLists.AssetName:
                    result.LibraryMapLists = LibraryMapLists.Parse(reader, context);
                    break;

                case Teams.AssetName:
                    result.Teams = Teams.Parse(reader, context);
                    break;

                case PlayerScriptsList.AssetName:
                    result.PlayerScriptsList = PlayerScriptsList.Parse(reader, context);
                    break;

                case BuildLists.AssetName:
                    result.BuildLists = BuildLists.Parse(reader, context, result.AssetList != null);
                    break;

                case ObjectsList.AssetName:
                    result.ObjectsList = ObjectsList.Parse(reader, context);
                    break;

                case PolygonTriggers.AssetName:
                    result.PolygonTriggers = PolygonTriggers.Parse(reader, context);
                    break;

                case TriggerAreas.AssetName:
                    result.TriggerAreas = TriggerAreas.Parse(reader, context);
                    break;

                case GlobalWaterSettings.AssetName:
                    result.GlobalWaterSettings = GlobalWaterSettings.Parse(reader, context);
                    break;

                case FogSettings.AssetName:
                    result.FogSettings = FogSettings.Parse(reader, context);
                    break;

                case MissionHotSpots.AssetName:
                    result.MissionHotSpots = MissionHotSpots.Parse(reader, context);
                    break;

                case MissionObjectives.AssetName:
                    result.MissionObjectives = MissionObjectives.Parse(reader, context);
                    break;

                case StandingWaterAreas.AssetName:
                    result.StandingWaterAreas = StandingWaterAreas.Parse(reader, context);
                    break;

                case RiverAreas.AssetName:
                    result.RiverAreas = RiverAreas.Parse(reader, context);
                    break;

                case StandingWaveAreas.AssetName:
                    result.StandingWaveAreas = StandingWaveAreas.Parse(reader, context);
                    break;

                case GlobalLighting.AssetName:
                    result.GlobalLighting = GlobalLighting.Parse(reader, context);
                    break;

                case PostEffectsChunk.AssetName:
                    result.PostEffectsChunk = PostEffectsChunk.Parse(reader, context);
                    break;

                case EnvironmentData.AssetName:
                    result.EnvironmentData = EnvironmentData.Parse(reader, context);
                    break;

                case NamedCameras.AssetName:
                    result.NamedCameras = NamedCameras.Parse(reader, context);
                    break;

                case CameraAnimationList.AssetName:
                    result.CameraAnimationList = CameraAnimationList.Parse(reader, context);
                    break;

                case CastleTemplates.AssetName:
                    result.CastleTemplates = CastleTemplates.Parse(reader, context);
                    break;

                case WaypointsList.AssetName:
                    result.WaypointsList = WaypointsList.Parse(reader, context);
                    break;

                case SkyboxSettings.AssetName:
                    result.SkyboxSettings = SkyboxSettings.Parse(reader, context);
                    break;

                default:
                    throw new NotImplementedException(assetName);
                }
            });

            context.PopAsset();

            return(result);
        }
示例#6
0
        internal static BlendTileData Parse(BinaryReader reader, MapParseContext context, HeightMapData heightMapData)
        {
            return(ParseAsset(reader, context, version =>
            {
                if (version < 6)
                {
                    throw new InvalidDataException();
                }

                if (heightMapData == null)
                {
                    throw new InvalidDataException("Expected HeightMapData asset before BlendTileData asset.");
                }

                var width = heightMapData.Width;
                var height = heightMapData.Height;

                var result = new BlendTileData();

                result.NumTiles = reader.ReadUInt32();
                if (result.NumTiles != width * height)
                {
                    throw new InvalidDataException();
                }

                result.Tiles = reader.ReadUInt16Array2D(width, height);

                var blendBitSize = GetBlendBitSize(version);
                result.Blends = reader.ReadUIntArray2D(width, height, blendBitSize);
                result.ThreeWayBlends = reader.ReadUIntArray2D(width, height, blendBitSize);
                result.CliffTextures = reader.ReadUIntArray2D(width, height, blendBitSize);

                if (version > 6)
                {
                    var passabilityWidth = heightMapData.Width;
                    if (version == 7)
                    {
                        // C&C Generals clips partial bytes from each row of passability data,
                        passabilityWidth = ((passabilityWidth + 1) / 8) * 8;
                    }

                    // If terrain is passable, there's a 0 in the data file.
                    result.Impassability = reader.ReadSingleBitBooleanArray2D(passabilityWidth, heightMapData.Height);
                }

                if (version >= 10)
                {
                    result.ImpassabilityToPlayers = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                }

                if (version >= 11)
                {
                    result.PassageWidths = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                }

                if (version >= 14 && version < 25)
                {
                    result.Taintability = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                }

                if (version >= 15)
                {
                    result.ExtraPassability = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                }

                if (version >= 16 && version < 25)
                {
                    result.Flammability = reader.ReadByteArray2DAsEnum <TileFlammability>(heightMapData.Width, heightMapData.Height);
                }

                if (version >= 17)
                {
                    result.Visibility = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                }

                if (version >= 24)
                {
                    // TODO: Are these in the right order?
                    result.Buildability = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                    result.ImpassabilityToAirUnits = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                    result.TiberiumGrowability = reader.ReadSingleBitBooleanArray2D(heightMapData.Width, heightMapData.Height);
                }

                if (version >= 25)
                {
                    result.DynamicShrubberyDensity = reader.ReadByteArray2D(heightMapData.Width, heightMapData.Height);
                }

                result.TextureCellCount = reader.ReadUInt32();

                var blendsCount = reader.ReadUInt32();
                if (blendsCount > 0)
                {
                    // Usually minimum value is 1, but some files (perhaps Generals, not Zero Hour?) have 0.
                    blendsCount--;
                }

                result.ParsedCliffTextureMappingsCount = reader.ReadUInt32();
                var cliffBlendsCount = result.ParsedCliffTextureMappingsCount;
                if (cliffBlendsCount > 0)
                {
                    // Usually minimum value is 1, but some files (perhaps Generals, not Zero Hour?) have 0.
                    cliffBlendsCount--;
                }

                var textureCount = reader.ReadUInt32();
                result.Textures = new BlendTileTexture[textureCount];
                for (var i = 0; i < textureCount; i++)
                {
                    result.Textures[i] = BlendTileTexture.Parse(reader);
                }

                // Can be a variety of values, don't know what it means.
                result.MagicValue1 = reader.ReadUInt32();

                result.MagicValue2 = reader.ReadUInt32();
                if (result.MagicValue2 != 0)
                {
                    throw new InvalidDataException();
                }

                result.BlendDescriptions = new BlendDescription[blendsCount];
                for (var i = 0; i < blendsCount; i++)
                {
                    result.BlendDescriptions[i] = BlendDescription.Parse(reader, version);
                }

                result.CliffTextureMappings = new CliffTextureMapping[cliffBlendsCount];
                for (var i = 0; i < cliffBlendsCount; i++)
                {
                    result.CliffTextureMappings[i] = CliffTextureMapping.Parse(reader);
                }

                return result;
            }));
        }
示例#7
0
        internal static BlendTileData Parse(BinaryReader reader, MapParseContext context, HeightMapData heightMapData)
        {
            return(ParseAsset(reader, context, version =>
            {
                if (version < 6 || version > 8)
                {
                    throw new InvalidDataException();
                }

                if (heightMapData == null)
                {
                    throw new InvalidDataException("Expected HeightMapData asset before BlendTileData asset.");
                }

                var width = heightMapData.Width;
                var height = heightMapData.Height;

                var numTiles = reader.ReadUInt32();
                if (numTiles != width * height)
                {
                    throw new InvalidDataException();
                }

                var tiles = reader.ReadUInt16Array2D(width, height);
                var blends = reader.ReadUInt16Array2D(width, height);
                var threeWayBlends = reader.ReadUInt16Array2D(width, height);
                var cliffTextures = reader.ReadUInt16Array2D(width, height);

                bool[,] passability = null;
                if (version > 6)
                {
                    var passabilityWidth = heightMapData.Width;
                    if (version == 7)
                    {
                        // C&C Generals clips partial bytes from each row of passability data,
                        // if the border width is large enough to fully contain the clipped data.
                        if (passabilityWidth % 8 <= 6 && passabilityWidth % 8 <= heightMapData.BorderWidth)
                        {
                            passabilityWidth -= passabilityWidth % 8;
                        }
                    }

                    // If terrain is passable, there's a 0 in the data file.
                    passability = reader.ReadSingleBitBooleanArray2D(passabilityWidth, heightMapData.Height);
                }

                var textureCellCount = reader.ReadUInt32();

                var blendsCount = reader.ReadUInt32();
                if (blendsCount > 0)
                {
                    // Usually minimum value is 1, but some files (perhaps Generals, not Zero Hour?) have 0.
                    blendsCount--;
                }

                var parsedCliffBlendsCount = reader.ReadUInt32();
                var cliffBlendsCount = parsedCliffBlendsCount;
                if (cliffBlendsCount > 0)
                {
                    // Usually minimum value is 1, but some files (perhaps Generals, not Zero Hour?) have 0.
                    cliffBlendsCount--;
                }

                var textureCount = reader.ReadUInt32();
                var textures = new BlendTileTexture[textureCount];
                for (var i = 0; i < textureCount; i++)
                {
                    textures[i] = BlendTileTexture.Parse(reader);
                }

                var magicValue1 = reader.ReadUInt32();
                if (magicValue1 != 0)
                {
                    throw new InvalidDataException();
                }

                var magicValue2 = reader.ReadUInt32();
                if (magicValue2 != 0)
                {
                    throw new InvalidDataException();
                }

                var blendDescriptions = new BlendDescription[blendsCount];
                for (var i = 0; i < blendsCount; i++)
                {
                    blendDescriptions[i] = BlendDescription.Parse(reader);
                }

                var cliffTextureMappings = new CliffTextureMapping[cliffBlendsCount];
                for (var i = 0; i < cliffBlendsCount; i++)
                {
                    cliffTextureMappings[i] = CliffTextureMapping.Parse(reader);
                }

                return new BlendTileData
                {
                    NumTiles = numTiles,

                    Tiles = tiles,

                    Blends = blends,
                    ThreeWayBlends = threeWayBlends,
                    CliffTextures = cliffTextures,

                    Passability = passability,

                    TextureCellCount = textureCellCount,

                    Textures = textures,

                    MagicValue1 = magicValue1,
                    MagicValue2 = magicValue2,

                    BlendDescriptions = blendDescriptions,

                    ParsedCliffTextureMappingsCount = parsedCliffBlendsCount,
                    CliffTextureMappings = cliffTextureMappings
                };
            }));
        }