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

Annotation of /trunk/libTES3FileFormat/PlugingClothing.cs

Parent Directory Parent Directory | Revision Log Revision Log


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

1 william 17 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 william 33
12 william 27 public enum ClothingTypes
13 william 18 {
14 william 26 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 william 18 }
25 william 17
26 william 20 public interface IClothingEntry : IOffset
27 william 17 {
28 william 20 byte[] CLOT_MAGIC { get; } // 4bytes, CLOT
29     byte[] CLOT_SIZE { get; set; } // 12 bytes
30 william 17
31 william 20 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 william 17 }
51 william 22 public class ClothingEntry : IClothingEntry, IComparable
52 william 20 {
53 william 33 internal EntryCommitEvent<ClothingEntry> OnEntryCommitEvent;
54    
55     //internal BinaryWriter writer = null;
56    
57 william 37 public bool Commit(IPluginDataClothing pluginData)
58 william 33 {
59 william 37 pluginData.ClothingSection.ClothingEntries[this.CLOT_NAME] = this;
60     return true;
61 william 33 }
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 william 22 #region IComparable Members
102     public int CompareTo(object obj) { return this.CLOT_NAME.CompareTo((obj as ClothingEntry).CLOT_NAME); }
103     #endregion
104 william 20 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 william 28 this.CLOT_CTDT_TYPE = (int)ClothingTypes.Amulet;
112 william 20 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 william 22
160    
161 william 20 }
162    
163     public interface IPlugingClothing : IParse, ICommit, IAsBytes, ISizeOffset
164     {
165 william 30 Dictionary<string, ClothingEntry> ClothingEntries { get; }
166 william 33 //bool CommitEntry(ClothingEntry entry);
167 william 20 }
168 william 17 public class PlugingClothing : IPlugingClothing, ICommitParseAsBytes
169     {
170     private ConsoleLog Log;
171 william 19 private const string CLOTHING_MAGIC = "\0CLOT";
172 william 17 private const string CLOTHING_NAME_MAGIC = "NAME";
173     MemoryStream reader = new MemoryStream();
174 william 19 private List<int> SectionOffsets = new List<int>();
175 william 17 public PlugingClothing()
176     {
177     this.reader = new MemoryStream();
178     this.Offset = 0;
179     this.Size = 0;
180 william 19 this.SectionOffsets = new List<int>();
181 william 30 this.ClothingEntries = new Dictionary<string, ClothingEntry>();
182 william 17 }
183 william 19 public PlugingClothing(BinaryReader br, List<int> SectionOffsets, bool ReadOnly, ConsoleLog Log)
184 william 17 : this()
185     {
186     this.Log = Log;
187 william 19 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 william 17 this.Parse(this.reader);
193     }
194 william 20 #region IPlugingClothing Members
195 william 30 private Dictionary<string, ClothingEntry> _ClothingEntries;
196     public Dictionary<string, ClothingEntry> ClothingEntries
197 william 20 {
198     get { return _ClothingEntries; }
199     private set { _ClothingEntries = value; }
200     }
201 william 17
202 william 20 #endregion
203 william 33
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 william 17 #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 william 19 for (int i = 0; i < this.SectionOffsets.Count; i++)
230 william 18 {
231 william 20 ClothingEntry entry = new ClothingEntry();
232 william 33 entry.OnEntryCommitEvent = new EntryCommitEvent<ClothingEntry>(this.CommitEntry); // commit callback
233 william 20 entry.Offset = this.SectionOffsets[i]; // set the offset for this entry
234    
235 william 19 br.BaseStream.Seek(this.SectionOffsets[i], SeekOrigin.Begin);
236 william 18 this.Log.WriteLine(string.Format("Clothing Section: Index=0x{0:x8} Offset=0x{1:x8}", i,(int)br.BaseStream.Position));
237 william 17
238 william 18 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 william 17
242 william 18 // Clothing Name
243 william 20 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 william 19 int name_offset = (int)br.BaseStream.Position;
249 william 18 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 william 20
255 william 18 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 william 20
259     entry.CLOT_NAME = ClothingName; // set the NAME
260    
261 william 18 this.Log.WriteLine("\t\tClothing Name : " + ClothingName);
262 william 17
263    
264 william 18 // 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 william 20
274     entry.CLOT_MODL = ClothingModelName; // set the MODL
275    
276 william 18 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 william 20 entry.CLOT_FULLNAME = ClothingFullName; // set the full name
288 william 18 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 william 20
297 william 18 int ctdt_type = br.ReadInt32();
298     string ctdt_type_string = "";
299    
300     try
301     {
302 william 28 ctdt_type_string = Enum.GetName(typeof(ClothingTypes), ctdt_type);
303 william 18 }
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 william 20
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 william 18 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 william 19
325 william 18
326 william 19 //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 william 18
333 william 19
334 william 20 //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 william 19
341     //break;
342 william 37 try
343     {
344     this.ClothingEntries.Add(entry.CLOT_NAME, entry);
345     }
346     catch (Exception)
347     {
348     continue;
349     }
350 william 30 //this.ClothingEntries.Sort(); // sorting should not cause any major issues, since each entry holds its own offset
351 william 18 }
352    
353    
354 william 17 return true;
355     }
356    
357     #endregion
358    
359     #region ICommit Members
360    
361 william 33 public bool Commit(ICommitWriter writer)
362 william 17 {
363 william 33 return this.CommitAllEntries(writer);
364 william 17 }
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 william 19 this.ClothingSectionOffsets = new List<int>();
402 william 20
403 william 17 }
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 william 19
422 william 17
423 william 19 this.ClothingSectionOffsets = new List<int>();
424 william 17
425     foreach (var position in data.Locate(ASCIIEncoding.ASCII.GetBytes(PlugingClothing.CLOTHING_MAGIC)))
426     {
427 william 19 this.ClothingSectionOffsets.Add(position + 0x1); // add 1 byte to remove the \0,
428 william 17 }
429    
430 william 19 if (this.ClothingSectionOffsets.Count == 0)
431 william 17 {
432 william 19 this.Log.WriteLine("\t\tNo Clothing Section Could be Found!");
433 william 17 }
434     else
435     {
436 william 19 this.Log.WriteLine("\t\tFound 0x" + this.ClothingSectionOffsets.Count.ToString("x2") + "clothing sections");
437     }
438 william 17
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 william 19 private List<int> _ClothingSectionOffsets;
460     public List<int> ClothingSectionOffsets
461 william 18 {
462 william 19 get { return _ClothingSectionOffsets; }
463     private set { _ClothingSectionOffsets = value; }
464 william 18 }
465 william 17 #endregion
466     }
467     #endregion
468 william 20
469    
470 william 17 }
471     }

  ViewVC Help
Powered by ViewVC 1.1.22