Exemple #1
0
        internal static T ParseAsset <T>(BinaryReader reader, MapParseContext context, AssetParseCallback <T> parseCallback)
            where T : Asset
        {
            var assetVersion = reader.ReadUInt16();

            var dataSize      = reader.ReadUInt32();
            var startPosition = reader.BaseStream.Position;
            var endPosition   = dataSize + startPosition;

            context.PushAsset(typeof(T).Name, endPosition);

            var result = parseCallback(assetVersion);

            result.StartPosition = startPosition;
            result.EndPosition   = endPosition;
            result.Version       = assetVersion;

            context.PopAsset();

            if (reader.BaseStream.Position != endPosition)
            {
                throw new InvalidDataException($"Error while parsing asset '{typeof(T).Name}', version {assetVersion}. Expected reader to be at position {endPosition}, but was at {reader.BaseStream.Position}.");
            }

            return(result);
        }
Exemple #2
0
        internal static ScriptOrCondition Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var conditions = new List <ScriptCondition>();

                ParseAssets(reader, context, assetName =>
                {
                    switch (assetName)
                    {
                    case ScriptCondition.AssetName:
                        conditions.Add(ScriptCondition.Parse(reader, context));
                        break;

                    default:
                        throw new InvalidDataException($"Unexpected asset: {assetName}");
                    }
                });

                return new ScriptOrCondition
                {
                    Conditions = conditions.ToArray()
                };
            }));
        }
Exemple #3
0
        internal static EnvironmentData Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, (version, endPosition) =>
            {
                var result = new EnvironmentData();

                if (version >= 3)
                {
                    result.WaterMaxAlphaDepth = reader.ReadSingle();
                    result.DeepWaterAlpha = reader.ReadSingle();
                }

                if (version < 5)
                {
                    result.Unknown = reader.ReadBooleanChecked();
                }

                result.MacroTexture = reader.ReadUInt16PrefixedAsciiString();
                result.CloudTexture = reader.ReadUInt16PrefixedAsciiString();

                if (version >= 4)
                {
                    result.UnknownTexture = reader.ReadUInt16PrefixedAsciiString();
                }

                // Both RA3 Uprising and C&C4 used v6 for this chunk, but RA3 Uprising had an extra texture here.
                if (version >= 6 && reader.BaseStream.Position < endPosition)
                {
                    result.UnknownTexture2 = reader.ReadUInt16PrefixedAsciiString();
                }

                return result;
            }));
        }
Exemple #4
0
        internal static EnvironmentData Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var result = new EnvironmentData();

                if (version >= 3)
                {
                    result.WaterMaxAlphaDepth = reader.ReadSingle();
                    result.DeepWaterAlpha = reader.ReadSingle();
                }

                result.Unknown = reader.ReadBooleanChecked();

                result.MacroTexture = reader.ReadUInt16PrefixedAsciiString();
                result.CloudTexture = reader.ReadUInt16PrefixedAsciiString();

                if (version >= 4)
                {
                    result.UnknownTexture = reader.ReadUInt16PrefixedAsciiString();
                }

                return result;
            }));
        }
Exemple #5
0
        internal static CastleTemplates Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var propertyKey = AssetPropertyKey.Parse(reader, context);

                var count = reader.ReadUInt32();
                var result = new CastleTemplate[count];

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

                CastlePerimeter perimeter = null;
                if (version >= 2)
                {
                    perimeter = CastlePerimeter.Parse(reader, version);
                }

                return new CastleTemplates
                {
                    PropertyKey = propertyKey,
                    Templates = result,
                    Perimeter = perimeter
                };
            }));
        }
Exemple #6
0
        internal static MPPositionInfo Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var result = new MPPositionInfo
                {
                    IsHuman = reader.ReadBooleanChecked(),
                    IsComputer = reader.ReadBooleanChecked()
                };

                if (version > 0)
                {
                    // I'm guessing about what 5 bytes are missing in version 0, compared to version 1.
                    result.LoadAIScript = reader.ReadBooleanChecked();
                }

                result.Team = reader.ReadUInt32();

                if (version > 0)
                {
                    result.SideRestrictions = new string[reader.ReadUInt32()];
                    for (var i = 0; i < result.SideRestrictions.Length; i++)
                    {
                        result.SideRestrictions[i] = reader.ReadUInt16PrefixedAsciiString();
                    }
                }

                return result;
            }));
        }
Exemple #7
0
 internal static Team Parse(BinaryReader reader, MapParseContext context)
 {
     return(new Team
     {
         Properties = AssetPropertyCollection.Parse(reader, context)
     });
 }
Exemple #8
0
        internal static BuildList Parse(BinaryReader reader, MapParseContext context, ushort version, bool mapHasAssetList)
        {
            var result = new BuildList();

            // BFME and C&C3 both used v1 for this chunk, but store the faction name differently :(
            // If the map file has an AssetList chunk, we assume it's C&C3.
            if (mapHasAssetList)
            {
                result.FactionName = reader.ReadUInt16PrefixedAsciiString();
            }
            else
            {
                result.FactionNameProperty = AssetPropertyKey.Parse(reader, context);
            }

            var numBuildListItems = reader.ReadUInt32();

            result.Items = new BuildListItem[numBuildListItems];

            for (var i = 0; i < numBuildListItems; i++)
            {
                result.Items[i] = BuildListItem.Parse(reader, version, 1, mapHasAssetList);
            }

            return(result);
        }
Exemple #9
0
 internal static SkyboxSettings Parse(BinaryReader reader, MapParseContext context)
 {
     return(ParseAsset(reader, context, version => new SkyboxSettings
     {
         Position = reader.ReadVector3(),
         Scale = reader.ReadSingle(),
         Rotation = reader.ReadSingle(),
         TextureScheme = reader.ReadUInt16PrefixedAsciiString()
     }));
 }
Exemple #10
0
 internal static WorldInfo Parse(BinaryReader reader, MapParseContext context)
 {
     return(ParseAsset(reader, context, version =>
     {
         return new WorldInfo
         {
             Properties = AssetPropertyCollection.Parse(reader, context)
         };
     }));
 }
Exemple #11
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);
        }
 internal static GlobalWaterSettings Parse(BinaryReader reader, MapParseContext context)
 {
     return(ParseAsset(reader, context, version =>
     {
         return new GlobalWaterSettings
         {
             ReflectionOn = reader.ReadBooleanUInt32Checked(),
             ReflectionPlaneZ = reader.ReadSingle()
         };
     }));
 }
Exemple #13
0
 internal static SkyboxSettings Parse(BinaryReader reader, MapParseContext context)
 {
     return(ParseAsset(reader, context, version =>
     {
         // TODO
         return new SkyboxSettings
         {
             Unknown = reader.ReadBytes(32)
         };
     }));
 }
Exemple #14
0
        internal static void ParseAssets(BinaryReader reader, MapParseContext context, AssetsParseCallback parseCallback)
        {
            while (reader.BaseStream.Position < context.CurrentEndPosition)
            {
                var assetIndex = reader.ReadUInt32();

                var assetName = context.GetAssetName(assetIndex);

                parseCallback(assetName);
            }
        }
        internal static AssetPropertyCollection Parse(BinaryReader reader, MapParseContext context)
        {
            var numProperties = reader.ReadUInt16();
            var result        = new AssetProperty[numProperties];

            for (var i = 0; i < numProperties; i++)
            {
                result[i] = AssetProperty.Parse(reader, context);
            }

            return(new AssetPropertyCollection(result));
        }
Exemple #16
0
        internal static FogSettings Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var result = new FogSettings();

                // TODO
                result.Unknown = reader.ReadBytes(24);

                return result;
            }));
        }
Exemple #17
0
        internal static AssetPropertyKey Parse(BinaryReader reader, MapParseContext context)
        {
            var propertyType = reader.ReadByteAsEnum <AssetPropertyType>();

            var propertyNameIndex = reader.ReadUInt24();
            var propertyName      = context.GetAssetName(propertyNameIndex);

            return(new AssetPropertyKey
            {
                PropertyType = propertyType,
                Name = propertyName
            });
        }
Exemple #18
0
 internal static MapObject Parse(BinaryReader reader, MapParseContext context)
 {
     return(ParseAsset(reader, context, version =>
     {
         return new MapObject
         {
             Position = reader.ReadVector3(),
             Angle = reader.ReadSingle(),
             RoadType = reader.ReadUInt32AsEnumFlags <RoadType>(),
             TypeName = reader.ReadUInt16PrefixedAsciiString(),
             Properties = AssetPropertyCollection.Parse(reader, context)
         };
     }));
 }
Exemple #19
0
 internal static ScriptCondition Parse(BinaryReader reader, MapParseContext context)
 {
     return(Parse(
                reader,
                context,
                MinimumVersionThatHasInternalName,
                MinimumVersionThatHasEnabledFlag,
                (version, x) =>
     {
         if (version >= MinimumVersionThatHasEnabledFlag)
         {
             x.IsInverted = reader.ReadBooleanUInt32Checked();
         }
     }));
 }
Exemple #20
0
        internal static GlobalLighting Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var time = reader.ReadUInt32AsEnum <TimeOfDay>();

                var lightingConfigurations = new Dictionary <TimeOfDay, GlobalLightingConfiguration>();

                for (var i = 0; i < TimeOfDayValues.Length; i++)
                {
                    lightingConfigurations[TimeOfDayValues[i]] = GlobalLightingConfiguration.Parse(reader, version);
                }

                var shadowColor = MapColorArgb.Parse(reader);

                // TODO: BFME. Overbright? Bloom?
                byte[] unknown = null;
                if (version >= 7 && version < 11)
                {
                    unknown = reader.ReadBytes(version >= 9 ? 4 : 44);
                }

                Vector3?unknown2 = null;
                MapColorArgb?unknown3 = null;
                if (version >= 12)
                {
                    unknown2 = reader.ReadVector3();
                    unknown3 = MapColorArgb.Parse(reader);
                }

                ColorRgbF?noCloudFactor = null;
                if (version >= 8)
                {
                    noCloudFactor = reader.ReadColorRgbF();
                }

                return new GlobalLighting
                {
                    Time = time,
                    LightingConfigurations = lightingConfigurations,
                    ShadowColor = shadowColor,
                    Unknown = unknown,
                    Unknown2 = unknown2,
                    Unknown3 = unknown3,
                    NoCloudFactor = noCloudFactor
                };
            }));
        }
Exemple #21
0
        internal static LibraryMaps Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var values = new string[reader.ReadUInt32()];
                for (var i = 0; i < values.Length; i++)
                {
                    values[i] = reader.ReadUInt16PrefixedAsciiString();
                }

                return new LibraryMaps
                {
                    Values = values
                };
            }));
        }
Exemple #22
0
        internal static HeightMapData Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var mapWidth = reader.ReadUInt32();
                var mapHeight = reader.ReadUInt32();

                var borderWidth = reader.ReadUInt32();

                var perimeterCount = reader.ReadUInt32();
                var perimeters = new HeightMapPerimeter[perimeterCount];

                for (var i = 0; i < perimeterCount; i++)
                {
                    perimeters[i] = new HeightMapPerimeter
                    {
                        Width = reader.ReadUInt32(),
                        Height = reader.ReadUInt32()
                    };
                }

                var area = reader.ReadUInt32();
                if (mapWidth * mapHeight != area)
                {
                    throw new InvalidDataException();
                }

                var elevations = new byte[mapWidth, mapHeight];
                for (var y = 0; y < mapHeight; y++)
                {
                    for (var x = 0; x < mapWidth; x++)
                    {
                        elevations[x, y] = reader.ReadByte();
                    }
                }

                return new HeightMapData
                {
                    Width = mapWidth,
                    Height = mapHeight,
                    BorderWidth = borderWidth,
                    Perimeters = perimeters,
                    Area = area,
                    Elevations = elevations
                };
            }));
        }
