/[MorrowindCustomClothingSlotCreator]/trunk/libTES3FileFormat/PlugingClothing.cs
ViewVC logotype

Contents of /trunk/libTES3FileFormat/PlugingClothing.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 37 - (show annotations) (download)
Sat Jul 30 13:42:33 2011 UTC (8 years, 6 months ago) by william
File size: 19362 byte(s)
*** work out properly saving the data (don't append when overwriting)

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6 using System.Diagnostics;
7 using System.Windows.Forms;
8
9 namespace libTES3FileFormat
10 {
11
12 public enum ClothingTypes
13 {
14 Pants, /* 0 */
15 Shoes, /* 1 */
16 Shirt, /* 2 */
17 Belt, /* 3 */
18 Robe, /* 4 */
19 RightGlove, /* 5 */
20 LeftGlove, /* 6 */
21 Skirt, /* 7 */
22 Ring, /* 8 */
23 Amulet, /* 9 */
24 }
25
26 public interface IClothingEntry : IOffset
27 {
28 byte[] CLOT_MAGIC { get; } // 4bytes, CLOT
29 byte[] CLOT_SIZE { get; set; } // 12 bytes
30
31 byte[] CLOT_NAME_MAGIC { get; } // 4bytes, NAME
32 int CLOT_NAME_LENGTH { get; }//4 bytes, name length
33 string CLOT_NAME { get; set; } // variable length, null terminated
34
35 byte[] CLOT_MODL_MAGIC { get; } // 4bytes, MODL
36 int CLOT_MODL_LENGTH { get; }//4 bytes, MODL length
37 string CLOT_MODL { get; set; } // variable length, null terminated
38
39 byte[] CLOT_FULLNAME_MAGIC { get; } // 4bytes, FNAM
40 int CLOT_FULLNAME_LENGTH { get; }//4 bytes, FNAM length
41 string CLOT_FULLNAME { get; set; } // variable length, null terminated
42
43 byte[] CLOT_CTDT_MAGIC { get; } // 4bytes, CTDT
44 int CLOT_CTDT_TYPE { get; set; }//4 bytes
45 float CLOT_CTDT_WEIGHT { get; set; }//4 bytes
46 short CLOT_CTDT_VALUE { get; set; }//2 bytes
47 short CLOT_CTDT_ENCHANTPTS { get; set; }//2 bytes
48
49 byte[] CLOT_OTHER_DATA { get; set; } // the rest of the clothing data entry
50 }
51 public class ClothingEntry : IClothingEntry, IComparable
52 {
53 internal EntryCommitEvent<ClothingEntry> OnEntryCommitEvent;
54
55 //internal BinaryWriter writer = null;
56
57 public bool Commit(IPluginDataClothing pluginData)
58 {
59 pluginData.ClothingSection.ClothingEntries[this.CLOT_NAME] = this;
60 return true;
61 }
62
63
64 internal bool WriteCommit(ICommitWriter commit_writer)
65 {
66 bool ret = true;
67 BinaryWriter bw = commit_writer.GetWriter();
68 if (bw == null) return false;
69 bw.Seek(this.Offset, SeekOrigin.Begin);
70 // write out the data
71 try
72 {
73 bw.Write(this.CLOT_MAGIC);
74 bw.Write(this.CLOT_SIZE);
75
76 bw.Write(this.CLOT_NAME_MAGIC);
77 bw.Write(this.CLOT_NAME_LENGTH);
78 bw.Write(ASCIIEncoding.ASCII.GetBytes(this.CLOT_NAME));
79
80 bw.Write(this.CLOT_MODL_MAGIC);
81 bw.Write(this.CLOT_MODL_LENGTH);
82 bw.Write(ASCIIEncoding.ASCII.GetBytes(this.CLOT_MODL));
83
84 bw.Write(this.CLOT_FULLNAME_MAGIC);
85 bw.Write(this.CLOT_FULLNAME_LENGTH);
86 bw.Write(ASCIIEncoding.ASCII.GetBytes(this.CLOT_FULLNAME));
87
88 bw.Write(this.CLOT_CTDT_MAGIC);
89 bw.Write(this.CLOT_CTDT_SIZE);
90 bw.Write(this.CLOT_CTDT_TYPE);
91 bw.Write(this.CLOT_CTDT_WEIGHT);
92 bw.Write(this.CLOT_CTDT_VALUE);
93 bw.Write(this.CLOT_CTDT_ENCHANTPTS);
94
95 bw.Write(this.CLOT_OTHER_DATA);
96 }
97 catch (Exception ex) { Console.WriteLine(ex.ToString()); ret = false; }
98 return ret;
99 }
100
101 #region IComparable Members
102 public int CompareTo(object obj) { return this.CLOT_NAME.CompareTo((obj as ClothingEntry).CLOT_NAME); }
103 #endregion
104 public ClothingEntry()
105 {
106 this.Offset = 0;
107 this.CLOT_SIZE = new byte[12];
108 this.CLOT_NAME = "";
109 this.CLOT_MODL = "";
110 this.CLOT_FULLNAME = "";
111 this.CLOT_CTDT_TYPE = (int)ClothingTypes.Amulet;
112 this.CLOT_CTDT_WEIGHT = 0;
113 this.CLOT_CTDT_VALUE = 0;
114 this.CLOT_CTDT_ENCHANTPTS = 0;
115 this.CLOT_OTHER_DATA = new byte[0];
116 }
117 #region IOffset Members
118 private int _Offset;
119 public int Offset { get { return _Offset; } set { _Offset = value; } }
120 #endregion
121 #region IClothingEntry Members
122 public byte[] CLOT_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("CLOT"); } } // 4bytes, CLOT
123 private byte[] _CLOT_SIZE;
124 public byte[] CLOT_SIZE { get { return _CLOT_SIZE; } set { _CLOT_SIZE = value; Debug.Assert(value.Length == 12, "Excepted CLOT_SIZE of 12 bytes. Found: " + value.Length + " bytes"); } }// 12 bytes
125
126 public byte[] CLOT_NAME_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("NAME"); } } // 4bytes, NAME
127 public int CLOT_NAME_LENGTH { get { return CLOT_NAME.Length; } }//4 bytes, name length
128 private string _CLOT_NAME;
129 public string CLOT_NAME { get { return _CLOT_NAME; } set { _CLOT_NAME = value; } } // variable length, null terminated
130
131 public byte[] CLOT_MODL_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("MODL"); } } // 4bytes, MODL
132 public int CLOT_MODL_LENGTH { get { return CLOT_MODL.Length; } }//4 bytes, MODL length
133 private string _CLOT_MODL;
134 public string CLOT_MODL { get { return _CLOT_MODL; } set { _CLOT_MODL = value; } } // variable length, null terminated
135
136 public byte[] CLOT_FULLNAME_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("FNAM"); } } // 4bytes, FNAM
137 public int CLOT_FULLNAME_LENGTH { get { return CLOT_FULLNAME.Length; } }//4 bytes, FNAM length
138 private string _CLOT_FULLNAME;
139 public string CLOT_FULLNAME { get { return _CLOT_FULLNAME; } set { _CLOT_FULLNAME = value; } } // variable length, null terminated
140
141 public byte[] CLOT_CTDT_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("CTDT"); } } // 4bytes, CTDT
142
143 private int _CLOT_CTDT_SIZE;
144 private int _CLOT_CTDT_TYPE;
145 private float _CLOT_CTDT_WEIGHT;
146 private short _CLOT_CTDT_VALUE;
147 private short _CLOT_CTDT_ENCHANTPTS;
148
149 public int CLOT_CTDT_SIZE { get { return _CLOT_CTDT_SIZE; } set { _CLOT_CTDT_SIZE = value; } }//4 bytes
150
151 public int CLOT_CTDT_TYPE { get { return _CLOT_CTDT_TYPE; } set { _CLOT_CTDT_TYPE = value; } }//4 bytes
152 public float CLOT_CTDT_WEIGHT { get { return _CLOT_CTDT_WEIGHT; } set { _CLOT_CTDT_WEIGHT = value; } }//4 bytes
153 public short CLOT_CTDT_VALUE { get { return _CLOT_CTDT_VALUE; } set { _CLOT_CTDT_VALUE = value; } }//2 bytes
154 public short CLOT_CTDT_ENCHANTPTS { get { return _CLOT_CTDT_ENCHANTPTS; } set { _CLOT_CTDT_ENCHANTPTS = value; } }//2 bytes
155
156 private byte[] _CLOT_OTHER_DATA;
157 public byte[] CLOT_OTHER_DATA { get { return _CLOT_OTHER_DATA; } set { _CLOT_OTHER_DATA = value; } } // the rest of the clothing data entry
158 #endregion
159
160
161 }
162
163 public interface IPlugingClothing : IParse, ICommit, IAsBytes, ISizeOffset
164 {
165 Dictionary<string, ClothingEntry> ClothingEntries { get; }
166 //bool CommitEntry(ClothingEntry entry);
167 }
168 public class PlugingClothing : IPlugingClothing, ICommitParseAsBytes
169 {
170 private ConsoleLog Log;
171 private const string CLOTHING_MAGIC = "\0CLOT";
172 private const string CLOTHING_NAME_MAGIC = "NAME";
173 MemoryStream reader = new MemoryStream();
174 private List<int> SectionOffsets = new List<int>();
175 public PlugingClothing()
176 {
177 this.reader = new MemoryStream();
178 this.Offset = 0;
179 this.Size = 0;
180 this.SectionOffsets = new List<int>();
181 this.ClothingEntries = new Dictionary<string, ClothingEntry>();
182 }
183 public PlugingClothing(BinaryReader br, List<int> SectionOffsets, bool ReadOnly, ConsoleLog Log)
184 : this()
185 {
186 this.Log = Log;
187 br.BaseStream.Seek(0, SeekOrigin.Begin);
188 //this.Offset = offset;
189 //this.Size = size;
190 this.SectionOffsets = SectionOffsets;
191 this.reader = new MemoryStream(br.ReadBytes((int)br.BaseStream.Length), 0, (int)br.BaseStream.Length);
192 this.Parse(this.reader);
193 }
194 #region IPlugingClothing Members
195 private Dictionary<string, ClothingEntry> _ClothingEntries;
196 public Dictionary<string, ClothingEntry> ClothingEntries
197 {
198 get { return _ClothingEntries; }
199 private set { _ClothingEntries = value; }
200 }
201
202 #endregion
203
204 internal bool CommitEntry(ClothingEntry entry, ICommitWriter writer)
205 {
206 bool ret = false;
207 //if (writer == null) writer = new BinaryWriter(this.reader);
208
209 ret = entry.WriteCommit(writer);
210 return ret;
211 }
212 internal bool CommitAllEntries(ICommitWriter writer)
213 {
214 bool ret = false;
215 foreach (KeyValuePair<string, ClothingEntry> key_pair in this.ClothingEntries)
216 {
217 ret = key_pair.Value.OnEntryCommitEvent(key_pair.Value, writer);
218 }
219 return ret;
220 }
221 #region IParse Members
222
223 public bool Parse(MemoryStream stream)
224 {
225 BinaryReader br = new BinaryReader(stream);
226 this.Log.WriteLine();
227 // read header section magic
228
229 for (int i = 0; i < this.SectionOffsets.Count; i++)
230 {
231 ClothingEntry entry = new ClothingEntry();
232 entry.OnEntryCommitEvent = new EntryCommitEvent<ClothingEntry>(this.CommitEntry); // commit callback
233 entry.Offset = this.SectionOffsets[i]; // set the offset for this entry
234
235 br.BaseStream.Seek(this.SectionOffsets[i], SeekOrigin.Begin);
236 this.Log.WriteLine(string.Format("Clothing Section: Index=0x{0:x8} Offset=0x{1:x8}", i,(int)br.BaseStream.Position));
237
238 byte[] magic = br.ReadBytes(4);
239 string str_magic = ASCIIEncoding.ASCII.GetString(magic);
240 Debug.Assert(str_magic == "CLOT", string.Format("Excepted: {0} found: {1}", "CLOT", str_magic));
241
242 // Clothing Name
243 byte[] section_size_bytes = br.ReadBytes(12);
244 int section_size = BitConverter.ToInt32(section_size_bytes, 0);
245
246 entry.CLOT_SIZE = section_size_bytes; // set the clot size
247
248 int name_offset = (int)br.BaseStream.Position;
249 magic = br.ReadBytes(4);
250 str_magic = ASCIIEncoding.ASCII.GetString(magic);
251 Debug.Assert(str_magic == "NAME", string.Format("Excepted: {0} found: {1}", "NAME", str_magic));
252
253 int name_size = br.ReadInt32();
254
255 this.Log.WriteLine("\t\tClothing Name Size: " + name_size.ToString());
256 byte[] name_bytes = br.ReadBytes(name_size);
257 string ClothingName = ASCIIEncoding.ASCII.GetString(name_bytes);
258
259 entry.CLOT_NAME = ClothingName; // set the NAME
260
261 this.Log.WriteLine("\t\tClothing Name : " + ClothingName);
262
263
264 // Clothing Model
265 magic = br.ReadBytes(4);
266 str_magic = ASCIIEncoding.ASCII.GetString(magic);
267 Debug.Assert(str_magic == "MODL", string.Format("Excepted: {0} found: {1}", "MODL", str_magic));
268
269 int modl_name_size = br.ReadInt32();
270 this.Log.WriteLine("\t\tClothing Model Name Size: " + modl_name_size.ToString());
271 byte[] modl_name_bytes = br.ReadBytes(modl_name_size);
272 string ClothingModelName = ASCIIEncoding.ASCII.GetString(modl_name_bytes);
273
274 entry.CLOT_MODL = ClothingModelName; // set the MODL
275
276 this.Log.WriteLine("\t\tClothing Model Name: " + ClothingModelName);
277
278 // Clothing Full Name
279 magic = br.ReadBytes(4);
280 str_magic = ASCIIEncoding.ASCII.GetString(magic);
281 Debug.Assert(str_magic == "FNAM", string.Format("Excepted: {0} found: {1}", "FNAM", str_magic));
282
283 int fname_size = br.ReadInt32();
284 this.Log.WriteLine("\t\tClothing FullName Size: " + fname_size.ToString());
285 byte[] fname_bytes = br.ReadBytes(fname_size);
286 string ClothingFullName = ASCIIEncoding.ASCII.GetString(fname_bytes);
287 entry.CLOT_FULLNAME = ClothingFullName; // set the full name
288 this.Log.WriteLine("\t\tClothing FullName: " + ClothingFullName);
289
290 // Clothing Data
291 magic = br.ReadBytes(4);
292 str_magic = ASCIIEncoding.ASCII.GetString(magic);
293 Debug.Assert(str_magic == "CTDT", string.Format("Excepted: {0} found: {1}", "CTDT", str_magic));
294
295 int ctdt_size = br.ReadInt32();
296
297 int ctdt_type = br.ReadInt32();
298 string ctdt_type_string = "";
299
300 try
301 {
302 ctdt_type_string = Enum.GetName(typeof(ClothingTypes), ctdt_type);
303 }
304 catch { ctdt_type_string = "unknown"; }
305
306
307 float ctdt_weight = br.ReadSingle();
308 short ctdt_value = br.ReadInt16();
309 short ctdt_echant_pts = br.ReadInt16();
310
311
312 entry.CLOT_CTDT_SIZE = ctdt_size; // set the size
313 entry.CLOT_CTDT_TYPE = ctdt_type; // set the type
314 entry.CLOT_CTDT_WEIGHT = ctdt_weight; // set the weight
315 entry.CLOT_CTDT_VALUE = ctdt_value; // set the value
316 entry.CLOT_CTDT_ENCHANTPTS = ctdt_echant_pts; // set the enchant pts
317
318 this.Log.WriteLine("\t\tClothing Data: ");
319 this.Log.WriteLine("\t\t\tType: " + ctdt_type + " (" + ctdt_type_string +")");
320 this.Log.WriteLine("\t\t\tWeight: " + ctdt_weight);
321 this.Log.WriteLine("\t\t\tValue: " + ctdt_value);
322 this.Log.WriteLine("\t\t\tEnchant Points: " + ctdt_echant_pts);
323
324
325
326 //magic = br.ReadBytes(4);
327 //str_magic = ASCIIEncoding.ASCII.GetString(magic);
328 //Debug.Assert(str_magic == "SCRI", string.Format("Excepted: {0} found: {1}", "SCRI", str_magic));
329 //br.BaseStream.Position = br.BaseStream.Position - 4; // back up 4 bytes
330 //int length_till_end_of_section = (name_offset + section_size) + 0x10;
331 int length_till_end_of_section = (name_offset + section_size) - (int)br.BaseStream.Position;
332
333
334 //try
335 //{
336 byte[] extra_clothing_data = br.ReadBytes(length_till_end_of_section);
337 entry.CLOT_OTHER_DATA = extra_clothing_data; // set the extra data
338 //}
339 //catch { break; }
340
341 //break;
342 try
343 {
344 this.ClothingEntries.Add(entry.CLOT_NAME, entry);
345 }
346 catch (Exception)
347 {
348 continue;
349 }
350 //this.ClothingEntries.Sort(); // sorting should not cause any major issues, since each entry holds its own offset
351 }
352
353
354 return true;
355 }
356
357 #endregion
358
359 #region ICommit Members
360
361 public bool Commit(ICommitWriter writer)
362 {
363 return this.CommitAllEntries(writer);
364 }
365
366 #endregion
367
368 #region IAsBytes Members
369
370 public byte[] AsBytes
371 {
372 get
373 {
374 this.reader.Seek(0, SeekOrigin.Begin);
375 BinaryReader br = new BinaryReader(this.reader);
376 return br.ReadBytes(this.Size);
377 }
378 }
379
380 #endregion
381
382 #region ISizeOffset Members
383
384 private int _Size;
385 public int Size { get { return _Size; } private set { _Size = value; } } // headersize
386
387 private int _Offset;
388 public int Offset { get { return _Offset; } private set { _Offset = value; } }
389 public int OffsetToNext { get { return this.Size + this.Offset; } } // force this to 16 bytes
390 #endregion
391
392 #region Sub-Classes
393 public class SectionLocater : IParse, IOffset, ISize
394 {
395 private ConsoleLog Log;
396 MemoryStream reader = new MemoryStream();
397 public SectionLocater()
398 {
399 this.reader = new MemoryStream();
400 this.Log = new ConsoleLog();
401 this.ClothingSectionOffsets = new List<int>();
402
403 }
404 public SectionLocater(BinaryReader br, int CurrentOffset, ConsoleLog Log) : this()
405 {
406 this.Log = Log;
407 br.BaseStream.Seek(0, SeekOrigin.Begin);
408 this.Offset = CurrentOffset;
409 this.reader = new MemoryStream(br.ReadBytes((int)br.BaseStream.Length), CurrentOffset, (int)br.BaseStream.Length - CurrentOffset);
410 this.Parse(this.reader);
411 }
412
413 #region IParse Members
414
415 public bool Parse(MemoryStream stream)
416 {
417 BinaryReader br = new BinaryReader(stream);
418 this.Log.WriteLine();
419
420 byte[] data = br.ReadBytes((int)br.BaseStream.Length);
421
422
423 this.ClothingSectionOffsets = new List<int>();
424
425 foreach (var position in data.Locate(ASCIIEncoding.ASCII.GetBytes(PlugingClothing.CLOTHING_MAGIC)))
426 {
427 this.ClothingSectionOffsets.Add(position + 0x1); // add 1 byte to remove the \0,
428 }
429
430 if (this.ClothingSectionOffsets.Count == 0)
431 {
432 this.Log.WriteLine("\t\tNo Clothing Section Could be Found!");
433 }
434 else
435 {
436 this.Log.WriteLine("\t\tFound 0x" + this.ClothingSectionOffsets.Count.ToString("x2") + "clothing sections");
437 }
438
439 return true;
440 }
441
442 #endregion
443
444
445
446 #region IOffset Members
447 private int _Offset;
448 public int Offset
449 {
450 get { return _Offset; }
451 private set { _Offset = value; }
452 }
453 private int _Size;
454 public int Size
455 {
456 get { return _Size; }
457 private set { _Size = value; }
458 }
459 private List<int> _ClothingSectionOffsets;
460 public List<int> ClothingSectionOffsets
461 {
462 get { return _ClothingSectionOffsets; }
463 private set { _ClothingSectionOffsets = value; }
464 }
465 #endregion
466 }
467 #endregion
468
469
470 }
471 }

  ViewVC Help
Powered by ViewVC 1.1.22