Exemplo n.º 1
0
        public unsafe bool LoadData()
        {
            if (IsLoaded)
            {
                return(true);
            }

            byte[] signature = mReader.ReadBytes(4);
            string str       = Encoding.UTF8.GetString(signature);

            if (str != "WDBC")
            {
                throw new Exception("Invalid signature in DBC file!");
            }

            var fields     = mCreationType.GetFields();
            int fieldCount = DBCHelper.FieldCount(fields, mCreationType);

            uint numRecords = mReader.ReadUInt32();
            uint numFields  = mReader.ReadUInt32();
            uint recordSize = mReader.ReadUInt32();
            uint stringSize = mReader.ReadUInt32();

            mReader.BaseStream.Position = numRecords * recordSize + 20;
            byte[] stringData = mReader.ReadBytes((int)stringSize);
            string fullStr    = Encoding.UTF8.GetString(stringData);

            string[] strings = fullStr.Split(new string[] { "\0" }, StringSplitOptions.None);
            Dictionary <int, string> stringTable = new Dictionary <int, string>();
            int curPos = 0;

            foreach (var strEnt in strings)
            {
                stringTable.Add(curPos, strEnt);
                curPos += Encoding.UTF8.GetByteCount(strEnt) + 1;
            }

            mReader.BaseStream.Position = 20;

            if (numFields != fieldCount)
            {
                throw new Exception("numFields != fieldCount in " + FileName + "!");
            }

            for (uint i = 0; i < numRecords; ++i)
            {
                var  t        = Activator.CreateInstance(mCreationType);
                long posStart = mReader.BaseStream.Position;
                foreach (var field in fields)
                {
                    switch (Type.GetTypeCode(field.FieldType))
                    {
                    case TypeCode.Int32:
                    {
                        int value = mReader.ReadInt32();
                        field.SetValue(t, value);
                        break;
                    }

                    case TypeCode.UInt32:
                    {
                        uint uvalue = mReader.ReadUInt32();
                        field.SetValue(t, uvalue);
                        break;
                    }

                    case TypeCode.String:
                    {
                        int    offset = mReader.ReadInt32();
                        string strFromTable;
                        if (!stringTable.TryGetValue(offset, out strFromTable))
                        {
                            throw new InvalidOperationException("Invalid index into stringtable found!");
                        }

                        string strVal = strFromTable;
                        field.SetValue(t, strVal);
                        break;
                    }

                    case TypeCode.Byte:
                    {
                        byte bvalue = mReader.ReadByte();
                        field.SetValue(t, bvalue);
                        break;
                    }

                    case TypeCode.Object:
                    {
                        try
                        {
                            if (field.FieldType == typeof(LocalizedString))
                            {
                                string strValue = "";
                                for (uint j = 0; j < 16; ++j)
                                {
                                    int    offset = mReader.ReadInt32();
                                    string strFromTable;
                                    if (strValue == "" && offset != 0 && stringTable.TryGetValue(offset, out strFromTable))
                                    {
                                        strValue       = strFromTable;
                                        LocalePosition = j;
                                    }
                                }

                                // Flag de localisation, utile du côté client ?
                                LocaleFlag = mReader.ReadUInt32();

                                field.SetValue(t, (LocalizedString)strValue);
                            }
                            else if (field.FieldType.IsArray)
                            {
                                int   len;
                                Array array;

                                switch (Type.GetTypeCode(field.FieldType.GetElementType()))
                                {
                                case TypeCode.Int32:
                                    len   = ((int[])field.GetValue(t)).Length;
                                    array = new int[len];
                                    for (var q = 0; q < len; ++q)
                                    {
                                        array.SetValue(mReader.ReadInt32(), q);
                                    }
                                    field.SetValue(t, array);
                                    break;

                                case TypeCode.UInt32:
                                    len   = ((uint[])field.GetValue(t)).Length;
                                    array = new uint[len];
                                    for (var q = 0; q < len; ++q)
                                    {
                                        array.SetValue(mReader.ReadUInt32(), q);
                                    }
                                    field.SetValue(t, array);
                                    break;

                                case TypeCode.Single:
                                    len   = ((float[])field.GetValue(t)).Length;
                                    array = new float[len];
                                    for (var q = 0; q < len; ++q)
                                    {
                                        array.SetValue(mReader.ReadSingle(), q);
                                    }
                                    field.SetValue(t, array);
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }
                            }
                        }
                        catch (System.Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                        }

                        break;
                    }

                    case TypeCode.Single:
                    {
                        float fvalue = mReader.ReadSingle();
                        field.SetValue(t, fvalue);
                        break;
                    }
                    }
                }


                long posEnd   = mReader.BaseStream.Position;
                var  firstVal = fields[0].GetValue(t);

                var  classAttribs = typeof(T).GetCustomAttributes(typeof(NoPrimaryAttribute), false);
                uint id;
                if (classAttribs.Length == 0)
                {
                    id = (uint)Convert.ChangeType(firstVal, typeof(uint));
                }
                else
                {
                    id = (uint)mRecords.Count();
                }

                if (mConverter == null)
                {
                    mRecords.Add(id, (T)t);
                }
                else
                {
                    mRecords.Add(id, mConverter.Convert(t));
                }
            }

            IsLoaded = true;

            mReader.Close(); // On peut sauvegarder par dessus notre mReader :D !

            return(true);
        }
Exemplo n.º 2
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);
            }
        }