2018-02-03 17:54:07 -06:00
using System ;
using System.IO ;
2017-03-04 07:59:37 -05:00
using System.Linq ;
2018-02-03 17:54:07 -06:00
using System.Reflection ;
2017-03-04 07:59:37 -05:00
using Microsoft.VisualStudio.TestTools.UnitTesting ;
2025-10-26 14:38:30 -04:00
[assembly: Parallelize]
2017-03-04 07:59:37 -05:00
namespace ACE.DatLoader.Tests
{
[TestClass]
public class DatTests
{
2024-08-13 11:45:30 -07:00
private static string DAT_PATH = @"C:\Turbine\Asheron's Call\" ;
private static string cellDatLocation = DAT_PATH + "client_cell_1.dat" ;
2018-02-03 17:54:07 -06:00
private static int expectedCellDatFileCount = 805003 ;
2024-08-13 11:45:30 -07:00
private static string portalDatLocation = DAT_PATH + "client_portal.dat" ;
2020-09-01 20:06:29 -05:00
private static int expectedPortalDatFileCount = 79694 ;
2024-08-13 11:45:30 -07:00
private static string localEnglishDatLocation = DAT_PATH + "client_local_English.dat" ;
2020-09-01 20:06:29 -05:00
private static int expectedLocalEnglishDatFileCount = 118 ;
2018-02-03 17:54:07 -06:00
2017-03-04 07:59:37 -05:00
[TestMethod]
public void LoadCellDat_NoExceptions ( )
{
2018-02-05 21:26:06 -06:00
DatDatabase dat = new DatDatabase ( cellDatLocation ) ;
2018-02-09 06:46:49 -06:00
int count = dat . AllFiles . Count ;
2018-02-03 17:54:07 -06:00
//Assert.AreEqual(ExpectedCellDatFileCount, count);
2025-10-26 14:38:30 -04:00
Assert . AreEqual ( expectedCellDatFileCount , count , "Insufficient files parsed from .dat." , $"{expectedCellDatFileCount}" , $"{count}" ) ;
2017-03-04 07:59:37 -05:00
}
[TestMethod]
public void LoadPortalDat_NoExceptions ( )
{
2018-07-05 13:09:20 -07:00
// Init our text encoding options. This will allow us to use more than standard ANSI text, which the client also supports.
System . Text . Encoding . RegisterProvider ( System . Text . CodePagesEncodingProvider . Instance ) ;
2018-02-05 21:26:06 -06:00
DatDatabase dat = new DatDatabase ( portalDatLocation ) ;
2018-02-09 06:46:49 -06:00
int count = dat . AllFiles . Count ;
2018-02-03 17:54:07 -06:00
//Assert.AreEqual(expectedPortalDatFileCount, count);
2025-10-26 14:38:30 -04:00
Assert . AreEqual ( expectedPortalDatFileCount , count , "Insufficient files parsed from .dat." , $"{expectedPortalDatFileCount}" , $"{count}" ) ;
2017-03-04 07:59:37 -05:00
}
2017-03-15 08:12:21 -04:00
2020-09-01 20:06:29 -05:00
[TestMethod]
public void LoadLocalEnglishDat_NoExceptions ( )
{
// Init our text encoding options. This will allow us to use more than standard ANSI text, which the client also supports.
System . Text . Encoding . RegisterProvider ( System . Text . CodePagesEncodingProvider . Instance ) ;
DatDatabase dat = new DatDatabase ( localEnglishDatLocation ) ;
int count = dat . AllFiles . Count ;
//Assert.AreEqual(expectedPortalDatFileCount, count);
2025-10-26 14:38:30 -04:00
Assert . AreEqual ( expectedLocalEnglishDatFileCount , count , "Insufficient files parsed from .dat." , $"{expectedLocalEnglishDatFileCount}" , $"{count}" ) ;
2020-09-01 20:06:29 -05:00
}
2018-02-03 17:54:07 -06:00
2018-02-04 11:16:30 -06:00
[TestMethod]
2018-02-03 17:54:07 -06:00
public void UnpackCellDatFiles_NoExceptions ( )
2017-03-15 08:12:21 -04:00
{
2018-02-04 11:16:30 -06:00
var assembly = typeof ( DatDatabase ) . GetTypeInfo ( ) . Assembly ;
var types = assembly . GetTypes ( ) . Where ( t = > t . GetCustomAttributes ( typeof ( DatFileTypeAttribute ) , false ) . Length > 0 ) . ToList ( ) ;
if ( types . Count = = 0 )
throw new Exception ( "Failed to locate any types with DatFileTypeAttribute." ) ;
2018-02-05 21:26:06 -06:00
DatDatabase dat = new DatDatabase ( cellDatLocation ) ;
2018-02-03 17:54:07 -06:00
foreach ( var kvp in dat . AllFiles )
{
2023-04-10 02:45:09 -07:00
if ( kvp . Key = = 0xFFFF0001 ) // // Iteration info
2020-09-01 19:59:47 -05:00
continue ;
2018-02-05 08:48:01 -06:00
if ( kvp . Value . FileSize = = 0 ) // DatFileType.LandBlock files can be empty
continue ;
2018-02-06 10:18:38 -06:00
var fileType = kvp . Value . GetFileType ( DatDatabaseType . Cell ) ;
2018-02-03 17:54:07 -06:00
2018-02-05 11:17:57 -06:00
if ( ( kvp . Key & 0xFFFF ) = = 0xFFFE ) fileType = DatFileType . LandBlockInfo ;
if ( ( kvp . Key & 0xFFFF ) = = 0xFFFF ) fileType = DatFileType . LandBlock ;
2018-02-05 08:48:01 -06:00
2018-02-04 11:16:30 -06:00
//Assert.IsNotNull(fileType, $"Key: 0x{kvp.Key:X8}, ObjectID: 0x{kvp.Value.ObjectId:X8}, FileSize: {kvp.Value.FileSize}, BitFlags:, 0x{kvp.Value.BitFlags:X8}");
2020-09-01 19:59:47 -05:00
Assert . IsNotNull ( fileType , $"Key: 0x{kvp.Key:X8}, ObjectID: 0x{kvp.Value.ObjectId:X8}, FileSize: {kvp.Value.FileSize}" ) ;
2018-02-03 17:54:07 -06:00
2018-02-04 11:16:30 -06:00
var type = types
. SelectMany ( m = > m . GetCustomAttributes ( typeof ( DatFileTypeAttribute ) , false ) , ( m , a ) = > new { m , a } )
. Where ( t = > ( ( DatFileTypeAttribute ) t . a ) . FileType = = fileType )
. Select ( t = > t . m ) ;
var first = type . FirstOrDefault ( ) ;
if ( first = = null )
throw new Exception ( $"Failed to Unpack fileType: {fileType}" ) ;
var obj = Activator . CreateInstance ( first ) ;
var unpackable = obj as IUnpackable ;
if ( unpackable = = null )
throw new Exception ( $"Class for fileType: {fileType} does not implement IUnpackable." ) ;
2018-02-05 21:26:06 -06:00
var datReader = new DatReader ( cellDatLocation , kvp . Value . FileOffset , kvp . Value . FileSize , dat . Header . BlockSize ) ;
2018-02-04 11:16:30 -06:00
using ( var memoryStream = new MemoryStream ( datReader . Buffer ) )
using ( var reader = new BinaryReader ( memoryStream ) )
2018-02-05 13:34:12 -06:00
{
2018-02-04 11:16:30 -06:00
unpackable . Unpack ( reader ) ;
2018-02-05 13:34:12 -06:00
if ( memoryStream . Position ! = kvp . Value . FileSize )
throw new Exception ( $"Failed to parse all bytes for fileType: {fileType}, ObjectId: 0x{kvp.Value.ObjectId:X8}. Bytes parsed: {memoryStream.Position} of {kvp.Value.FileSize}" ) ;
}
2018-02-03 17:54:07 -06:00
}
2018-02-04 11:16:30 -06:00
}
2018-02-03 17:54:07 -06:00
[TestMethod]
public void UnpackPortalDatFiles_NoExceptions ( )
{
2024-08-13 11:45:30 -07:00
// 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 ) ;
2018-02-03 17:54:07 -06:00
var assembly = typeof ( DatDatabase ) . GetTypeInfo ( ) . Assembly ;
var types = assembly . GetTypes ( ) . Where ( t = > t . GetCustomAttributes ( typeof ( DatFileTypeAttribute ) , false ) . Length > 0 ) . ToList ( ) ;
if ( types . Count = = 0 )
throw new Exception ( "Failed to locate any types with DatFileTypeAttribute." ) ;
2018-02-05 21:26:06 -06:00
DatDatabase dat = new DatDatabase ( portalDatLocation ) ;
2018-02-03 17:54:07 -06:00
foreach ( var kvp in dat . AllFiles )
{
2023-04-10 02:45:09 -07:00
if ( kvp . Key = = 0xFFFF0001 ) // Iteration info
2018-02-03 17:54:07 -06:00
continue ;
2018-02-06 10:18:38 -06:00
var fileType = kvp . Value . GetFileType ( DatDatabaseType . Portal ) ;
2018-02-03 17:54:07 -06:00
2018-12-02 12:49:52 -05:00
//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}" ) ;
2018-02-03 17:54:07 -06:00
// These file types aren't converted yet
2024-08-13 11:45:30 -07:00
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
2018-02-03 17:54:07 -06:00
var type = types
2023-04-10 02:45:09 -07:00
. SelectMany ( m = > m . GetCustomAttributes ( typeof ( DatFileTypeAttribute ) , false ) , ( m , a ) = > new { m , a } )
. Where ( t = > ( ( DatFileTypeAttribute ) t . a ) . FileType = = fileType )
2018-02-03 17:54:07 -06:00
. Select ( t = > t . m ) ;
var first = type . FirstOrDefault ( ) ;
if ( first = = null )
throw new Exception ( $"Failed to Unpack fileType: {fileType}" ) ;
var obj = Activator . CreateInstance ( first ) ;
var unpackable = obj as IUnpackable ;
if ( unpackable = = null )
throw new Exception ( $"Class for fileType: {fileType} does not implement IUnpackable." ) ;
2018-02-05 21:26:06 -06:00
var datReader = new DatReader ( portalDatLocation , kvp . Value . FileOffset , kvp . Value . FileSize , dat . Header . BlockSize ) ;
2018-02-03 17:54:07 -06:00
using ( var memoryStream = new MemoryStream ( datReader . Buffer ) )
using ( var reader = new BinaryReader ( memoryStream ) )
2018-02-05 13:34:12 -06:00
{
2018-02-03 17:54:07 -06:00
unpackable . Unpack ( reader ) ;
2020-09-01 20:06:29 -05:00
if ( memoryStream . Position ! = kvp . Value . FileSize )
throw new Exception ( $"Failed to parse all bytes for fileType: {fileType}, ObjectId: 0x{kvp.Value.ObjectId:X8}. Bytes parsed: {memoryStream.Position} of {kvp.Value.FileSize}" ) ;
}
}
}
[TestMethod]
public void UnpackLocalEnglishDatFiles_NoExceptions ( )
{
2024-08-13 11:45:30 -07:00
// 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 ) ;
2020-09-01 20:06:29 -05:00
var assembly = typeof ( DatDatabase ) . GetTypeInfo ( ) . Assembly ;
var types = assembly . GetTypes ( ) . Where ( t = > t . GetCustomAttributes ( typeof ( DatFileTypeAttribute ) , false ) . Length > 0 ) . ToList ( ) ;
if ( types . Count = = 0 )
throw new Exception ( "Failed to locate any types with DatFileTypeAttribute." ) ;
DatDatabase dat = new DatDatabase ( localEnglishDatLocation ) ;
foreach ( var kvp in dat . AllFiles )
{
2023-04-10 02:45:09 -07:00
if ( kvp . Key = = 0xFFFF0001 ) // Iteration info
2020-09-01 20:06:29 -05:00
continue ;
var fileType = kvp . Value . GetFileType ( DatDatabaseType . Language ) ;
//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}" ) ;
var type = types
. SelectMany ( m = > m . GetCustomAttributes ( typeof ( DatFileTypeAttribute ) , false ) , ( m , a ) = > new { m , a } )
. Where ( t = > ( ( DatFileTypeAttribute ) t . a ) . FileType = = fileType )
. Select ( t = > t . m ) ;
var first = type . FirstOrDefault ( ) ;
if ( first = = null )
throw new Exception ( $"Failed to Unpack fileType: {fileType}" ) ;
var obj = Activator . CreateInstance ( first ) ;
var unpackable = obj as IUnpackable ;
if ( unpackable = = null )
throw new Exception ( $"Class for fileType: {fileType} does not implement IUnpackable." ) ;
var datReader = new DatReader ( localEnglishDatLocation , kvp . Value . FileOffset , kvp . Value . FileSize , dat . Header . BlockSize ) ;
using ( var memoryStream = new MemoryStream ( datReader . Buffer ) )
using ( var reader = new BinaryReader ( memoryStream ) )
{
unpackable . Unpack ( reader ) ;
2018-02-05 13:34:12 -06:00
if ( memoryStream . Position ! = kvp . Value . FileSize )
throw new Exception ( $"Failed to parse all bytes for fileType: {fileType}, ObjectId: 0x{kvp.Value.ObjectId:X8}. Bytes parsed: {memoryStream.Position} of {kvp.Value.FileSize}" ) ;
}
2018-02-03 17:54:07 -06:00
}
2017-03-15 08:12:21 -04:00
}
// uncomment if you want to run this
// [TestMethod]
public void ExtractCellDatByLandblock ( )
{
string output = @"c:\Turbine\cell_dat_export_by_landblock" ;
2018-02-03 17:54:07 -06:00
CellDatDatabase db = new CellDatDatabase ( cellDatLocation ) ;
2017-03-15 08:12:21 -04:00
db . ExtractLandblockContents ( output ) ;
}
2018-02-03 17:54:07 -06:00
// uncomment if you want to run this
// [TestMethod]
public void ExportPortalDatsWithTypeInfo ( )
{
string output = @"c:\Turbine\typed_portal_dat_export" ;
PortalDatDatabase db = new PortalDatDatabase ( portalDatLocation ) ;
2018-12-02 13:46:01 -06:00
db . ExtractCategorizedPortalContents ( output ) ;
2018-02-03 17:54:07 -06:00
}
2017-03-04 07:59:37 -05:00
}
}