44using System . Text ;
55using System . Threading . Tasks ;
66using System . IO ;
7+ using System . IO . MemoryMappedFiles ;
78using System . Xml . Linq ;
9+ using ESPSharp . Enums ;
10+ using ESPSharp . Enums . Flags ;
11+ using ESPSharp . Interfaces ;
12+ using ESPSharp . Subrecords ;
13+ using ESPSharp . SubrecordCollections ;
14+ using ESPSharp . DataTypes ;
815
916namespace ESPSharp
1017{
11- public class ElderScrollsPlugin
18+ public class ElderScrollsPlugin : IDisposable
1219 {
13- public Record Header ;
14- public List < Group > Groups = new List < Group > ( ) ;
20+ public static List < ElderScrollsPlugin > LoadedPlugins = new List < ElderScrollsPlugin > ( ) ;
21+ public static Dictionary < LoadOrderFormID , List < RecordView > > LoadedRecordViews = new Dictionary < LoadOrderFormID , List < RecordView > > ( ) ;
22+
23+ protected string name = "" ;
24+ public List < string > Masters = new List < string > ( ) ;
25+ public RecordView Header ;
26+ public List < Group > TopGroups = new List < Group > ( ) ;
27+ public List < Group > AllGroups = new List < Group > ( ) ;
28+ public HashSet < RecordView > RecordViews = new HashSet < RecordView > ( ) ;
29+
30+ protected MemoryMappedFile mmf ;
31+
32+ public string Name
33+ {
34+ get
35+ {
36+ if ( Header . Flags . HasFlag ( RecordFlag . IsMasterFile ) )
37+ return name + ".esm" ;
38+ else
39+ return name + ".esp" ;
40+ }
41+ protected set
42+ {
43+ name = Path . GetFileNameWithoutExtension ( value ) ;
44+ }
45+ }
46+
47+ public ElderScrollsPlugin ( )
48+ {
49+ }
50+
51+ public ElderScrollsPlugin ( string name )
52+ {
53+ Name = name ;
54+ }
55+
56+ public void Read ( string source )
57+ {
58+ if ( source == "" )
59+ throw new Exception ( ) ;
60+
61+ if ( File . Exists ( source ) )
62+ ReadBinary ( source ) ;
63+ else if ( Directory . Exists ( source ) )
64+ ReadXML ( source ) ;
65+ }
1566
1667 public void WriteXML ( string destinationFolder )
1768 {
18- Header . WriteXML ( Path . Combine ( destinationFolder , "Header.xml" ) ) ;
69+ Header . Record . WriteXML ( Path . Combine ( destinationFolder , "Header.xml" ) ) ;
1970
20- foreach ( Group group in Groups . Where ( g => g . ToString ( ) != "Interior Cells" && g . ToString ( ) != "Worldspaces" && g . ToString ( ) != "Dialog Topics" ) )
71+ foreach ( Group group in TopGroups . Where ( g => g . ToString ( ) != "Interior Cells" && g . ToString ( ) != "Worldspaces" && g . ToString ( ) != "Dialog Topics" ) )
2172 {
2273 string newDir = Path . Combine ( destinationFolder , group . ToString ( ) ) ;
2374 Directory . CreateDirectory ( newDir ) ;
@@ -28,38 +79,121 @@ public void WriteXML(string destinationFolder)
2879 public static ElderScrollsPlugin ReadXML ( string sourceFolder )
2980 {
3081 ElderScrollsPlugin outPlug = new ElderScrollsPlugin ( ) ;
31- outPlug . Header = Record . ReadXML ( Path . Combine ( sourceFolder , "Header.xml" ) ) ;
82+ outPlug . name = Path . GetDirectoryName ( sourceFolder ) ;
83+ outPlug . Header = new RecordView ( Path . Combine ( sourceFolder , "Header.xml" ) ) ;
84+
85+ ESPSharp . Records . Header headRec = outPlug . Header . Record as ESPSharp . Records . Header ;
86+
87+ if ( headRec . MasterFiles != null )
88+ {
89+ foreach ( var masterData in headRec . MasterFiles )
90+ {
91+ ElderScrollsPlugin master = new ElderScrollsPlugin ( masterData . FileName . Value ) ;
92+ master . Read ( masterData . FileName . Value ) ;
93+ outPlug . Masters . Add ( masterData . FileName . Value ) ;
94+ }
95+ }
96+
97+ outPlug . Masters . Add ( outPlug . Name ) ;
3298
3399 foreach ( var folder in Directory . EnumerateDirectories ( sourceFolder , "*.*" , SearchOption . TopDirectoryOnly ) )
34100 {
35- Group newGroup = Group . ReadXML ( folder ) ;
101+ Group newGroup = Group . CreateGroup ( folder ) ;
36102
37- outPlug . Groups . Add ( newGroup ) ;
103+ newGroup . GroupAdded += ( g ) => outPlug . AllGroups . Add ( g ) ;
104+ newGroup . RecordViewAdded += ( r ) => outPlug . RecordViews . Add ( r ) ;
105+ outPlug . TopGroups . Add ( newGroup ) ;
106+ outPlug . AllGroups . Add ( newGroup ) ;
107+
108+ newGroup . ReadXML ( folder ) ;
38109 }
39110
111+ ElderScrollsPlugin . LoadedPlugins . Add ( outPlug ) ;
112+
40113 return outPlug ;
41114 }
42115
43116 public void WriteBinary ( ESPWriter writer )
44117 {
45- Header . WriteBinary ( writer ) ;
118+ Header . Record . WriteBinary ( writer ) ;
46119
47- foreach ( var group in Groups )
120+ foreach ( var group in TopGroups )
48121 group . WriteBinary ( writer ) ;
49122 }
50123
51- public void ReadBinary ( ESPReader reader )
124+ public void ReadBinary ( string file )
52125 {
53- Header = Record . CreateRecord ( reader ) ;
54- Header . ReadBinary ( reader ) ;
126+ name = Path . GetFileNameWithoutExtension ( file ) ;
127+ FileInfo fi = new FileInfo ( file ) ;
128+ mmf = MemoryMappedFile . CreateFromFile ( file , FileMode . Open , Path . GetFileNameWithoutExtension ( file ) , fi . Length , MemoryMappedFileAccess . Read ) ;
129+
130+ using ( MemoryMappedViewStream stream = mmf . CreateViewStream ( 0 , fi . Length , MemoryMappedFileAccess . Read ) )
131+ using ( ESPReader reader = new ESPReader ( stream ) )
132+ {
133+ Header = new RecordView ( reader , mmf ) ;
134+
135+ Masters = new List < string > ( ) ;
136+
137+ ESPSharp . Records . Header headRec = Header . Record as ESPSharp . Records . Header ;
138+
139+ if ( headRec . MasterFiles != null )
140+ {
141+ foreach ( var masterData in headRec . MasterFiles )
142+ {
143+ ElderScrollsPlugin master = new ElderScrollsPlugin ( masterData . FileName . Value ) ;
144+ master . Read ( masterData . FileName . Value ) ;
145+ Masters . Add ( masterData . FileName . Value ) ;
146+ }
147+ }
148+
149+ Masters . Add ( Name ) ;
150+
151+ while ( reader . BaseStream . Position < reader . BaseStream . Length )
152+ {
153+ var group = Group . CreateGroup ( reader ) ;
154+
155+ group . GroupAdded += ( g ) => AllGroups . Add ( g ) ;
156+ group . RecordViewAdded += ( r ) => RecordViews . Add ( r ) ;
157+ TopGroups . Add ( group ) ;
158+ AllGroups . Add ( group ) ;
159+
160+ group . ReadBinary ( reader , mmf ) ;
161+ }
162+ }
55163
56- while ( reader . BaseStream . Position < reader . BaseStream . Length )
164+ ElderScrollsPlugin . LoadedPlugins . Add ( this ) ;
165+
166+ foreach ( RecordView view in RecordViews )
57167 {
58- var group = Group . CreateGroup ( reader ) ;
59- group . ReadBinary ( reader ) ;
168+ LoadOrderFormID loID = new LoadOrderFormID ( view . FormID , this ) ;
169+
170+ List < RecordView > viewList ;
171+
172+ if ( ! ElderScrollsPlugin . LoadedRecordViews . TryGetValue ( loID , out viewList ) )
173+ {
174+ viewList = new List < RecordView > ( ) ;
175+ ElderScrollsPlugin . LoadedRecordViews . Add ( loID , viewList ) ;
176+ }
177+
178+ viewList . Add ( view ) ;
179+ }
180+ }
60181
61- Groups . Add ( group ) ;
182+ public static void Clear ( )
183+ {
184+ foreach ( ElderScrollsPlugin plugin in LoadedPlugins )
185+ {
186+ plugin . Dispose ( ) ;
62187 }
188+
189+ LoadedPlugins = new List < ElderScrollsPlugin > ( ) ;
190+ LoadedRecordViews = new Dictionary < LoadOrderFormID , List < RecordView > > ( ) ;
191+ }
192+
193+ public void Dispose ( )
194+ {
195+ if ( mmf != null )
196+ mmf . Dispose ( ) ;
63197 }
64198 }
65199}
0 commit comments