]> Dogcows Code - chaz/carfire/blob - CarFire/CarFire/CarFire/MapReader.cs
35089ba6531d7345f15e0a164790f01f81c3d322
[chaz/carfire] / CarFire / CarFire / CarFire / MapReader.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Runtime.Serialization;
5 using System.Text.RegularExpressions;
6 using Microsoft.Xna.Framework;
7 using Microsoft.Xna.Framework.Content;
8 using Microsoft.Xna.Framework.Graphics;
9
10 namespace CarFire
11 {
12 /// <summary>
13 /// This class will be instantiated by the XNA Framework Content
14 /// Pipeline to read cfmap files from binary .xnb format.
15 /// </summary>
16 public class MapReader : ContentTypeReader<Map>
17 {
18 public class ParserException : System.ApplicationException
19 {
20 public ParserException()
21 {
22 }
23
24 public ParserException(string message) :
25 base(message)
26 {
27 }
28
29 public ParserException(string message, System.Exception inner) :
30 base(message, inner)
31 {
32 }
33
34 protected ParserException(SerializationInfo info, StreamingContext context) :
35 base(info, context)
36 {
37 }
38 }
39
40 ContentReader mInput;
41 int mLineNumber = 0;
42 int mExpectedNumberOfLines;
43
44 Map.Data mData;
45
46
47 protected override Map Read(ContentReader input, Map existingInstance)
48 {
49 mInput = input;
50 mExpectedNumberOfLines = mInput.ReadInt32();
51
52 ReadData();
53
54 return new Map(mData);
55 }
56
57
58 #region Private Reading Methods
59
60 string ReadLine()
61 {
62 return mInput.ReadString();
63 }
64
65 void ReadData()
66 {
67 mData = new Map.Data();
68
69 while (mLineNumber < mExpectedNumberOfLines)
70 {
71 string line = ReadLine();
72 mLineNumber++;
73
74 while (line != null)
75 {
76 if (!IsLineSignificant(line)) break;
77
78 string section = Parse.IniSectionHeader(line);
79 if (section != null)
80 {
81 if (section == "metadata")
82 {
83 line = ReadMetadataSection();
84 }
85 else if (section == "maptable")
86 {
87 line = ReadMapTableSection();
88 }
89 else if (section.Length == 1)
90 {
91 line = ReadEntitySection(section[0]);
92 }
93 else
94 {
95 ThrowException("Unknown section", section);
96 }
97 }
98 else
99 {
100 ThrowException("Unexpected text", line);
101 }
102 }
103 }
104 }
105
106 string ReadMetadataSection()
107 {
108 while (mLineNumber < mExpectedNumberOfLines)
109 {
110 string line = ReadLine();
111 mLineNumber++;
112
113 if (!IsLineSignificant(line)) continue;
114
115 string[] pair = Parse.KeyValuePair(line);
116 if (pair != null)
117 {
118 if (pair[0] == "type")
119 {
120 object type = Parse.Constant<Map.Type>(pair[1]);
121 if (type != null)
122 {
123 mData.Type = (Map.Type)type;
124 }
125 else
126 {
127 ThrowException("Invalid type", pair[1]);
128 }
129 }
130 else if (pair[0] == "dimensions")
131 {
132 Point? dimensions = Parse.Coordinates(pair[1]);
133 if (dimensions != null)
134 {
135 mData.Dimensions = dimensions.Value;
136 if (mData.Dimensions.X <= 0 || mData.Dimensions.Y <= 0)
137 {
138 ThrowException("Invalid dimensions", pair[1]);
139 }
140 }
141 else
142 {
143 ThrowException("Invalid value", pair[1]);
144 }
145 }
146 else if (pair[0] == "tileset")
147 {
148 string tileset = Parse.String(pair[1]);
149 if (tileset != null)
150 {
151 mData.Tileset = tileset;
152 }
153 else
154 {
155 ThrowException("Invalid tileset", pair[1]);
156 }
157 }
158 else if (pair[0] == "numplayers")
159 {
160 int[] numPlayers = Parse.Range(pair[1]);
161 if (numPlayers != null)
162 {
163 mData.MinNumPlayers = numPlayers[0];
164 mData.MaxNumPlayers = numPlayers[1];
165 if (mData.MinNumPlayers <= 0 || mData.MaxNumPlayers <= 0 ||
166 mData.MinNumPlayers > mData.MaxNumPlayers)
167 {
168 ThrowException("Invalid range", pair[1]);
169 }
170 }
171 else
172 {
173 ThrowException("Invalid value", pair[1]);
174 }
175 }
176 else if (pair[0] == "author")
177 {
178 string author = Parse.String(pair[1]);
179 if (author != null)
180 {
181 mData.Author = author;
182 }
183 else
184 {
185 ThrowException("Invalid value", pair[1]);
186 }
187 }
188 else if (pair[0] == "levelname")
189 {
190 string level = Parse.String(pair[1]);
191 if (level != null)
192 {
193 mData.Name = level;
194 }
195 else
196 {
197 ThrowException("Invalid value", pair[1]);
198 }
199 }
200 else
201 {
202 Console.WriteLine("Unimplemented key: " + pair[0]);
203 }
204 }
205 else
206 {
207 return line;
208 }
209 }
210
211 return null;
212 }
213
214 string ReadMapTableSection()
215 {
216 if (mData.Dimensions.X == 0 || mData.Dimensions.Y == 0)
217 {
218 ThrowException("Unexpected section", "You must define the map dimensions before this section.");
219 }
220
221 mData.Grid = new char[mData.Dimensions.X, mData.Dimensions.Y];
222
223 int y;
224 for (y = 0; y < mData.Dimensions.Y && mLineNumber < mExpectedNumberOfLines; y++)
225 {
226 string line = ReadLine();
227 mLineNumber++;
228
229 if (line.Length < mData.Dimensions.X)
230 {
231 ThrowException("Not enough characters", "Expecting " + mData.Dimensions.X + " characters.");
232 }
233
234 for (int x = 0; x < mData.Dimensions.X; x++)
235 {
236 mData.Grid[x, y] = line[x];
237 }
238 }
239
240 if (y < mData.Dimensions.Y)
241 {
242 ThrowException("Unexpected ", "");
243 }
244
245 return null;
246 }
247
248 string ReadEntitySection(char entity)
249 {
250 while (mLineNumber < mExpectedNumberOfLines)
251 {
252 string line = ReadLine();
253 mLineNumber++;
254
255 string[] pair = Parse.KeyValuePair(line);
256 if (pair != null)
257 {
258 // TODO
259 }
260 else
261 {
262 return line;
263 }
264 }
265
266 return null;
267 }
268
269 #endregion
270
271
272 #region Private Methods
273
274 bool IsLineSignificant(string line)
275 {
276 if (line.Length == 0 || Regex.IsMatch(line, @"^;|^\s*$")) return false;
277 return true;
278 }
279
280 void ThrowException(string problem, string text)
281 {
282 throw new ParserException(problem + " on line " + mLineNumber + ": " + text);
283 }
284
285 #endregion
286 }
287 }
This page took 0.0429 seconds and 3 git commands to generate.