Пример #1
0
        internal void WriteDBC(DBCFile <T> dbcFile, string path, string signature)
        {
            using var fileStream = File.OpenWrite(path);
            using var writer     = new BinaryWriter(fileStream);
            // Sign the file with the signature
            var signatureBytes = Encoding.UTF8.GetBytes(signature);

            writer.Write(signatureBytes);
            writer.Write(dbcFile.Records.Count);

            // Get fields of the DBC type and write to the DBC file
            var dbcType    = dbcFile.GetDBCType();
            var fields     = dbcType.GetFields();
            int fieldCount = DBCUtility.FieldCount(fields, dbcType);

            writer.Write(fieldCount);
            writer.Write(fieldCount * 4);
            writer.Write(0);

            // Adding an empty string to obtain the correct size
            if (signature == "WDBC")
            {
                AddStringToDictionary(string.Empty);
            }

            foreach (var record in dbcFile.Records)
            {
                foreach (var field in fields)
                {
                    switch (Type.GetTypeCode(field.FieldType))
                    {
                    case TypeCode.Object:
                    {
                        if (field.FieldType == typeof(LocalizedString))
                        {
                            int position = AddStringToDictionary((LocalizedString)field.GetValue(record));

                            // Local strings before the local position
                            for (uint i = 0; i < dbcFile.LocalPosition; ++i)
                            {
                                writer.Write(0);
                            }

                            // Write to the Local Position
                            writer.Write(position);

                            // Local strings after the local position
                            for (uint j = dbcFile.LocalPosition + 1; j < LocalizedString.Size - 1; ++j)
                            {
                                writer.Write(0);
                            }

                            // 17th location field
                            writer.Write(dbcFile.LocalFlag);
                        }
                        else
                        {
                            if (field.GetValue(record) is Array array)
                            {
                                int arrayLength = array.Length;

                                switch (Type.GetTypeCode(field.FieldType.GetElementType()))
                                {
                                case TypeCode.Int32:
                                    for (var i = 0; i < arrayLength; ++i)
                                    {
                                        writer.Write((int)array.GetValue(i));
                                    }
                                    break;

                                case TypeCode.UInt32:
                                    for (var i = 0; i < arrayLength; ++i)
                                    {
                                        writer.Write((uint)array.GetValue(i));
                                    }
                                    break;

                                case TypeCode.Single:
                                    for (var i = 0; i < arrayLength; ++i)
                                    {
                                        writer.Write((float)array.GetValue(i));
                                    }
                                    break;

                                default:
                                    throw new NotImplementedException(Type.GetTypeCode(field.FieldType.GetElementType()).ToString());
                                }
                            }
                        }
                        break;
                    }

                    case TypeCode.Byte:
                    {
                        var value = (byte)field.GetValue(record);
                        writer.Write(value);
                        break;
                    }

                    case TypeCode.Int32:
                    {
                        var value = (int)field.GetValue(record);
                        writer.Write(value);
                        break;
                    }

                    case TypeCode.UInt32:
                    {
                        var value = (uint)field.GetValue(record);
                        writer.Write(value);
                        break;
                    }

                    case TypeCode.String:
                    {
                        var str = field.GetValue(record) as string;
                        writer.Write(AddStringToDictionary(str));
                        break;
                    }

                    case TypeCode.Single:
                    {
                        var value = (float)field.GetValue(record);
                        writer.Write(value);
                        break;
                    }

                    default:
                        throw new NotImplementedException(Type.GetTypeCode(field.FieldType).ToString());
                    }
                }
            }

            // Write all of the strings to the DBC file
            foreach (var stringTableBytes in stringTable.Values.Select(str => Encoding.UTF8.GetBytes(str)))
            {
                writer.Write(stringTableBytes);
                writer.Write((byte)0);
            }

            // TODO: Allow for dynamic header size
            writer.BaseStream.Position = 16;
            if (stringTable.Count > 0)
            {
                writer.Write(stringTable.Last().Key + Encoding.UTF8.GetByteCount(stringTable.Last().Value) + 1);
            }
        }
