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

Annotation of /trunk/libTES3FileFormat/PlugingClothing.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (hide annotations) (download)
Sat Jul 30 11:47:53 2011 UTC (8 years, 6 months ago) by william
File size: 19270 byte(s)
*** work out committing individual entries back into the main data stream

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

  ViewVC Help
Powered by ViewVC 1.1.22