Mercurial > repos > IBDev-IBBoard.WarFoundry.API
annotate api/Factories/Xml/WarFoundryXmlFactory.cs @ 15:306558904c2a
Re #1 - LGPL license all code
* Add LGPL header to all files
* Add COPYING.LGPL and COPYING.GPL with content of license
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 25 Jan 2009 14:50:36 +0000 |
parents | ac232763858b |
children | a99d3b8466ba |
rev | line source |
---|---|
15 | 1 // This file (WarFoundryXmlFactory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 IBBoard. |
0 | 2 // |
15 | 3 // The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license. |
0 | 4 |
5 using System; | |
6 using System.IO; | |
7 using System.Xml; | |
8 using System.Xml.Schema; | |
9 using System.Collections.Generic; | |
10 using System.Text; | |
11 using IBBoard; | |
12 using IBBoard.IO; | |
13 using IBBoard.Lang; | |
14 using IBBoard.Logging; | |
15 using IBBoard.Xml; | |
16 using IBBoard.WarFoundry.API.Requirements; | |
17 using IBBoard.WarFoundry.API.Objects; | |
18 using ICSharpCode.SharpZipLib.Zip; | |
19 | |
20 namespace IBBoard.WarFoundry.API.Factories.Xml | |
21 { | |
22 /// <summary> | |
10 | 23 /// The WarFoundryXmlFactory loads WarFoundry classes from the native "XML in a zip" file format. Files are validated using the schema for the file type, so structurally invalid files should be identified at initial load. |
0 | 24 /// </summary> |
25 public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory | |
26 { | |
27 private Dictionary<IWarFoundryObject, XmlDocument> extraData = new Dictionary<IWarFoundryObject, XmlDocument>(); | |
28 private XmlResolver xmlResolver; | |
29 | |
30 public static AbstractNativeWarFoundryFactory CreateFactory() | |
31 { | |
32 return new WarFoundryXmlFactory(); | |
33 } | |
34 | |
35 protected WarFoundryXmlFactory() : base() | |
36 { | |
37 xmlResolver = new IBBXmlResolver(Constants.ExecutablePath); | |
38 } | |
39 | |
40 protected override bool CheckCanFindArmyFileContent(ZipFile file) | |
41 { | |
42 return file.FindEntry("data.armyx", true) > -1; | |
43 } | |
44 | |
45 protected override bool CheckCanFindSystemFileContent(ZipFile file) | |
46 { | |
47 return file.FindEntry("data.systemx", true) > -1; | |
48 } | |
49 | |
50 protected override bool CheckCanFindRaceFileContent(ZipFile file) | |
51 { | |
52 return file.FindEntry("data.racex", true) > -1; | |
53 } | |
54 | |
55 protected XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName) | |
56 { | |
57 XmlDocument doc = CreateXmlDocumentFromStream(stream); | |
58 XmlElement elem = (XmlElement)doc.LastChild; | |
59 | |
60 if (!elem.Name.Equals(elementName.Value)) | |
61 { | |
62 throw new InvalidFileException(String.Format("Root element of XML was not valid. Expected {0} but got {1}", elementName.Value, elem.Name)); | |
63 } | |
64 | |
65 return elem; | |
66 } | |
67 | |
68 protected override Stream GetArmyDataStream(ZipFile file) | |
69 { | |
70 return file.GetInputStream(file.FindEntry("data.armyx", true)); | |
71 } | |
72 | |
73 protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream) | |
74 { | |
75 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT); | |
76 return CreateArmyFromElement(file, elem); | |
77 } | |
78 | |
79 private Army CreateArmyFromElement(ZipFile file, XmlElement elem) | |
80 { | |
81 string name = elem.GetAttribute("name"); | |
82 string systemID = elem.GetAttribute("gameSystem"); | |
83 GameSystem system = WarFoundryLoader.GetDefault().GetGameSystem(systemID); | |
84 string raceID = elem.GetAttribute("race"); | |
85 Race race = WarFoundryLoader.GetDefault().GetRace(system, raceID); | |
86 string pointsString = elem.GetAttribute("maxPoints"); | |
87 int points = 0; | |
88 | |
89 try | |
90 { | |
91 points = int.Parse(pointsString); | |
92 } | |
93 catch(FormatException) | |
94 { | |
95 throw new FormatException("Attribute 'maxPoints' of army '"+name+"' was not a valid number"); | |
96 } | |
97 | |
10 | 98 Army army = new Army(race, name, points, file); |
0 | 99 extraData[army] = elem.OwnerDocument; |
100 return army; | |
101 } | |
102 | |
103 protected override Stream GetGameSystemDataStream (ZipFile file) | |
104 { | |
105 return file.GetInputStream(file.FindEntry("data.systemx", true)); | |
106 } | |
107 | |
108 protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream) | |
109 { | |
110 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT); | |
111 LogNotifier.Debug(GetType(), "Create GameSystem"); | |
112 return CreateSystemFromElement(file, elem); | |
113 } | |
114 | |
115 private GameSystem CreateSystemFromElement(ZipFile file, XmlElement elem) | |
116 { | |
117 string id = elem.GetAttribute("id"); | |
118 string name = elem.GetAttribute("name"); | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
119 GameSystem system = new GameSystem(id, name, this); |
0 | 120 extraData[system] = elem.OwnerDocument; |
121 return system; | |
122 } | |
123 | |
124 protected override Stream GetRaceDataStream (ZipFile file) | |
125 { | |
126 return file.GetInputStream(file.FindEntry("data.racex", true)); | |
127 } | |
128 | |
129 protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream) | |
130 { | |
131 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT); | |
132 LogNotifier.Debug(GetType(), "Create Race"); | |
133 return CreateRaceFromElement(file, elem); | |
134 } | |
135 | |
136 private Race CreateRaceFromElement(ZipFile file, XmlElement elem) | |
137 { | |
138 string id = elem.GetAttribute("id"); | |
139 string subid = elem.GetAttribute("subid"); | |
140 string systemID = elem.GetAttribute("system"); | |
141 string name = elem.GetAttribute("name"); | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
142 Race race = new Race(id, subid, name, systemID, this); |
0 | 143 extraData[race] = elem.OwnerDocument; |
144 return race; | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
145 } |
0 | 146 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
147 public override void CompleteLoading(IWarFoundryStagedLoadObject obj) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
148 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
149 LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
150 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
151 if (obj is GameSystem) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
152 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
153 CompleteLoading((GameSystem)obj); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
154 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
155 else if (obj is Race) |
0 | 156 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
157 CompleteLoading((Race)obj); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
158 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
159 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
160 |
10 | 161 public XmlNode GetExtraData(IWarFoundryObject obj) |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
162 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
163 XmlDocument extra = null; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
164 extraData.TryGetValue(obj, out extra); |
10 | 165 XmlNode node = null; |
166 | |
167 if (extra !=null) | |
168 { | |
169 node = extra.LastChild; | |
170 } | |
171 | |
172 return node; | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
173 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
174 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
175 public void CompleteLoading(GameSystem system) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
176 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
177 if (system.IsFullyLoaded) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
178 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
179 LogNotifier.DebugFormat(GetType(), "Object of type GameSystem with ID {0} is already fully loaded", system.ID); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
180 return; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
181 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
182 |
10 | 183 XmlNode elem = GetExtraData(system); |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
184 XmlNode catsElem = elem.FirstChild; |
10 | 185 LoadCategoriesForSystem(system, elem); |
186 | |
187 XmlElement statsElem = (XmlElement)catsElem.NextSibling; | |
188 LoadSystemStatsFromElement(statsElem, system); | |
189 string defaultStatsID = statsElem.GetAttribute("defaultStats"); | |
190 | |
191 LogNotifier.DebugFormat(GetType(), "Completed loading of GameSystem with ID {0}", system.Name); | |
192 system.StandardSystemStatsID = defaultStatsID; | |
193 system.SetAsFullyLoaded(); | |
194 } | |
195 | |
196 private void LoadCategoriesForSystem(GameSystem system, XmlNode elem) | |
197 { | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
198 WarFoundryObject tempObj; |
10 | 199 |
200 foreach (XmlElement cat in elem.SelectNodes("//"+WarFoundryXmlElementName.CATEGORY_ELEMENT.Value)) | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
201 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
202 tempObj = CreateObjectFromElement(cat); |
0 | 203 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
204 if (tempObj is Category) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
205 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
206 system.AddCategory((Category)tempObj); |
0 | 207 } |
208 else | |
209 { | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
210 LogNotifier.WarnFormat(GetType(), "Object for string {0} was not of type Category", cat.OuterXml); |
0 | 211 } |
212 } | |
213 } | |
214 | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
215 public void CompleteLoading(Race race) |
0 | 216 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
217 if (race.IsFullyLoaded) |
0 | 218 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
219 LogNotifier.DebugFormat(GetType(), "Object of type Race with ID {0} is already fully loaded", race.ID); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
220 return; |
0 | 221 } |
222 | |
10 | 223 XmlNode elem = GetExtraData(race); |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
224 XmlNode colNode = elem.FirstChild; |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
225 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
226 foreach (XmlElement node in colNode.ChildNodes) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
227 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
228 UnitType type = CreateUnitTypeFromElement(node, race, race.GameSystem); |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
229 race.AddUnitType(type); |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
230 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
231 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
232 colNode = colNode.NextSibling; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
233 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
234 if (colNode!=null && colNode.Name == WarFoundryXmlElementName.CATEGORIES_ELEMENT.Value) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
235 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
236 foreach (XmlElement node in colNode.ChildNodes) |
0 | 237 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
238 race.AddCategory(CreateCategoryFromElement(node)); |
0 | 239 } |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
240 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
241 colNode = colNode.NextSibling; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
242 } |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
243 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
244 if (colNode!=null && colNode.Name == WarFoundryXmlElementName.RACE_EQUIPMENT_ITEMS_ELEMENT.Value) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
245 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
246 foreach (XmlElement node in colNode.ChildNodes) |
0 | 247 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
248 EquipmentItem item = CreateEquipmentItemFromElement(node, race); |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
249 race.AddEquipmentItem(item); |
0 | 250 } |
251 } | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
252 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
253 Dictionary<string, Ability> raceAbilities = new Dictionary<string, Ability>(); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
254 //TODO: Load abilities |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
255 race.SetAbilities(raceAbilities); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
256 race.SetAsFullyLoaded(); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
257 LogNotifier.DebugFormat(GetType(), "Completed loading of Race with ID {0}", race.Name); |
0 | 258 } |
259 | |
260 protected XmlDocument CreateXmlDocumentFromStream(Stream stream) | |
261 { | |
262 XmlDocument doc = new XmlDocument(); | |
263 XmlReaderSettings settings = new XmlReaderSettings(); | |
264 settings.XmlResolver = xmlResolver; | |
265 settings.ValidationType = ValidationType.DTD; | |
266 settings.ProhibitDtd = false; | |
267 settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod); | |
268 XmlReader reader = XmlReader.Create(stream, settings); | |
269 | |
270 try | |
271 { | |
272 doc.Load(reader); | |
273 } | |
274 //Don't catch XMLSchemaExceptions - let them get thrown out | |
275 finally | |
276 { | |
277 reader.Close(); | |
278 } | |
279 | |
280 if (doc.ChildNodes.Count!=3) | |
281 { | |
282 throw new InvalidFileException(Translation.GetTranslation("ErrorInvalidXmlFile", "XML file was not a valid XML file. It should contain three child nodes - XML definition, DocType and root node.")); | |
283 } | |
284 | |
285 return doc; | |
286 } | |
287 | |
288 protected XmlDocument CreateXmlDocumentFromString(string xmlString) | |
289 { | |
290 XmlReaderSettings settings = new XmlReaderSettings(); | |
291 settings.XmlResolver = xmlResolver; | |
292 settings.ValidationType = ValidationType.DTD; | |
293 settings.ProhibitDtd = false; | |
294 settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod); | |
295 XmlReader reader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(xmlString)), settings); | |
296 XmlDocument doc = new XmlDocument(); | |
297 | |
298 try | |
299 { | |
300 doc.Load(reader); | |
301 } | |
302 catch(XmlSchemaException ex) | |
303 { | |
304 throw new InvalidFileException(Translation.GetTranslation("ErrorInvalidXmlString", "Failed to parse invalid XML string"), ex); | |
305 } | |
306 finally | |
307 { | |
308 //We might not need to make sure the memory stream is closed, but do it just in case | |
309 reader.Close(); | |
310 } | |
311 | |
312 if (doc.ChildNodes.Count!=3) | |
313 { | |
314 throw new InvalidFileException(String.Format(Translation.GetTranslation("ErrorInvalidXmlFile", "XML string was not a valid XML file. It should contain three child nodes - XML definition, DocType and root node."))); | |
315 } | |
316 | |
317 return doc; | |
318 } | |
319 | |
320 private WarFoundryObject CreateObjectFromElement(XmlElement elem) | |
321 { | |
322 WarFoundryObject obj = null; | |
323 LogNotifier.DebugFormat(GetType(), "Create object for <{0}>", elem.Name); | |
324 | |
325 if (elem.Name.Equals(WarFoundryXmlElementName.CATEGORY_ELEMENT.Value)) | |
326 { | |
327 LogNotifier.Debug(GetType(), "Create Category"); | |
328 obj = CreateCategoryFromElement(elem); | |
329 } | |
330 else | |
331 { | |
332 LogNotifier.Debug(GetType(), "No match"); | |
333 } | |
334 | |
335 return obj; | |
336 } | |
337 | |
338 private Category CreateCategoryFromElement(XmlElement elem) | |
339 { | |
340 string id = elem.GetAttribute("id"); | |
341 string name = elem.GetAttribute("name"); | |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
342 int minPc, maxPc, minPts, maxPts, minChoices, maxChoices, baseValue, incValue, incAmount; |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
343 minPc = GetIntValueFromAttribute(elem, "minPercentage"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
344 maxPc = GetIntValueFromAttribute(elem, "maxPercentage"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
345 minPts = GetIntValueFromAttribute(elem, "minPoints"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
346 maxPts = GetIntValueFromAttribute(elem, "maxPoints"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
347 minChoices = GetIntValueFromAttribute(elem, "minChoices"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
348 maxChoices = GetIntValueFromAttribute(elem, "maxChoices"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
349 baseValue = GetIntValueFromAttribute(elem, "baseValue"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
350 incValue = GetIntValueFromAttribute(elem, "incValue"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
351 incAmount = GetIntValueFromAttribute(elem, "incAmount"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
352 |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
353 return new Category(id, name, minPts, maxPts, minPc, maxPc, minChoices, maxChoices, baseValue, incValue, incAmount); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
354 } |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
355 |
10 | 356 private int GetIntValueFromAttribute(XmlElement elem, string attributeName) |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
357 { |
0 | 358 try |
359 { | |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
360 return int.Parse(elem.GetAttribute(attributeName)); |
0 | 361 } |
362 catch(FormatException) | |
363 { | |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
364 throw new FormatException(String.Format("Attribute '{0}' of {1} with ID {2} was not a valid number", attributeName, elem.Name, elem.GetAttribute("id"))); |
0 | 365 } |
366 } | |
367 | |
368 private UnitType CreateUnitTypeFromElement(XmlElement elem, Race parentRace, GameSystem system) | |
369 { | |
370 string id = elem.GetAttribute("id"); | |
371 string name = elem.GetAttribute("typeName"); | |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
372 UnitType type = new UnitType(id, name, parentRace); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
373 type.MinNumber = GetIntValueFromAttribute(elem, "minNum"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
374 type.MaxNumber = GetIntValueFromAttribute(elem, "maxNum"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
375 type.MinSize = GetIntValueFromAttribute(elem, "minSize"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
376 type.MaxSize = GetIntValueFromAttribute(elem, "maxSize"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
377 //TODO: Add base size |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
378 type.CostPerTrooper = GetIntValueFromAttribute(elem, "points"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
379 type.BaseUnitCost = GetIntValueFromAttribute(elem, "unitPoints"); |
0 | 380 |
381 XmlNode node = elem.FirstChild; | |
382 | |
383 foreach(XmlElement cat in node.ChildNodes) | |
384 { | |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
385 string catID = cat.GetAttribute("catID"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
386 type.AddCategory(parentRace.GetCategory(catID)); |
0 | 387 } |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
388 |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
389 string mainCatID = elem.GetAttribute("cat"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
390 type.MainCategory = parentRace.GetCategory(mainCatID); |
0 | 391 node = node.NextSibling; |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
392 type.UnitStats = ParseUnitStats((XmlElement)node, system); |
0 | 393 //TODO: Add unit requirements |
394 | |
395 return type; | |
396 } | |
397 | |
398 private Stats ParseUnitStats(XmlElement elem, GameSystem system) | |
399 { | |
400 List<Stat> statsList = new List<Stat>(); | |
401 String statsID = elem.GetAttribute("statSet"); | |
402 SystemStats statsSet; | |
403 | |
404 if (statsID == "") | |
405 { | |
406 statsSet = system.StandardSystemStats; | |
407 } | |
408 else | |
409 { | |
6 | 410 statsSet = system.GetSystemStatsForID(statsID); |
0 | 411 } |
412 | |
413 Stats stats = new Stats(statsSet); | |
414 | |
415 foreach (XmlElement stat in elem.ChildNodes) | |
416 { | |
417 String statID = stat.GetAttribute("name"); | |
418 StatSlot slot = statsSet[statID]; | |
419 | |
420 if (slot!=null) | |
421 { | |
422 statsList.Add(new Stat(slot, stat.InnerText)); | |
423 } | |
424 else | |
425 { | |
426 throw new InvalidFileException("The stat "+statID+" was not found in stats set "+statsID); | |
427 } | |
428 } | |
429 | |
430 stats.SetStats(statsList); | |
431 | |
432 return stats; | |
433 } | |
434 | |
6 | 435 private void LoadSystemStatsFromElement(XmlElement elem, GameSystem system) |
0 | 436 { |
437 foreach (XmlElement stats in elem.ChildNodes) | |
438 { | |
439 SystemStats sysStats = CreateSystemStatsFromElement(stats); | |
6 | 440 system.AddSystemStats(sysStats); |
0 | 441 } |
442 } | |
443 | |
444 private SystemStats CreateSystemStatsFromElement(XmlElement elem) | |
445 { | |
446 List<StatSlot> slots = new List<StatSlot>(); | |
447 string id = elem.GetAttribute("id"); | |
448 | |
449 foreach (XmlElement slot in elem.ChildNodes) | |
450 { | |
451 StatSlot statSlot = new StatSlot(slot.GetAttribute("name")); | |
452 slots.Add(statSlot); | |
453 } | |
454 | |
455 return new SystemStats(id, slots.ToArray()); | |
456 } | |
457 | |
458 private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race) | |
459 { | |
460 string id = elem.GetAttribute("id"); | |
461 string name = elem.GetAttribute("name"); | |
462 float cost = 0, min = 0, max = 0; | |
463 ArmourType armourType; | |
464 | |
465 try | |
466 { | |
467 cost = float.Parse(elem.GetAttribute("cost")); | |
468 } | |
469 catch(FormatException) | |
470 { | |
471 throw new FormatException("Attribute 'cost' of equipment item "+id+" was not a valid number"); | |
472 } | |
473 | |
474 try | |
475 { | |
476 min = float.Parse(elem.GetAttribute("min")); | |
477 } | |
478 catch(FormatException) | |
479 { | |
480 throw new FormatException("Attribute 'min' of equipment item "+id+" was not a valid number"); | |
481 } | |
482 | |
483 try | |
484 { | |
485 max = float.Parse(elem.GetAttribute("max")); | |
486 } | |
487 catch(FormatException) | |
488 { | |
489 throw new FormatException("Attribute 'max' of equipment item "+id+" was not a valid number"); | |
490 } | |
491 | |
492 try | |
493 { | |
494 armourType = (ArmourType)Enum.Parse(typeof(ArmourType), elem.GetAttribute("armourType")); | |
495 } | |
496 catch(FormatException) | |
497 { | |
498 throw new InvalidFileException("Attribute 'armourType' of equipment "+id+" was not a valid value from the enumeration"); | |
499 } | |
500 | |
501 if (elem.ChildNodes.Count>0) | |
502 { | |
503 //It has stats! | |
504 //TODO: Parse equipment stats | |
505 } | |
506 | |
507 return new EquipmentItem(id, name, cost, min, max, armourType, race); | |
508 } | |
509 | |
510 private void ValidationEventMethod(object sender, ValidationEventArgs e) | |
511 { | |
512 //TODO: Fire a validation failure event | |
513 LogNotifier.WarnFormat(GetType(), "Validation Error: {0}", e.Message); | |
514 } | |
515 } | |
516 } |