Exemple #23
0
        internal static SidesList Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numPlayers = reader.ReadUInt32();
                var players = new Player[numPlayers];

                for (var i = 0; i < numPlayers; i++)
                {
                    players[i] = Player.Parse(reader, context);
                }

                var numTeams = reader.ReadUInt32();
                var teams = new Team[numTeams];

                for (var i = 0; i < numTeams; i++)
                {
                    teams[i] = Team.Parse(reader, context);
                }

                PlayerScriptsList playerScripts = null;

                ParseAssets(reader, context, assetName =>
                {
                    if (assetName != PlayerScriptsList.AssetName)
                    {
                        throw new InvalidDataException();
                    }

                    if (playerScripts != null)
                    {
                        throw new InvalidDataException();
                    }

                    playerScripts = PlayerScriptsList.Parse(reader, context);
                });

                return new SidesList
                {
                    Players = players,
                    Teams = teams,
                    PlayerScripts = playerScripts
                };
            }));
        }
Exemple #24
0
        internal static AssetList Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numAssets = reader.ReadUInt32();

                var items = new AssetListItem[numAssets];
                for (var i = 0; i < numAssets; i++)
                {
                    items[i] = AssetListItem.Parse(reader);
                }

                return new AssetList
                {
                    Items = items
                };
            }));
        }
Exemple #25
0
        internal static TriggerAreas Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numTriggers = reader.ReadUInt32();
                var triggers = new TriggerArea[numTriggers];

                for (var i = 0; i < numTriggers; i++)
                {
                    triggers[i] = TriggerArea.Parse(reader);
                }

                return new TriggerAreas
                {
                    Areas = triggers
                };
            }));
        }
Exemple #26
0
        internal static WaypointsList Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numWaypointPaths = reader.ReadUInt32();
                var waypointPaths = new WaypointPath[numWaypointPaths];

                for (var i = 0; i < numWaypointPaths; i++)
                {
                    waypointPaths[i] = WaypointPath.Parse(reader);
                }

                return new WaypointsList
                {
                    WaypointPaths = waypointPaths
                };
            }));
        }
Exemple #27
0
        internal static StandingWaveAreas Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numAreas = reader.ReadUInt32();
                var areas = new StandingWaveArea[numAreas];

                for (var i = 0; i < numAreas; i++)
                {
                    areas[i] = StandingWaveArea.Parse(reader, version);
                }

                return new StandingWaveAreas
                {
                    Areas = areas
                };
            }));
        }
Exemple #28
0
        internal static NamedCameras Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numNamedCameras = reader.ReadUInt32();
                var cameras = new NamedCamera[numNamedCameras];

                for (var i = 0; i < numNamedCameras; i++)
                {
                    cameras[i] = NamedCamera.Parse(reader);
                }

                return new NamedCameras
                {
                    Cameras = cameras
                };
            }));
        }
Exemple #29
0
        internal static BuildLists Parse(BinaryReader reader, MapParseContext context, bool mapHasAssetList)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numBuildLists = reader.ReadUInt32();
                var buildLists = new BuildList[numBuildLists];

                for (var i = 0; i < numBuildLists; i++)
                {
                    buildLists[i] = BuildList.Parse(reader, context, version, mapHasAssetList);
                }

                return new BuildLists
                {
                    Items = buildLists
                };
            }));
        }
Exemple #30
0
        internal static MissionObjectives Parse(BinaryReader reader, MapParseContext context)
        {
            return(ParseAsset(reader, context, version =>
            {
                var numItems = reader.ReadUInt32();
                var items = new MissionObjective[numItems];

                for (var i = 0; i < numItems; i++)
                {
                    items[i] = MissionObjective.Parse(reader);
                }

                return new MissionObjectives
                {
                    Items = items
                };
            }));
        }