Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Dat structures and tests for UILayout and DbProperties #4208

Merged
merged 1 commit into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions Source/ACE.DatLoader.Tests/DatTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ namespace ACE.DatLoader.Tests
[TestClass]
public class DatTests
{
private static string cellDatLocation = @"C:\Turbine\Asheron's Call\client_cell_1.dat";
private static string DAT_PATH = @"C:\Turbine\Asheron's Call\";

private static string cellDatLocation = DAT_PATH + "client_cell_1.dat";
private static int expectedCellDatFileCount = 805003;

private static string portalDatLocation = @"C:\Turbine\Asheron's Call\client_portal.dat";
private static string portalDatLocation = DAT_PATH + "client_portal.dat";
private static int expectedPortalDatFileCount = 79694;

private static string localEnglishDatLocation = @"C:\Turbine\Asheron's Call\client_local_English.dat";
private static string localEnglishDatLocation = DAT_PATH + "client_local_English.dat";
private static int expectedLocalEnglishDatFileCount = 118;


Expand Down Expand Up @@ -114,6 +116,11 @@ public void UnpackCellDatFiles_NoExceptions()
[TestMethod]
public void UnpackPortalDatFiles_NoExceptions()
{
// We need to init the DatManager to load PortalDat.MasterProperty for the BaseProperty references for DbProperties
// And we need the code page for some of the PortalDat autoload types
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
DatManager.Initialize(DAT_PATH, true, false);

var assembly = typeof(DatDatabase).GetTypeInfo().Assembly;
var types = assembly.GetTypes().Where(t => t.GetCustomAttributes(typeof(DatFileTypeAttribute), false).Length > 0).ToList();

Expand All @@ -133,12 +140,11 @@ public void UnpackPortalDatFiles_NoExceptions()
Assert.IsNotNull(fileType, $"Key: 0x{kvp.Key:X8}, ObjectID: 0x{kvp.Value.ObjectId:X8}, FileSize: {kvp.Value.FileSize}");

// These file types aren't converted yet
if (fileType == DatFileType.KeyMap) continue;
if (fileType == DatFileType.RenderMaterial) continue;
if (fileType == DatFileType.MaterialModifier) continue;
if (fileType == DatFileType.MaterialInstance) continue;
if (fileType == DatFileType.ActionMap) continue;
if (fileType == DatFileType.DbProperties) continue;
if (fileType == DatFileType.KeyMap) continue; // 0x14, 2 files
if (fileType == DatFileType.RenderMaterial) continue; // 0x16, 1 file
if (fileType == DatFileType.MaterialModifier) continue; // 0x17, 1 file
if (fileType == DatFileType.MaterialInstance) continue; // 0x18, 1 file
if (fileType == DatFileType.ActionMap) continue; // 0x26, 1 file

var type = types
.SelectMany(m => m.GetCustomAttributes(typeof(DatFileTypeAttribute), false), (m, a) => new { m, a })
Expand Down Expand Up @@ -173,6 +179,11 @@ public void UnpackPortalDatFiles_NoExceptions()
[TestMethod]
public void UnpackLocalEnglishDatFiles_NoExceptions()
{
// We need to init the DatManager to load PortalDat.MasterProperty for the BaseProperty references for UiLayout/LayoutDesc
// And we need the code page for some of the PortalDat autoload types
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
DatManager.Initialize(DAT_PATH, true, false);

var assembly = typeof(DatDatabase).GetTypeInfo().Assembly;
var types = assembly.GetTypes().Where(t => t.GetCustomAttributes(typeof(DatFileTypeAttribute), false).Length > 0).ToList();

Expand All @@ -191,9 +202,6 @@ public void UnpackLocalEnglishDatFiles_NoExceptions()
//Assert.IsNotNull(fileType, $"Key: 0x{kvp.Key:X8}, ObjectID: 0x{kvp.Value.ObjectId:X8}, FileSize: {kvp.Value.FileSize}, BitFlags:, 0x{kvp.Value.BitFlags:X8}");
Assert.IsNotNull(fileType, $"Key: 0x{kvp.Key:X8}, ObjectID: 0x{kvp.Value.ObjectId:X8}, FileSize: {kvp.Value.FileSize}");

// These file types aren't converted yet
if (fileType == DatFileType.UiLayout) continue;

var type = types
.SelectMany(m => m.GetCustomAttributes(typeof(DatFileTypeAttribute), false), (m, a) => new { m, a })
.Where(t => ((DatFileTypeAttribute)t.a).FileType == fileType)
Expand Down
108 changes: 108 additions & 0 deletions Source/ACE.DatLoader/Entity/BaseProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using ACE.Entity.Enum;
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;

namespace ACE.DatLoader.Entity
{
public class BaseProperty : IUnpackable
{
// If this is in a collection/hashtable, this will actually match the key in that table.
// The enum value of this can be looked up in MasterProperty
public uint Id;

public BasePropertyType PropertyType; // This is read from the MasterProperty table

// Depending on the PropertyType, one of these values will be populated
public uint ValueEnum;
public bool ValueBool;
public uint ValueDataFile;
public float ValueFloat;
public StringInfo ValueString;
public uint ValueColor;
public List<BaseProperty> ValueArray;
public int ValueInt;
public Dictionary<uint, BaseProperty> ValueStruct;
public Vector3 ValueVector;
public uint ValueBitfield32;
public ulong ValueBitfield64;
public uint ValueInstanceId;

public void Unpack(BinaryReader reader)
{
Id = reader.ReadUInt32();

if (!DatManager.PortalDat.MasterProperty.m_properties.ContainsKey(Id))
throw (new Exception("Unable to locate BaseProperty type in the MasterProperty table"));

PropertyType = DatManager.PortalDat.MasterProperty.m_properties[Id].m_propertyType;
switch(PropertyType)
{
case BasePropertyType.Enum:
ValueEnum = reader.ReadUInt32();
break;
case BasePropertyType.Bool:
ValueBool = reader.ReadBoolean();
break;
case BasePropertyType.DataFile:
ValueDataFile = reader.ReadUInt32();
break;
case BasePropertyType.Float:
ValueFloat = reader.ReadSingle();
break;
case BasePropertyType.StringInfo:
ValueString = new StringInfo();
ValueString.Unpack(reader);
break;
case BasePropertyType.Color:
ValueColor = reader.ReadUInt32();
break;
case BasePropertyType.Array:
ValueArray = new List<BaseProperty>();
ValueArray.Unpack(reader);
break;
case BasePropertyType.Integer:
ValueInt = reader.ReadInt32();
break;
case BasePropertyType.Struct:
ValueStruct = new Dictionary<uint, BaseProperty>();

// This packed list uses a little different format not handled in the unpackable extensions
reader.ReadByte(); // bucketSize?
var totalObjects = reader.ReadByte();
for (int i = 0; i < totalObjects; i++)
{
var key = reader.ReadUInt32();

var item = new BaseProperty();
item.Unpack(reader);
ValueStruct.Add(key, item);
}
break;
case BasePropertyType.String:
// No use cases in end-of-retail Dat files.
// While there are a couple of MasterProperty entries of this type, there are no BaseProperty entries that use them.
break;
case BasePropertyType.Vector:
ValueVector = reader.ReadVector3();
break;
case BasePropertyType.Bitfield32:
ValueBitfield32 = reader.ReadUInt32();
break;
case BasePropertyType.Bitfield64:
ValueBitfield64 = reader.ReadUInt64();
break;
case BasePropertyType.InstanceID:
ValueInstanceId = reader.ReadUInt32();
break;
default:
// Should never hit this!
throw new NotImplementedException();
break;
}


}
}
}
70 changes: 35 additions & 35 deletions Source/ACE.DatLoader/Entity/BasePropertyDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,53 @@ namespace ACE.DatLoader.Entity
{
public class BasePropertyDesc : IUnpackable
{
uint m_propertyName;
BasePropertyType m_propertyType;
PropertyGroupName m_propertyGroup;
uint m_propertyProvider;
uint m_data;
int unknown_int_1; // Is this `m_ePatchFlags`?
public uint m_propertyName;
public BasePropertyType m_propertyType;
public PropertyGroupName m_propertyGroup;
public uint m_propertyProvider;
public uint m_data;
public int unknown_int_1; // Is this `m_ePatchFlags`?

bool has_default_value; // Guessed Var Name based on usage
bool hasMax; // Guessed Var Name based on usage
bool hasMin; // Guessed Var Name based on usage
float minFloat;
float maxFloat;
int min;
int max;
public bool has_default_value; // Guessed Var Name based on usage
public bool hasMax; // Guessed Var Name based on usage
public bool hasMin; // Guessed Var Name based on usage
public float minFloat;
public float maxFloat;
public int min;
public int max;

// These are technically all extended BasePropertyValue types, e.g. BoolPropertyValue
bool defaultValueBool;
uint defaultValueColor;
Vector3 defaultValueVector;
int defaultValueInt;
float defaultValueFloat;
uint defaultValueEnum;
uint defaultValueDataFile;
public bool defaultValueBool;
public uint defaultValueColor;
public Vector3 defaultValueVector;
public int defaultValueInt;
public float defaultValueFloat;
public uint defaultValueEnum;
public uint defaultValueDataFile;

float m_fPredictionTimeout;
PropertyInheritanceType m_inheritanceType;
PropertyDatFileType m_datFileType;
PropertyPropagationType m_propagationType;
//PropertyCachingType m_cachingType;
PropertyCachingType m_cachingType;

bool m_bRequired;
bool m_bReadOnly;
bool m_bPropagateToChildren;
bool m_bNoCheckpoint;
bool m_bAbsoluteTimeStamp;
bool m_bGroupable;
bool m_bAllAvailable;
bool m_bDoNotReplay;
bool m_bRecorded;
bool m_bToolOnly;
public bool m_bRequired;
public bool m_bReadOnly;
public bool m_bPropagateToChildren;
public bool m_bNoCheckpoint;
public bool m_bAbsoluteTimeStamp;
public bool m_bGroupable;
public bool m_bAllAvailable;
public bool m_bDoNotReplay;
public bool m_bRecorded;
public bool m_bToolOnly;

Dictionary<uint, uint> m_availableProperties = new Dictionary<uint, uint>();
public Dictionary<uint, uint> m_availableProperties = new Dictionary<uint, uint>();

public void Unpack(BinaryReader reader)
{
// This is a reference to the m_emapper of the MasterProperty. It also matches the SmartArray key
m_propertyName = reader.ReadUInt32();
m_propertyName = reader.ReadUInt32();
m_propertyType = (BasePropertyType)reader.ReadUInt32();
m_propertyGroup = (PropertyGroupName)reader.ReadUInt32();
m_propertyProvider = reader.ReadUInt32();
Expand Down Expand Up @@ -110,7 +110,7 @@ public void Unpack(BinaryReader reader)
}
hasMin = reader.ReadBoolean();
if (hasMax)
{
{
switch (m_propertyType)
{
case BasePropertyType.Float:
Expand Down Expand Up @@ -141,7 +141,7 @@ public void Unpack(BinaryReader reader)
m_bToolOnly = reader.ReadBoolean(); // Always true

var numItems = reader.ReadByte();
for(var i = 0; i < numItems; i++)
for (var i = 0; i < numItems; i++)
{
m_availableProperties.Add(reader.ReadUInt32(), reader.ReadUInt32());
}
Expand Down
88 changes: 88 additions & 0 deletions Source/ACE.DatLoader/Entity/ElementDesc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using ACE.Entity.Enum;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace ACE.DatLoader.Entity
{
public class ElementDesc : StateDesc
{
public uint UiReadOrder;

// Enum names for these are in EnumMapper 0x2200001B (UIElementID)
public uint ElementId;
public uint Type;
public uint BaseElement;
public uint BaseLayout;
public uint DefaultState;

public uint X;
public uint Y;
public uint Width;
public uint Height;
public uint ZLevel;
public uint LeftEdge;
public uint TopEdge;
public uint RightEdge;
public uint BottomEdge;

public Dictionary<uint, StateDesc> States = new Dictionary<uint, StateDesc>();
public Dictionary<uint, ElementDesc> Children = new Dictionary<uint, ElementDesc>();

public override void Unpack(BinaryReader reader)
{
base.Unpack(reader);
UnpackElementDesc(reader);
}

public void UnpackElementDesc(BinaryReader reader)
{
UiReadOrder = reader.ReadUInt32();
ElementId = reader.ReadUInt32();
Type = reader.ReadUInt32();
BaseElement = reader.ReadUInt32();
BaseLayout = reader.ReadUInt32();
DefaultState = reader.ReadUInt32();

if ((UiIncorporationFlags & IncorporationFlags.X) != 0)
X = reader.ReadUInt32();
if ((UiIncorporationFlags & IncorporationFlags.Y) != 0)
Y = reader.ReadUInt32();
if ((UiIncorporationFlags & IncorporationFlags.Width) != 0)
Width = reader.ReadUInt32();
if ((UiIncorporationFlags & IncorporationFlags.Height) != 0)
Height = reader.ReadUInt32();
if ((UiIncorporationFlags & IncorporationFlags.ZLevel) != 0)
ZLevel = reader.ReadUInt32();

LeftEdge = reader.ReadUInt32();
TopEdge = reader.ReadUInt32();
RightEdge = reader.ReadUInt32();
BottomEdge = reader.ReadUInt32();

reader.ReadByte();
var totalObjects = reader.ReadByte();
for (int i = 0; i < totalObjects; i++)
{
var key = reader.ReadUInt32();

var item = new StateDesc();
item.Unpack(reader);
States.Add(key, item);
}

reader.ReadByte();
var totalChildren = reader.ReadByte();
for (int i = 0; i < totalChildren; i++)
{
var key = reader.ReadUInt32();

var item = new ElementDesc();
item.Unpack(reader);
Children.Add(key, item);
}

}
}
}
Loading