using SharpDX; using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; namespace CodeWalker.GameFiles { public class CacheDatFile : PackedFile { public RpfFileEntry FileEntry { get; set; } public string Version { get; set; } public CacheFileDate[] FileDates { get; set; } public Dictionary MapNodeDict { get; set; } public MapDataStoreNode[] RootMapNodes { get; set; } //public Dictionary InteriorProxyDict { get; set; } public Dictionary BoundsStoreDict { get; set; } public MapDataStoreNode[] AllMapNodes { get; set; } public CInteriorProxy[] AllCInteriorProxies { get; set; } public BoundsStoreItem[] AllBoundsStoreItems { get; set; } public void Load(byte[] data, RpfFileEntry entry) { FileEntry = entry; MemoryStream ms = new MemoryStream(data); BinaryReader br = new BinaryReader(ms); StringBuilder sb = new StringBuilder(); for (int i = 0; (i < 100) && (i < data.Length); i++) { //read version string. byte b = data[i]; if (b == 0) break; sb.Append((char)b); } Version = sb.ToString().Replace("[VERSION]", "").Replace("\r", "").Replace("\n", ""); sb.Clear(); int lastn = 0; int lspos = 0; uint structcount = 0; uint modlen; bool indates = false; List lines = new List(); var dates = new List(); var allMapNodes = new List(); var allCInteriorProxies = new List(); var allBoundsStoreItems = new List(); for (int i = 100; i < data.Length; i++) { byte b = data[i]; if (b == 0) break; if (b == 0xA) { lastn = i; string line = sb.ToString(); lines.Add(line); switch (line) { case "": indates = true; break; case "": indates = false; break; case "": break; case "": break; case "fwMapDataStore": ms.Position = i + 1; modlen = br.ReadUInt32(); structcount = modlen / 64; lspos = i + (int)modlen + 5; while (ms.Position(); var rootMapNodes = new List(); foreach (var mapnode in AllMapNodes) { MapNodeDict[mapnode.Name] = mapnode; if (mapnode.ParentName == 0) { rootMapNodes.Add(mapnode); } if (mapnode.UnkExtra != null) { }//notsure what to do with this } foreach (var mapnode in AllMapNodes) { MapDataStoreNode pnode; if (MapNodeDict.TryGetValue(mapnode.ParentName, out pnode)) { pnode.AddChildToList(mapnode); } else if ((mapnode.ParentName != 0)) { } } foreach (var mapnode in AllMapNodes) { mapnode.ChildrenListToArray(); } RootMapNodes = rootMapNodes.ToArray(); BoundsStoreDict = new Dictionary(); foreach (BoundsStoreItem item in AllBoundsStoreItems) { BoundsStoreItem mbsi = null; if (BoundsStoreDict.TryGetValue(item.Name, out mbsi)) { } BoundsStoreDict[item.Name] = item; } //InteriorProxyDict = new Dictionary(); foreach (CInteriorProxy prx in AllCInteriorProxies) { //CInteriorProxy mprx = null; //if (InteriorProxyDict.TryGetValue(prx.Name, out mprx)) //{ } //InteriorProxyDict[prx.Name] = prx;//can't do this! multiples with same name different pos MapDataStoreNode mnode = null; if (MapNodeDict.TryGetValue(prx.Parent, out mnode)) { mnode.AddInteriorToList(prx); } else { } } foreach (var mapnode in AllMapNodes) { mapnode.InteriorProxyListToArray(); } br.Dispose(); ms.Dispose(); } public byte[] Save() { MemoryStream s = new MemoryStream(); DataWriter w = new DataWriter(s, Endianess.LittleEndian); w.Write("[VERSION]\n" + Version + "\n"); while (w.Position < 100) w.Write((byte)0); WriteString(w, "\n"); if (FileDates != null) { foreach (var d in FileDates) { WriteString(w, d.ToCacheFileString()); WriteString(w, "\n"); } } WriteString(w, "\n"); WriteString(w, "\nfwMapDataStore\n"); var modlen = (AllMapNodes?.Length ?? 0) * 64; //if (AllMapNodes != null) //{ // foreach (var n in AllMapNodes) // { // if (n.Unk4 == 0xFE) // { // modlen += 96; // } // } //} w.Write(modlen); if (AllMapNodes != null) { foreach (var n in AllMapNodes) { n.Write(w); } } WriteString(w, "\n"); WriteString(w, "\nCInteriorProxy\n"); w.Write((AllCInteriorProxies?.Length ?? 0) * 104); if (AllCInteriorProxies != null) { foreach (var p in AllCInteriorProxies) { p.Write(w); } } WriteString(w, "\n"); WriteString(w, "\nBoundsStore\n"); w.Write((AllBoundsStoreItems?.Length ?? 0) * 32); if (AllBoundsStoreItems != null) { foreach (var b in AllBoundsStoreItems) { b.Write(w); } } WriteString(w, "\n"); var buf = new byte[s.Length]; s.Position = 0; s.Read(buf, 0, buf.Length); return buf; } private void WriteString(DataWriter w, string s) { for (int i = 0; i < s.Length; i++) { w.Write((byte)s[i]); } } public void WriteXml(StringBuilder sb, int indent) { CacheDatXml.ValueTag(sb, indent, "Version", Version); CacheDatXml.WriteItemArray(sb, FileDates, indent, "FileDates"); CacheDatXml.WriteItemArray(sb, AllMapNodes, indent, "MapDataStore"); CacheDatXml.WriteItemArray(sb, AllCInteriorProxies, indent, "InteriorProxies"); CacheDatXml.WriteItemArray(sb, AllBoundsStoreItems, indent, "BoundsStore"); } public void ReadXml(XmlNode node) { Version = Xml.GetChildStringAttribute(node, "Version"); FileDates = XmlMeta.ReadItemArray(node, "FileDates"); AllMapNodes = XmlMeta.ReadItemArray(node, "MapDataStore"); AllCInteriorProxies = XmlMeta.ReadItemArray(node, "InteriorProxies"); AllBoundsStoreItems = XmlMeta.ReadItemArray(node, "BoundsStore"); } public string GetXmlOLD() { StringBuilder sb = new StringBuilder(); sb.AppendLine(MetaXmlBase.XmlHeader); sb.AppendLine(string.Format("", Version)); sb.AppendLine(" "); if (FileDates != null) { foreach (var date in FileDates) { sb.AppendLine(string.Format(" {0}", date.ToCacheFileString())); } } sb.AppendLine(" "); sb.AppendLine(" "); if (AllMapNodes != null) { foreach (var mapnode in AllMapNodes) { sb.AppendLine(" "); sb.AppendLine(string.Format(" {0}", mapnode.Name.ToCleanString())); sb.AppendLine(string.Format(" {0}", mapnode.ParentName.ToCleanString())); sb.AppendLine(string.Format(" ", mapnode.ContentFlags.ToString())); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(mapnode.streamingExtentsMin))); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(mapnode.streamingExtentsMax))); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(mapnode.entitiesExtentsMin))); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(mapnode.entitiesExtentsMax))); sb.AppendLine(string.Format(" ", mapnode.Unk1, mapnode.Unk2, mapnode.Unk3)); sb.AppendLine(" "); } } sb.AppendLine(" "); sb.AppendLine(" "); if (AllCInteriorProxies != null) { foreach (var intprox in AllCInteriorProxies) { sb.AppendLine(" "); sb.AppendLine(string.Format(" {0}", intprox.Name.ToCleanString())); sb.AppendLine(string.Format(" {0}", intprox.Parent.ToCleanString())); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(intprox.Position))); sb.AppendLine(string.Format(" ", FloatUtil.GetQuaternionXmlString(intprox.Orientation))); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(intprox.BBMin))); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(intprox.BBMax))); sb.AppendLine(string.Format(" ", intprox.Unk01, intprox.Unk03)); sb.AppendLine(string.Format(" ", intprox.Unk11, intprox.Unk12, intprox.Unk13, intprox.Unk14)); sb.AppendLine(" "); } } sb.AppendLine(" "); sb.AppendLine(" "); if (AllBoundsStoreItems != null) { foreach (var bndstore in AllBoundsStoreItems) { sb.AppendLine(" "); sb.AppendLine(string.Format(" {0}", bndstore.Name.ToCleanString())); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(bndstore.Min))); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(bndstore.Max))); sb.AppendLine(string.Format(" ", bndstore.Layer)); sb.AppendLine(" "); } } sb.AppendLine(" "); sb.AppendLine(""); return sb.ToString(); } public override string ToString() { if (FileEntry != null) { return FileEntry.ToString(); } return base.ToString(); } } [TypeConverter(typeof(ExpandableObjectConverter))] public class CacheFileDate : IMetaXmlItem { public MetaHash FileName { get; set; } //"resource_surrogate:/%s.rpf" public DateTime TimeStamp { get; set; } public uint FileID { get; set; } public CacheFileDate() { } public CacheFileDate(string line) { string[] parts = line.Split(' '); if (parts.Length == 3) { FileName = new MetaHash(uint.Parse(parts[0])); TimeStamp = DateTime.FromFileTimeUtc(long.Parse(parts[1])); FileID = uint.Parse(parts[2]); } else { } //testing } public string ToCacheFileString() { return FileName.Hash.ToString() + " " + TimeStamp.ToFileTimeUtc().ToString() + " " + FileID.ToString(); } public void WriteXml(StringBuilder sb, int indent) { CacheDatXml.StringTag(sb, indent, "fileName", CacheDatXml.HashString(FileName)); CacheDatXml.ValueTag(sb, indent, "timeStamp", TimeStamp.ToFileTimeUtc().ToString()); CacheDatXml.ValueTag(sb, indent, "fileID", FileID.ToString()); } public void ReadXml(XmlNode node) { FileName = XmlMeta.GetHash(Xml.GetChildInnerText(node, "fileName")); TimeStamp = DateTime.FromFileTimeUtc((long)Xml.GetChildULongAttribute(node, "timeStamp")); FileID = Xml.GetChildUIntAttribute(node, "fileID"); } public override string ToString() { return FileName.ToString() + ", " + TimeStamp.ToString() + ", " + FileID.ToString(); } } [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundsStoreItem : IMetaXmlItem { public MetaHash Name { get; set; } public Vector3 Min { get; set; } public Vector3 Max { get; set; } public uint Layer { get; set; } public BoundsStoreItem() { } public BoundsStoreItem(Bounds b) { Name = 0; Min = b.BoxMin; Max = b.BoxMax; Layer = 0; } public BoundsStoreItem(BinaryReader br) { Name = new MetaHash(br.ReadUInt32()); Min = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Max = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Layer = br.ReadUInt32(); } public void Write(DataWriter w) { w.Write(Name); w.Write(Min); w.Write(Max); w.Write(Layer); } public void WriteXml(StringBuilder sb, int indent) { CacheDatXml.StringTag(sb, indent, "name", CacheDatXml.HashString(Name)); CacheDatXml.SelfClosingTag(sb, indent, "bbMin " + FloatUtil.GetVector3XmlString(Min)); CacheDatXml.SelfClosingTag(sb, indent, "bbMax " + FloatUtil.GetVector3XmlString(Max)); CacheDatXml.ValueTag(sb, indent, "layer", Layer.ToString()); } public void ReadXml(XmlNode node) { Name = XmlMeta.GetHash(Xml.GetChildInnerText(node, "name")); Min = Xml.GetChildVector3Attributes(node, "bbMin"); Max = Xml.GetChildVector3Attributes(node, "bbMax"); Layer = Xml.GetChildUIntAttribute(node, "layer"); } public override string ToString() { return Name.ToString() + ", " + Min.ToString() + ", " + Max.ToString() + ", " + Layer.ToString(); } } [TypeConverter(typeof(ExpandableObjectConverter))] public class CInteriorProxy : IMetaXmlItem { public uint Unk01 { get; set; } public uint Unk02 { get; set; } public uint Unk03 { get; set; } public MetaHash Name { get; set; } public MetaHash Parent { get; set; } public Vector3 Position { get; set; } public Quaternion Orientation { get; set; } public Vector3 BBMin { get; set; } public Vector3 BBMax { get; set; } public ulong Unk11 { get; set; }//possibly file offsets..? public ulong Unk12 { get; set; }//possibly file offsets..? public ulong Unk13 { get; set; }//possibly file offsets..? public ulong Unk14 { get; set; }//possibly file offsets..? public CInteriorProxy() { } public CInteriorProxy(BinaryReader br) { Unk01 = br.ReadUInt32(); Unk02 = br.ReadUInt32(); Unk03 = br.ReadUInt32(); Name = new MetaHash(br.ReadUInt32()); Parent = new MetaHash(br.ReadUInt32()); Position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Orientation = new Quaternion(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); BBMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); BBMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Unk11 = br.ReadUInt64(); Unk12 = br.ReadUInt64(); Unk13 = br.ReadUInt64(); Unk14 = br.ReadUInt64(); //(unk14-unk13)=~ 5500000 switch (Unk01) { case 0: //v_cashdepot case 19: //dt1_02_carpark case 20: //dt1_03_carpark case 21: //dt1_05_carpark case 4: //dt1_rd1_tun case 14: //id1_11_tunnel1_int case 24: //v_firedept case 3: //id2_21_a_tun1 case 22: //po1_08_warehouseint1 case 11: //sc1_rd_inttun1 case 10: //sc1_rd_inttun2b_end case 18: //bt1_04_carpark case 16: //v_hanger case 1: //ap1_03_lisapark_subway case 13: //kt1_03_carpark_int case 5: //sm20_tun1 case 2: //vbca_tunnel1 case 15: //cs1_12_tunnel01_int case 6: //cs1_14brailway1 case 9: //cs2_roadsb_tunnel_01 case 7: //cs3_03railtunnel_int1 case 8: //cs4_rwayb_tunnelint case 12: //ch1_roadsdint_tun1 case 100: //hei_int_mph_carrierhang3 case 47: //xm_x17dlc_int_base_ent case 120: case 119: break; default: break; } if (Unk02 != 0) { } switch (Unk03) { case 6: //v_cashdepot case 2: //dt1_02_carpark case 8: //v_fib01 case 4: //v_fib03 case 0: //v_fib04 case 7: //v_clotheslo case 1: //v_gun case 3: //v_genbank case 11: //v_hospital case 5: //v_shop_247 case 32: //v_abattoir case 13: //v_franklins case 15: //v_michael case 18: //v_faceoffice case 29: //v_recycle case 9: //v_stadium case 54: //v_farmhouse case 12: //v_ranch case 26: //hei_gta_milo_bar case 17: //hei_gta_milo_bedrm case 14: //hei_gta_milo_bridge case 48: //apa_mpapa_yacht case 43: break; default: break; } switch (Unk11) { case 5390106048: case 50578352072311817: case 140699061757388: case 738537932908210: case 65651138218412653: case 19678574933270533: case 67944777457713148: case 42661052301639680: case 64551944402634707: case 6851324394453320: case 5376209604: case 7160325822942775: case 140695211737544: case 5379565000: case 12610731652297560: case 0: case 5836226042334228: break; default: break; } switch (Unk12) { case 5394258664: case 1788295895209: case 2301144275160: case 2301144295745: case 2301144271926: case 2293121037876: case 2301144284982: case 2301144280511: case 2301144292239: case 2301144276247: case 2297948090320: case 2301144281267: case 2301144273909: case 2301144274429: case 2301144278131: case 2301144276931: case 2301144285912: case 2301144279392: case 2301144278900: case 2301144280746: case 2301144276750: case 2301144279385: case 794564824: case 794585409: case 3426812900: case 3363906997: case 2488666884898: case 1551090123535: case 3581544739: case 2697016884: case 2697019190: case 2697014452: case 2697013894: case 2697026447: case 2697010756: case 2697012560: case 2697010345: case 2697015248: case 2697009368: case 2697014442: case 2697008117: case 2697008069: case 2697018851: case 2697012339: case 2697010263: case 2697019078: case 2697013518: case 2697013308: case 2697013108: case 2079647991056: case 2333569996536: case 3433367119: case 2293344373240: case 1527735255327: case 1581974815172: case 2067312412743: case 2240565805648: break; default: break; } switch (Unk13) { case 5416947112: case 140699301996180: case 140699066065044: case 5381321844: case 5385188756: case 5385376164: case 140696605328676: case 140701349594068: case 5387902360: case 5380079992: case 140695959352556: case 140695215813968: case 5383741744: case 140697989613796: case 140701810993260: case 140701892506988: case 140701188531008: break; default: break; } switch (Unk14) { case 9: case 140699307584676: case 140699071655044: case 5386712196: case 5390629684: case 5390817140: case 140696610778260: case 140701355067892: case 5393331812: case 5385368100: case 140695964849172: case 140695221335892: case 5389196308: case 140697995052276: case 140701816510228: case 140701898076100: case 140701194017116: break; default: break; } } public void Write(DataWriter w) { w.Write(Unk01); w.Write(Unk02); w.Write(Unk03); w.Write(Name); w.Write(Parent); w.Write(Position); w.Write(Orientation.ToVector4()); w.Write(BBMin); w.Write(BBMax); w.Write(Unk11); w.Write(Unk12); w.Write(Unk13); w.Write(Unk14); } public void WriteXml(StringBuilder sb, int indent) { CacheDatXml.StringTag(sb, indent, "name", CacheDatXml.HashString(Name)); CacheDatXml.StringTag(sb, indent, "parent", CacheDatXml.HashString(Parent)); CacheDatXml.SelfClosingTag(sb, indent, "position " + FloatUtil.GetVector3XmlString(Position)); CacheDatXml.SelfClosingTag(sb, indent, "rotation " + FloatUtil.GetVector4XmlString(Orientation.ToVector4())); CacheDatXml.SelfClosingTag(sb, indent, "bbMin " + FloatUtil.GetVector3XmlString(BBMin)); CacheDatXml.SelfClosingTag(sb, indent, "bbMax " + FloatUtil.GetVector3XmlString(BBMax)); CacheDatXml.ValueTag(sb, indent, "unk01", Unk01.ToString()); CacheDatXml.ValueTag(sb, indent, "unk02", Unk02.ToString()); CacheDatXml.ValueTag(sb, indent, "unk03", Unk03.ToString()); CacheDatXml.ValueTag(sb, indent, "unk11", Unk11.ToString()); CacheDatXml.ValueTag(sb, indent, "unk12", Unk12.ToString()); CacheDatXml.ValueTag(sb, indent, "unk13", Unk13.ToString()); CacheDatXml.ValueTag(sb, indent, "unk14", Unk14.ToString()); } public void ReadXml(XmlNode node) { Name = XmlMeta.GetHash(Xml.GetChildInnerText(node, "name")); Parent = XmlMeta.GetHash(Xml.GetChildInnerText(node, "parent")); Position = Xml.GetChildVector3Attributes(node, "position"); Orientation = Xml.GetChildVector4Attributes(node, "rotation").ToQuaternion(); BBMin = Xml.GetChildVector3Attributes(node, "bbMin"); BBMax = Xml.GetChildVector3Attributes(node, "bbMax"); Unk01 = Xml.GetChildUIntAttribute(node, "unk01"); Unk02 = Xml.GetChildUIntAttribute(node, "unk02"); Unk03 = Xml.GetChildUIntAttribute(node, "unk03"); Unk11 = Xml.GetChildULongAttribute(node, "unk11"); Unk12 = Xml.GetChildULongAttribute(node, "unk12"); Unk13 = Xml.GetChildULongAttribute(node, "unk13"); Unk14 = Xml.GetChildULongAttribute(node, "unk14"); } public override string ToString() { return Unk01.ToString() + ", " + Unk02.ToString() + ", " + Unk03.ToString() + ", " + Name.ToString() + ", " + Parent.ToString() + ", " + Position.ToString() + ", " + Orientation.ToString() + ", " + BBMin.ToString() + ", " + BBMax.ToString() + ", " + Unk11.ToString() + ", " + Unk12.ToString() + ", " + Unk13.ToString() + ", " + Unk14.ToString(); } } [TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNode : IMetaXmlItem { public MetaHash Name { get; set; } public MetaHash ParentName { get; set; } public uint ContentFlags { get; set; } public Vector3 streamingExtentsMin { get; set; } public Vector3 streamingExtentsMax { get; set; } public Vector3 entitiesExtentsMin { get; set; } public Vector3 entitiesExtentsMax { get; set; } public byte Unk1 { get; set; } public byte Unk2 { get; set; } public byte Unk3 { get; set; } public byte Unk4 { get; set; } public MapDataStoreNodeExtra UnkExtra { get; set; } public MapDataStoreNode[] Children { get; set; } private List ChildrenList; //used when building the array public CInteriorProxy[] InteriorProxies { get; set; } private List InteriorProxyList; public MapDataStoreNode() { } public MapDataStoreNode(YmapFile ymap) { Name = ymap._CMapData.name; ParentName = ymap._CMapData.parent; ContentFlags = ymap._CMapData.contentFlags; streamingExtentsMin = ymap._CMapData.streamingExtentsMin; streamingExtentsMax = ymap._CMapData.streamingExtentsMax; entitiesExtentsMin = ymap._CMapData.entitiesExtentsMin; entitiesExtentsMax = ymap._CMapData.entitiesExtentsMax; } public MapDataStoreNode(BinaryReader br) { Name = new MetaHash(br.ReadUInt32()); ParentName = new MetaHash(br.ReadUInt32()); ContentFlags = br.ReadUInt32(); streamingExtentsMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); streamingExtentsMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); entitiesExtentsMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); entitiesExtentsMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Unk1 = br.ReadByte(); //HD flag? (critical, long, strm) Unk2 = br.ReadByte(); //lod flag? - primary map files Unk3 = br.ReadByte(); //slod flag? Unk4 = br.ReadByte(); if (Unk1 != 0) { } if (Unk2 != 0) { } if (Unk3 != 0) { } if (Unk4 != 0) { } //no hits here now.. //if (Unk4 == 0xFE) //{ // //this seems to never be hit anymore... // UnkExtra = new MapDataStoreNodeExtra(br); //} } public void Write(DataWriter w) { w.Write(Name); w.Write(ParentName); w.Write(ContentFlags); w.Write(streamingExtentsMin); w.Write(streamingExtentsMax); w.Write(entitiesExtentsMin); w.Write(entitiesExtentsMax); w.Write(Unk1); w.Write(Unk2); w.Write(Unk3); w.Write(Unk4); //if (Unk4 == 0xFE) //{ // if (UnkExtra == null) // { // UnkExtra = new MapDataStoreNodeExtra(); // } // UnkExtra.Write(w); //} } public void WriteXml(StringBuilder sb, int indent) { CacheDatXml.StringTag(sb, indent, "name", CacheDatXml.HashString(Name)); CacheDatXml.StringTag(sb, indent, "parent", CacheDatXml.HashString(ParentName)); CacheDatXml.ValueTag(sb, indent, "contentFlags", ContentFlags.ToString()); CacheDatXml.SelfClosingTag(sb, indent, "streamingExtentsMin " + FloatUtil.GetVector3XmlString(streamingExtentsMin)); CacheDatXml.SelfClosingTag(sb, indent, "streamingExtentsMax " + FloatUtil.GetVector3XmlString(streamingExtentsMax)); CacheDatXml.SelfClosingTag(sb, indent, "entitiesExtentsMin " + FloatUtil.GetVector3XmlString(entitiesExtentsMin)); CacheDatXml.SelfClosingTag(sb, indent, "entitiesExtentsMax " + FloatUtil.GetVector3XmlString(entitiesExtentsMax)); CacheDatXml.ValueTag(sb, indent, "unk1", Unk1.ToString()); CacheDatXml.ValueTag(sb, indent, "unk2", Unk2.ToString()); CacheDatXml.ValueTag(sb, indent, "unk3", Unk3.ToString()); CacheDatXml.ValueTag(sb, indent, "unk4", Unk4.ToString()); } public void ReadXml(XmlNode node) { Name = XmlMeta.GetHash(Xml.GetChildInnerText(node, "name")); ParentName = XmlMeta.GetHash(Xml.GetChildInnerText(node, "parent")); ContentFlags = Xml.GetChildUIntAttribute(node, "contentFlags"); streamingExtentsMin = Xml.GetChildVector3Attributes(node, "streamingExtentsMin"); streamingExtentsMax = Xml.GetChildVector3Attributes(node, "streamingExtentsMax"); entitiesExtentsMin = Xml.GetChildVector3Attributes(node, "entitiesExtentsMin"); entitiesExtentsMax = Xml.GetChildVector3Attributes(node, "entitiesExtentsMax"); Unk1 = (byte)Xml.GetChildUIntAttribute(node, "unk1"); Unk2 = (byte)Xml.GetChildUIntAttribute(node, "unk2"); Unk3 = (byte)Xml.GetChildUIntAttribute(node, "unk3"); Unk4 = (byte)Xml.GetChildUIntAttribute(node, "unk4"); } public void AddChildToList(MapDataStoreNode child) { if (ChildrenList == null) { ChildrenList = new List(); } ChildrenList.Add(child); } public void ChildrenListToArray() { if (ChildrenList != null) { Children = ChildrenList.ToArray(); ChildrenList = null; //plz get this GC } } public void AddInteriorToList(CInteriorProxy iprx) { if (InteriorProxyList == null) { InteriorProxyList = new List(); } InteriorProxyList.Add(iprx); } public void InteriorProxyListToArray() { if (InteriorProxyList != null) { InteriorProxies = InteriorProxyList.ToArray(); InteriorProxyList = null; //plz get this GC } } public override string ToString() { return Name.ToString() + ", " + ParentName.ToString() + ", " + ContentFlags.ToString() + ", " + streamingExtentsMin.ToString() + ", " + streamingExtentsMax.ToString() + ", " + entitiesExtentsMin.ToString() + ", " + entitiesExtentsMax.ToString();// + ", " + } } [TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNodeExtra { public uint Unk01; //0 public byte[] Unk02; //1 - 16 (60 bytes) public uint Unk03;//16 public uint Unk04; public uint Unk05; public uint Unk06; public uint Unk07; public uint Unk08; public uint Unk09; public uint Unk10; public string Unk02str { get { StringBuilder sb = new StringBuilder(); if (Unk02 != null) { for (int i = 0; i < Unk02.Length; i++) { if (Unk02[i] == 0) break; sb.Append((char)Unk02[i]); } } return sb.ToString(); } } public MapDataStoreNodeExtra() { } public MapDataStoreNodeExtra(BinaryReader br) { Unk01 = br.ReadUInt32(); Unk02 = new byte[60]; for (int i = 0; i < 60; i++) { Unk02[i] = br.ReadByte(); } Unk03 = br.ReadUInt32(); Unk04 = br.ReadUInt32(); Unk05 = br.ReadUInt32(); Unk06 = br.ReadUInt32(); Unk07 = br.ReadUInt32(); Unk08 = br.ReadUInt32(); Unk09 = br.ReadUInt32(); Unk10 = br.ReadUInt32(); } public void Write(DataWriter w) { w.Write(Unk01); var alen = Unk02?.Length ?? 0; for (int i = 0; i < 60; i++) { w.Write((i < alen) ? Unk02[i] : (byte)0); } w.Write(Unk03); w.Write(Unk04); w.Write(Unk05); w.Write(Unk06); w.Write(Unk07); w.Write(Unk08); w.Write(Unk09); w.Write(Unk10); } public override string ToString() { return Unk01.ToString() + ", " + Unk02str; } } public class CacheDatXml : MetaXmlBase { public static string GetXml(CacheDatFile cdf) { StringBuilder sb = new StringBuilder(); sb.AppendLine(XmlHeader); if (cdf != null) { var name = "CacheFile"; OpenTag(sb, 0, name); cdf.WriteXml(sb, 1); CloseTag(sb, 0, name); } return sb.ToString(); } } public class XmlCacheDat { public static CacheDatFile GetCacheDat(string xml) { XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); return GetCacheDat(doc); } public static CacheDatFile GetCacheDat(XmlDocument doc) { CacheDatFile cdf = new CacheDatFile(); cdf.ReadXml(doc.DocumentElement); return cdf; } } }