mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-09-19 07:37:33 +08:00
1077 lines
40 KiB
C#
1077 lines
40 KiB
C#
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<uint, MapDataStoreNode> MapNodeDict { get; set; }
|
|
public MapDataStoreNode[] RootMapNodes { get; set; }
|
|
//public Dictionary<MetaHash, CInteriorProxy> InteriorProxyDict { get; set; }
|
|
public Dictionary<MetaHash, BoundsStoreItem> 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<string> lines = new List<string>();
|
|
var dates = new List<CacheFileDate>();
|
|
var allMapNodes = new List<MapDataStoreNode>();
|
|
var allCInteriorProxies = new List<CInteriorProxy>();
|
|
var allBoundsStoreItems = new List<BoundsStoreItem>();
|
|
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 "<fileDates>":
|
|
indates = true;
|
|
break;
|
|
case "</fileDates>":
|
|
indates = false;
|
|
break;
|
|
case "<module>":
|
|
break;
|
|
case "</module>":
|
|
break;
|
|
case "fwMapDataStore":
|
|
ms.Position = i + 1;
|
|
modlen = br.ReadUInt32();
|
|
structcount = modlen / 64;
|
|
lspos = i + (int)modlen + 5;
|
|
while (ms.Position<lspos)
|
|
{
|
|
allMapNodes.Add(new MapDataStoreNode(br));
|
|
}
|
|
//if (allMapNodes.Count != structcount)
|
|
//{ }//test fail due to variable length struct
|
|
i += (int)(modlen + 4);
|
|
break;
|
|
case "CInteriorProxy":
|
|
ms.Position = i + 1;
|
|
modlen = br.ReadUInt32();
|
|
structcount = modlen / 104;
|
|
lspos = i + (int)modlen + 5;
|
|
while (ms.Position < lspos)
|
|
{
|
|
allCInteriorProxies.Add(new CInteriorProxy(br));
|
|
}
|
|
if (allCInteriorProxies.Count != structcount)
|
|
{ }//all pass here
|
|
i += (int)(modlen + 4);
|
|
break;
|
|
case "BoundsStore":
|
|
ms.Position = i + 1;
|
|
modlen = br.ReadUInt32();
|
|
structcount = modlen / 32;
|
|
lspos = i + (int)modlen + 5;
|
|
while (ms.Position < lspos)
|
|
{
|
|
allBoundsStoreItems.Add(new BoundsStoreItem(br));
|
|
}
|
|
if (allBoundsStoreItems.Count != structcount)
|
|
{ }//all pass here
|
|
i += (int)(modlen + 4);
|
|
break;
|
|
default:
|
|
if (!indates)
|
|
{ } //just testing
|
|
else
|
|
{
|
|
dates.Add(new CacheFileDate(line));//eg: 2740459947 (hash of: platform:/data/cdimages/scaleform_frontend.rpf) 130680580712018938 8944
|
|
}
|
|
break;
|
|
}
|
|
|
|
sb.Clear();
|
|
}
|
|
else
|
|
{
|
|
sb.Append((char)b);
|
|
}
|
|
}
|
|
FileDates = dates.ToArray();
|
|
AllMapNodes = allMapNodes.ToArray();
|
|
AllCInteriorProxies = allCInteriorProxies.ToArray();
|
|
AllBoundsStoreItems = allBoundsStoreItems.ToArray();
|
|
|
|
MapNodeDict = new Dictionary<uint, MapDataStoreNode>();
|
|
var rootMapNodes = new List<MapDataStoreNode>();
|
|
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<MetaHash, BoundsStoreItem>();
|
|
foreach (BoundsStoreItem item in AllBoundsStoreItems)
|
|
{
|
|
BoundsStoreItem mbsi = null;
|
|
if (BoundsStoreDict.TryGetValue(item.Name, out mbsi))
|
|
{ }
|
|
BoundsStoreDict[item.Name] = item;
|
|
}
|
|
|
|
//InteriorProxyDict = new Dictionary<MetaHash, CInteriorProxy>();
|
|
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, "<fileDates>\n");
|
|
if (FileDates != null)
|
|
{
|
|
foreach (var d in FileDates)
|
|
{
|
|
WriteString(w, d.ToCacheFileString());
|
|
WriteString(w, "\n");
|
|
}
|
|
}
|
|
WriteString(w, "</fileDates>\n");
|
|
WriteString(w, "<module>\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, "</module>\n");
|
|
WriteString(w, "<module>\nCInteriorProxy\n");
|
|
w.Write((AllCInteriorProxies?.Length ?? 0) * 104);
|
|
if (AllCInteriorProxies != null)
|
|
{
|
|
foreach (var p in AllCInteriorProxies)
|
|
{
|
|
p.Write(w);
|
|
}
|
|
}
|
|
WriteString(w, "</module>\n");
|
|
WriteString(w, "<module>\nBoundsStore\n");
|
|
w.Write((AllBoundsStoreItems?.Length ?? 0) * 32);
|
|
if (AllBoundsStoreItems != null)
|
|
{
|
|
foreach (var b in AllBoundsStoreItems)
|
|
{
|
|
b.Write(w);
|
|
}
|
|
}
|
|
WriteString(w, "</module>\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<CacheFileDate>(node, "FileDates");
|
|
AllMapNodes = XmlMeta.ReadItemArray<MapDataStoreNode>(node, "MapDataStore");
|
|
AllCInteriorProxies = XmlMeta.ReadItemArray<CInteriorProxy>(node, "InteriorProxies");
|
|
AllBoundsStoreItems = XmlMeta.ReadItemArray<BoundsStoreItem>(node, "BoundsStore");
|
|
}
|
|
|
|
|
|
|
|
public string GetXmlOLD()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.AppendLine(MetaXmlBase.XmlHeader);
|
|
sb.AppendLine(string.Format("<CacheDatFile version=\"{0}\">", Version));
|
|
sb.AppendLine(" <fileDates>");
|
|
if (FileDates != null)
|
|
{
|
|
foreach (var date in FileDates)
|
|
{
|
|
sb.AppendLine(string.Format(" <fileDate>{0}</fileDate>", date.ToCacheFileString()));
|
|
}
|
|
}
|
|
sb.AppendLine(" </fileDates>");
|
|
sb.AppendLine(" <module type=\"fwMapDataStore\">");
|
|
if (AllMapNodes != null)
|
|
{
|
|
foreach (var mapnode in AllMapNodes)
|
|
{
|
|
sb.AppendLine(" <Item>");
|
|
sb.AppendLine(string.Format(" <name>{0}</name>", mapnode.Name.ToCleanString()));
|
|
sb.AppendLine(string.Format(" <parent>{0}</parent>", mapnode.ParentName.ToCleanString()));
|
|
sb.AppendLine(string.Format(" <contentFlags value=\"{0}\" />", mapnode.ContentFlags.ToString()));
|
|
sb.AppendLine(string.Format(" <streamingExtentsMin {0} />", FloatUtil.GetVector3XmlString(mapnode.streamingExtentsMin)));
|
|
sb.AppendLine(string.Format(" <streamingExtentsMax {0} />", FloatUtil.GetVector3XmlString(mapnode.streamingExtentsMax)));
|
|
sb.AppendLine(string.Format(" <entitiesExtentsMin {0} />", FloatUtil.GetVector3XmlString(mapnode.entitiesExtentsMin)));
|
|
sb.AppendLine(string.Format(" <entitiesExtentsMax {0} />", FloatUtil.GetVector3XmlString(mapnode.entitiesExtentsMax)));
|
|
sb.AppendLine(string.Format(" <flags unk1=\"{0}\" unk2=\"{1}\" unk3=\"{2}\" />", mapnode.Unk1, mapnode.Unk2, mapnode.Unk3));
|
|
sb.AppendLine(" </Item>");
|
|
}
|
|
}
|
|
sb.AppendLine(" </module>");
|
|
sb.AppendLine(" <module type=\"CInteriorProxy\">");
|
|
if (AllCInteriorProxies != null)
|
|
{
|
|
foreach (var intprox in AllCInteriorProxies)
|
|
{
|
|
sb.AppendLine(" <Item>");
|
|
sb.AppendLine(string.Format(" <name>{0}</name>", intprox.Name.ToCleanString()));
|
|
sb.AppendLine(string.Format(" <parent>{0}</parent>", intprox.Parent.ToCleanString()));
|
|
sb.AppendLine(string.Format(" <position {0} />", FloatUtil.GetVector3XmlString(intprox.Position)));
|
|
sb.AppendLine(string.Format(" <rotation {0} />", FloatUtil.GetQuaternionXmlString(intprox.Orientation)));
|
|
sb.AppendLine(string.Format(" <aabbMin {0} />", FloatUtil.GetVector3XmlString(intprox.BBMin)));
|
|
sb.AppendLine(string.Format(" <aabbMax {0} />", FloatUtil.GetVector3XmlString(intprox.BBMax)));
|
|
sb.AppendLine(string.Format(" <unknowns1 unk01=\"{0}\" unk03=\"{1}\" />", intprox.Unk01, intprox.Unk03));
|
|
sb.AppendLine(string.Format(" <unknowns2 unk11=\"{0}\" unk12=\"{1}\" unk13=\"{2}\" unk14=\"{3}\" />", intprox.Unk11, intprox.Unk12, intprox.Unk13, intprox.Unk14));
|
|
sb.AppendLine(" </Item>");
|
|
}
|
|
}
|
|
sb.AppendLine(" </module>");
|
|
sb.AppendLine(" <module type=\"BoundsStore\">");
|
|
if (AllBoundsStoreItems != null)
|
|
{
|
|
foreach (var bndstore in AllBoundsStoreItems)
|
|
{
|
|
sb.AppendLine(" <Item>");
|
|
sb.AppendLine(string.Format(" <name>{0}</name>", bndstore.Name.ToCleanString()));
|
|
sb.AppendLine(string.Format(" <aabbMin {0} />", FloatUtil.GetVector3XmlString(bndstore.Min)));
|
|
sb.AppendLine(string.Format(" <aabbMax {0} />", FloatUtil.GetVector3XmlString(bndstore.Max)));
|
|
sb.AppendLine(string.Format(" <layer value=\"{0}\" />", bndstore.Layer));
|
|
sb.AppendLine(" </Item>");
|
|
}
|
|
}
|
|
sb.AppendLine(" </module>");
|
|
sb.AppendLine("</CacheDatFile>");
|
|
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<MapDataStoreNode> ChildrenList; //used when building the array
|
|
|
|
public CInteriorProxy[] InteriorProxies { get; set; }
|
|
private List<CInteriorProxy> 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<MapDataStoreNode>();
|
|
}
|
|
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<CInteriorProxy>();
|
|
}
|
|
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;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|