Example #1
0
        /// <summary>
        /// Loads Terrain from File
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">Path given is not valid</exception>
        /// <exception cref="EndOfDataException">Unexpected end of Data</exception>
        /// <exception cref="FileNotFoundException">File could not be found</exception>
        /// <exception cref="InsufficientPermissionsException">Insufficient Permissions</exception>
        /// <exception cref="IOException">Read / Write Error</exception>
        public static TER LoadFromFile(string path)
        {
            ChunkStream stream = null;

            try {
                stream = new ChunkStream(path, FileMode.Open, FileAccess.Read);
            } catch (ArgumentException ex) {
                Log.Add("Path given is not valid!", LogType.Error);
                throw new ArgumentException("Path given is not valid!", ex);
            } catch (NotSupportedException ex) {
                Log.Add("Path given is not valid!", LogType.Error);
                throw new ArgumentException("Path given is not valid!", ex);
            } catch (PathTooLongException ex) {
                Log.Add("Path given is not valid!", LogType.Error);
                throw new ArgumentException("Path given is not valid!", ex);
            } catch (UnauthorizedAccessException ex) {
                Log.Add("Insufficient Permissions!", LogType.Error);
                throw new InsufficientPermissionsException("Insufficient Permissions!", ex);
            } catch (SecurityException ex) {
                Log.Add("Insufficient Permissions!", LogType.Error);
                throw new InsufficientPermissionsException("Insufficient Permissions!", ex);
            }

            TER terrain = new TER();

            if (!stream.ReadString(4).Equals("TERR"))
            {
                throw new InvalidChunkException("Not a valid Terrain File: " + path);
            }

            switch (stream.ReadInt32())
            {
            case 21:
                terrain.Version = TerrainVersion.SWBF1;
                break;

            case 22:
                terrain.Version = TerrainVersion.SWBF2;
                break;

            default:
                Log.Add("Unknown Terrain Version found!", LogType.Warning);
                terrain.Version = TerrainVersion.Unknown;
                break;
            }

            //Terrain Extent (From Position, To Position);
            terrain.Extent.FromX = stream.ReadInt16();
            terrain.Extent.FromY = stream.ReadInt16();
            terrain.Extent.ToX   = stream.ReadInt16();
            terrain.Extent.ToY   = stream.ReadInt16();

            //Int32, unknown purpose
            stream.SkipBytes(4);

            //16 floats follow, describing the Tile Range of each Texture Layer
            for (int i = 0; i < terrain.Layers.Length; i++)
            {
                //tile range is stored as reciprocal (1/X), e.g. 0.03125 for actually 32
                //to get the true tile size, we have ge the reciprocal again
                // (1 / 32) = 0.03125     (1 / 0.03125) = 32
                terrain.Layers[i].TileRange = 1 / stream.ReadFloat();
            }

            //16 bytes follow, describing mapping type for each layer
            for (int i = 0; i < terrain.Layers.Length; i++)
            {
                terrain.Layers[i].MappingType = stream.ReadByte();
            }

            //unknown purpose of bytes
            stream.SkipBytes(64);

            terrain.HeightMultiplier = stream.ReadFloat();
            terrain.GridScale        = stream.ReadFloat();

            //unknown int32
            stream.SkipBytes(4);

            //Full Map Size (e.g. 256 for a 256x256 Map)
            terrain.GridSize = stream.ReadInt32();

            //unknown int32
            stream.SkipBytes(4);

            //SWBF2 Versions have a byte exactly on this point. purpose unknown
            if (terrain.Version == TerrainVersion.SWBF2)
            {
                stream.SkipBytes(1);
            }

            //16 Texture Layers follow (total length of 1024)
            //char[32]	Diffuse texture name.
            //char[32]  Detail texture name.
            for (int i = 0; i < terrain.Layers.Length; i++)
            {
                terrain.Layers[i].DiffuseTexture = stream.ReadString(32).Trim();
                terrain.Layers[i].DetailTexture  = stream.ReadString(32).Trim();
            }

            //skip water layers
            stream.SkipBytes(1088);

            //unknown bytes
            stream.SkipBytes(524);

            //Terrain Height Data
            Log.Add("Size: " + terrain.GridSize, LogType.Info);

            terrain.RawHeights = new short[terrain.GridSize, terrain.GridSize];

            for (int x = 0; x < terrain.GridSize; x++)
            {
                for (int y = 0; y < terrain.GridSize; y++)
                {
                    terrain.RawHeights[x, y] = stream.ReadInt16();
                }
            }

            stream.Close();

            return(terrain);
        }