Пример #2
0
        internal void ReadDBC(DBCFile <T> dbcFile, BinaryReader reader, DBCInfo info)
        {
            if (reader is null)
            {
                return;
            }

            // Validate the DBC fields
            var fields      = dbcFile.GetDBCType().GetFields();
            int fieldCounts = dbcFile.FieldCount(fields, dbcFile.GetDBCType());

            if (info.DBCFields != fieldCounts)
            {
                throw new InvalidDBCFields(dbcFile.GetDBCType().ToString());
            }

            // We don't need to read the first bytes again (signature, dbcRecords, dbcFields, recordSize & stringSize)
            long headerSize = reader.BaseStream.Position;

            // Set position of reader
            reader.BaseStream.Position = info.DBCRecords * info.RecordSize + headerSize;

            var    stringData = reader.ReadBytes((int)info.StringSize);
            string fullString = Encoding.UTF8.GetString(stringData);
            var    strings    = fullString.Split(new[] { '\0' }, StringSplitOptions.None);

            var stringTable     = new Dictionary <int, string>();
            var currentPosition = 0;

            foreach (string str in strings)
            {
                stringTable.Add(currentPosition, str);
                currentPosition += Encoding.UTF8.GetByteCount(str) + 1;
            }

            // Reset position to base position
            reader.BaseStream.Position = headerSize;

            // Loop through all of the records in the DBC file
            for (uint i = 0; i < info.DBCRecords; ++i)
            {
                var instance = Activator.CreateInstance(dbcFile.GetDBCType());

                foreach (var field in fields)
                {
                    switch (Type.GetTypeCode(field.FieldType))
                    {
                    case TypeCode.Object:
                    {
                        if (field.FieldType == typeof(LocalizedString))
                        {
                            var value = "";
                            for (uint j = 0; j < LocalizedString.Size - 1; ++j)
                            {
                                int offsetKey = reader.ReadInt32();
                                if (value == "" && offsetKey != 0 && stringTable.TryGetValue(offsetKey, out string stringFromTable))
                                {
                                    value = stringFromTable;
                                    dbcFile.LocalPosition = j;
                                }
                            }

                            dbcFile.LocalFlag = reader.ReadUInt32();

                            field.SetValue(instance, (LocalizedString)value);
                        }
                        else if (field.FieldType.IsArray)
                        {
                            Array array;
                            int   arrayLength;

                            switch (Type.GetTypeCode(field.FieldType.GetElementType()))
                            {
                            case TypeCode.Int32:
                                // Get length of array
                                arrayLength = ((int[])field.GetValue(instance)).Length;

                                // Set Array
                                array = new int[arrayLength];

                                // Set Value of DBC object by looping through the array
                                for (var j = 0; j < arrayLength; ++j)
                                {
                                    array.SetValue(reader.ReadInt32(), j);
                                }
                                field.SetValue(instance, array);
                                break;

                            case TypeCode.UInt32:
                                // Get length of array
                                arrayLength = ((uint[])field.GetValue(instance)).Length;

                                // Set Array
                                array = new uint[arrayLength];

                                // Set Value of DBC object by looping through the array
                                for (var j = 0; j < arrayLength; ++j)
                                {
                                    array.SetValue(reader.ReadUInt32(), j);
                                }
                                field.SetValue(instance, array);
                                break;

                            case TypeCode.Single:
                                // Get length of array
                                arrayLength = ((float[])field.GetValue(instance)).Length;

                                // Set Array
                                array = new float[arrayLength];

                                // Set Value of DBC object by looping through the array
                                for (var j = 0; j < arrayLength; ++j)
                                {
                                    array.SetValue(reader.ReadSingle(), j);
                                }
                                field.SetValue(instance, array);
                                break;

                            default:
                                throw new NotImplementedException(Type.GetTypeCode(field.FieldType.GetElementType()).ToString());
                            }
                        }
                        break;
                    }

                    case TypeCode.Byte:
                    {
                        byte value = reader.ReadByte();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.Int32:
                    {
                        int value = reader.ReadInt32();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.UInt32:
                    {
                        uint value = reader.ReadUInt32();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.Single:
                    {
                        float value = reader.ReadSingle();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.String:
                    {
                        // Get offset for string table
                        int offsetKey = reader.ReadInt32();

                        // Check if offset exists in the string table
                        if (!stringTable.TryGetValue(offsetKey, out string stringFromTable))
                        {
                            throw new KeyNotFoundException(offsetKey.ToString());
                        }

                        string value = stringFromTable;
                        field.SetValue(instance, value);
                        break;
                    }

                    default:
                        throw new NotImplementedException(Type.GetTypeCode(field.FieldType).ToString());
                    }
                }

                // Get the first value of the DBC file and use that as key for the DBC record
                var firstValue = fields[0].GetValue(instance);
                var key        = (uint)Convert.ChangeType(firstValue, typeof(uint));
                dbcFile.AddEntry(key, (T)instance);
            }
        }
Пример #3
0
        internal static void ReadDBC(DBCFile <T> dbcFile, BinaryReader reader)
        {
            if (reader is null)
            {
                return;
            }

            var info = DBCUtility.GetDBCInfo(reader);

            // Validate the DBC fields
            var fields      = dbcFile.GetDBCType().GetFields();
            int fieldCounts = DBCUtility.FieldCount(fields, dbcFile.GetDBCType());

            if (info.DBCFields != fieldCounts)
            {
                throw new InvalidDBCFields(dbcFile.GetDBCType().ToString());
            }

            // We don't need to read the first bytes again (signature)
            long headerSize = reader.BaseStream.Position;

            // Extract all strings and construct string table
            var stringTable = DBCUtility.GetStringTable(reader, info, headerSize);

            // Reset position to base position
            reader.BaseStream.Position = headerSize;

            // Loop through all of the records in the DBC file
            for (uint i = 0; i < info.DBCRecords; ++i)
            {
                var instance = Activator.CreateInstance(dbcFile.GetDBCType());

                foreach (var field in fields)
                {
                    switch (Type.GetTypeCode(field.FieldType))
                    {
                    case TypeCode.Object:
                    {
                        if (field.FieldType == typeof(LocalizedString))
                        {
                            var value = "";
                            for (uint j = 0; j < LocalizedString.Size - 1; ++j)
                            {
                                int offsetKey = reader.ReadInt32();
                                if (string.IsNullOrEmpty(value) && offsetKey != 0 && stringTable.TryGetValue(offsetKey, out string stringFromTable))
                                {
                                    value = stringFromTable;
                                    dbcFile.LocalPosition = j;
                                }
                            }

                            dbcFile.LocalFlag = reader.ReadUInt32();

                            field.SetValue(instance, (LocalizedString)value);
                        }
                        else if (field.FieldType.IsArray)
                        {
                            Array array;
                            int   arrayLength;

                            switch (Type.GetTypeCode(field.FieldType.GetElementType()))
                            {
                            case TypeCode.Int32:
                                // Get length of array
                                arrayLength = ((int[])field.GetValue(instance)).Length;

                                // Set Array
                                array = new int[arrayLength];

                                // Set Value of DBC object by looping through the array
                                for (var j = 0; j < arrayLength; ++j)
                                {
                                    array.SetValue(reader.ReadInt32(), j);
                                }
                                field.SetValue(instance, array);
                                break;

                            case TypeCode.UInt32:
                                // Get length of array
                                arrayLength = ((uint[])field.GetValue(instance)).Length;

                                // Set Array
                                array = new uint[arrayLength];

                                // Set Value of DBC object by looping through the array
                                for (var j = 0; j < arrayLength; ++j)
                                {
                                    array.SetValue(reader.ReadUInt32(), j);
                                }
                                field.SetValue(instance, array);
                                break;

                            case TypeCode.Single:
                                // Get length of array
                                arrayLength = ((float[])field.GetValue(instance)).Length;

                                // Set Array
                                array = new float[arrayLength];

                                // Set Value of DBC object by looping through the array
                                for (var j = 0; j < arrayLength; ++j)
                                {
                                    array.SetValue(reader.ReadSingle(), j);
                                }
                                field.SetValue(instance, array);
                                break;

                            default:
                                throw new NotImplementedException(Type.GetTypeCode(field.FieldType.GetElementType()).ToString());
                            }
                        }
                        break;
                    }

                    case TypeCode.Byte:
                    {
                        byte value = reader.ReadByte();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.Int32:
                    {
                        int value = reader.ReadInt32();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.UInt32:
                    {
                        uint value = reader.ReadUInt32();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.Single:
                    {
                        float value = reader.ReadSingle();
                        field.SetValue(instance, value);
                        break;
                    }

                    case TypeCode.String:
                    {
                        // Get offset for string table
                        int offsetKey = reader.ReadInt32();

                        // Check if offset exists in the string table
                        if (!stringTable.TryGetValue(offsetKey, out string stringFromTable))
                        {
                            throw new KeyNotFoundException(offsetKey.ToString());
                        }

                        string value = stringFromTable;
                        field.SetValue(instance, value);
                        break;
                    }

                    default:
                        throw new NotImplementedException(Type.GetTypeCode(field.FieldType).ToString());
                    }
                }

                // Get the first value of the record and use that as the key for the DBC record
                var firstValue = fields[0].GetValue(instance);
                var key        = (uint)Convert.ChangeType(firstValue, typeof(uint));
                dbcFile.AddEntry(key, (T)instance);
            }
        }
Пример #4
0
        internal void WriteDBC(DBCFile <T> file, string path, IComparer <T> comparison)
        {
            var dirName = Path.GetDirectoryName(path);

            if (!string.IsNullOrEmpty(dirName))
            {
                Directory.CreateDirectory(dirName);
            }

            try
            {
                FileStream   strm  = File.OpenWrite(path);
                BinaryWriter bw    = new BinaryWriter(strm);
                byte[]       bytes = Encoding.UTF8.GetBytes("WDBC");
                bw.Write(bytes);
                bw.Write(file.Records.Count);
                Type type       = typeof(T);
                var  fields     = type.GetFields();
                int  fieldCount = DBCHelper.FieldCount(fields, type);

                var classAttribs = typeof(T).GetCustomAttributes(typeof(NoPrimaryAttribute), false);

                bw.Write(fieldCount);

                //The charBaseInfo.dbc is weird, and don't have *4.
                string charBaseInfoPath = Application.ExecutablePath + "\\DBC\\CharBaseInfo.dbc";

                if (path == charBaseInfoPath)
                {
                    bw.Write(fieldCount);
                }
                else
                {
                    bw.Write(fieldCount * 4);
                }

                bw.Write(0);

                // Ajout d'une string vide afin d'obtenir un format blizzlike
                AddStringToTable("");

                List <T> valueCollection = file.Records.ToList();
                if (comparison != null)
                {
                    valueCollection.Sort(comparison);
                }

                // Ecriture de chaque champ de chaque enregistrement
                foreach (var rec in valueCollection)
                {
                    foreach (var field in fields)
                    {
                        switch (Type.GetTypeCode(field.FieldType))
                        {
                        case TypeCode.Int32:
                        {
                            int value = (int)field.GetValue(rec);
                            bw.Write(value);
                            break;
                        }

                        case TypeCode.UInt32:
                        {
                            uint uvalue = (uint)field.GetValue(rec);
                            bw.Write(uvalue);
                            break;
                        }

                        case TypeCode.String:
                        {
                            string str = field.GetValue(rec) as string;
                            bw.Write(AddStringToTable(str));
                            break;
                        }

                        case TypeCode.Single:
                        {
                            float fvalue = (float)field.GetValue(rec);
                            bw.Write(fvalue);
                            break;
                        }

                        //Added typecode byte for the charbaseinfo, don't work properly
                        case TypeCode.Byte:
                            byte bvalue = (byte)field.GetValue(rec);
                            bw.Write(bvalue);
                            break;

                        case TypeCode.Object:
                        {
                            if (field.FieldType == typeof(LocalizedString))
                            {
                                int pos = AddStringToTable((LocalizedString)field.GetValue(rec));
                                for (uint j = 0; j < file.LocalePosition; ++j)
                                {
                                    bw.Write((int)0);
                                }

                                bw.Write(pos);
                                for (uint j = file.LocalePosition + 1; j < 16; ++j)
                                {
                                    bw.Write((int)0);
                                }

                                // 17ème champ de localisation
                                bw.Write((uint)file.LocaleFlag);
                            }
                            else
                            {
                                int   len;
                                Array array;

                                switch (Type.GetTypeCode(field.FieldType.GetElementType()))
                                {
                                case TypeCode.Int32:
                                    array = field.GetValue(rec) as Array;
                                    len   = array.Length;
                                    for (var q = 0; q < len; ++q)
                                    {
                                        bw.Write((int)array.GetValue(q));
                                    }
                                    break;

                                case TypeCode.UInt32:
                                    array = field.GetValue(rec) as Array;
                                    len   = array.Length;
                                    for (var q = 0; q < len; ++q)
                                    {
                                        bw.Write((uint)array.GetValue(q));
                                    }
                                    break;

                                case TypeCode.Single:
                                    array = field.GetValue(rec) as Array;
                                    len   = array.Length;
                                    for (var q = 0; q < len; ++q)
                                    {
                                        bw.Write((float)array.GetValue(q));
                                    }
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }
                            }
                        }
                        break;
                        }
                    }
                }

                foreach (var str in _stringTable.Values)
                {
                    bytes = Encoding.UTF8.GetBytes(str);
                    bw.Write(bytes);
                    bw.Write((byte)0);
                }

                bw.BaseStream.Position = 16;
                if (_stringTable.Count > 0)
                {
                    bw.Write(_stringTable.Last().Key + Encoding.UTF8.GetByteCount(_stringTable.Last().Value) + 1);
                }

                strm.Close();
            }
            catch (IOException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }