X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fcarfire;a=blobdiff_plain;f=CarFire%2FCarFire%2FCarFire%2FMapReader.cs;fp=CarFire%2FCarFire%2FCarFire%2FMapReader.cs;h=35089ba6531d7345f15e0a164790f01f81c3d322;hp=0000000000000000000000000000000000000000;hb=c5daf1d9adca0c3a826dfa2ac7b6d4f8a64c84a3;hpb=14e69b6fff5171d3362c88fdaf00edf6ca4f6a13 diff --git a/CarFire/CarFire/CarFire/MapReader.cs b/CarFire/CarFire/CarFire/MapReader.cs new file mode 100644 index 0000000..35089ba --- /dev/null +++ b/CarFire/CarFire/CarFire/MapReader.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text.RegularExpressions; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace CarFire +{ + /// + /// This class will be instantiated by the XNA Framework Content + /// Pipeline to read cfmap files from binary .xnb format. + /// + public class MapReader : ContentTypeReader + { + public class ParserException : System.ApplicationException + { + public ParserException() + { + } + + public ParserException(string message) : + base(message) + { + } + + public ParserException(string message, System.Exception inner) : + base(message, inner) + { + } + + protected ParserException(SerializationInfo info, StreamingContext context) : + base(info, context) + { + } + } + + ContentReader mInput; + int mLineNumber = 0; + int mExpectedNumberOfLines; + + Map.Data mData; + + + protected override Map Read(ContentReader input, Map existingInstance) + { + mInput = input; + mExpectedNumberOfLines = mInput.ReadInt32(); + + ReadData(); + + return new Map(mData); + } + + + #region Private Reading Methods + + string ReadLine() + { + return mInput.ReadString(); + } + + void ReadData() + { + mData = new Map.Data(); + + while (mLineNumber < mExpectedNumberOfLines) + { + string line = ReadLine(); + mLineNumber++; + + while (line != null) + { + if (!IsLineSignificant(line)) break; + + string section = Parse.IniSectionHeader(line); + if (section != null) + { + if (section == "metadata") + { + line = ReadMetadataSection(); + } + else if (section == "maptable") + { + line = ReadMapTableSection(); + } + else if (section.Length == 1) + { + line = ReadEntitySection(section[0]); + } + else + { + ThrowException("Unknown section", section); + } + } + else + { + ThrowException("Unexpected text", line); + } + } + } + } + + string ReadMetadataSection() + { + while (mLineNumber < mExpectedNumberOfLines) + { + string line = ReadLine(); + mLineNumber++; + + if (!IsLineSignificant(line)) continue; + + string[] pair = Parse.KeyValuePair(line); + if (pair != null) + { + if (pair[0] == "type") + { + object type = Parse.Constant(pair[1]); + if (type != null) + { + mData.Type = (Map.Type)type; + } + else + { + ThrowException("Invalid type", pair[1]); + } + } + else if (pair[0] == "dimensions") + { + Point? dimensions = Parse.Coordinates(pair[1]); + if (dimensions != null) + { + mData.Dimensions = dimensions.Value; + if (mData.Dimensions.X <= 0 || mData.Dimensions.Y <= 0) + { + ThrowException("Invalid dimensions", pair[1]); + } + } + else + { + ThrowException("Invalid value", pair[1]); + } + } + else if (pair[0] == "tileset") + { + string tileset = Parse.String(pair[1]); + if (tileset != null) + { + mData.Tileset = tileset; + } + else + { + ThrowException("Invalid tileset", pair[1]); + } + } + else if (pair[0] == "numplayers") + { + int[] numPlayers = Parse.Range(pair[1]); + if (numPlayers != null) + { + mData.MinNumPlayers = numPlayers[0]; + mData.MaxNumPlayers = numPlayers[1]; + if (mData.MinNumPlayers <= 0 || mData.MaxNumPlayers <= 0 || + mData.MinNumPlayers > mData.MaxNumPlayers) + { + ThrowException("Invalid range", pair[1]); + } + } + else + { + ThrowException("Invalid value", pair[1]); + } + } + else if (pair[0] == "author") + { + string author = Parse.String(pair[1]); + if (author != null) + { + mData.Author = author; + } + else + { + ThrowException("Invalid value", pair[1]); + } + } + else if (pair[0] == "levelname") + { + string level = Parse.String(pair[1]); + if (level != null) + { + mData.Name = level; + } + else + { + ThrowException("Invalid value", pair[1]); + } + } + else + { + Console.WriteLine("Unimplemented key: " + pair[0]); + } + } + else + { + return line; + } + } + + return null; + } + + string ReadMapTableSection() + { + if (mData.Dimensions.X == 0 || mData.Dimensions.Y == 0) + { + ThrowException("Unexpected section", "You must define the map dimensions before this section."); + } + + mData.Grid = new char[mData.Dimensions.X, mData.Dimensions.Y]; + + int y; + for (y = 0; y < mData.Dimensions.Y && mLineNumber < mExpectedNumberOfLines; y++) + { + string line = ReadLine(); + mLineNumber++; + + if (line.Length < mData.Dimensions.X) + { + ThrowException("Not enough characters", "Expecting " + mData.Dimensions.X + " characters."); + } + + for (int x = 0; x < mData.Dimensions.X; x++) + { + mData.Grid[x, y] = line[x]; + } + } + + if (y < mData.Dimensions.Y) + { + ThrowException("Unexpected ", ""); + } + + return null; + } + + string ReadEntitySection(char entity) + { + while (mLineNumber < mExpectedNumberOfLines) + { + string line = ReadLine(); + mLineNumber++; + + string[] pair = Parse.KeyValuePair(line); + if (pair != null) + { + // TODO + } + else + { + return line; + } + } + + return null; + } + + #endregion + + + #region Private Methods + + bool IsLineSignificant(string line) + { + if (line.Length == 0 || Regex.IsMatch(line, @"^;|^\s*$")) return false; + return true; + } + + void ThrowException(string problem, string text) + { + throw new ParserException(problem + " on line " + mLineNumber + ": " + text); + } + + #endregion + } +}