[Release]Loading the 4267 Itemtype.dat

01/29/2010 12:09 Korvacs#1
I recently got a pm about loading the itemtype.dat from the 4267 client and decided i would just make a release for it, this is how i do it anyway. This will not work for the later clients because they are setup differently.

First you will need a data structure to hold the information your going to load, this could be a class if you really wanted although i dont recommend it. Im using a struct:

Code:
        public struct ItemDetail
        {
            public string Name, Description;
            public uint ID, Price;
            public ushort Class, Prof, Level, Str_Req, Dex_Req, Vit_Req,
                Spi_Req, Damage_Max, Damage_Min, Defense_Add, Dex_Add, Dodge_Add,
                HP_Add, MP_Add, Magic_Attack, MDefense_Add, Dura, MaxDura, Frequency;
            public byte Range, TradeType;
        }
This contains all of the information that you could possibly need from the itemtype.dat, there are some fields in the itemtype.dat which are not used from what i can tell, so im not going to load them.

Secondly you need the method to load the itemtype.dat, and heres my version:

Code:
        private static Dictionary<uint, ItemDetail> _Itemdata = new Dictionary<uint, ItemDetail>();

        public static void LoadItemData()
        {
            Console.WriteLine("[Database] Loading Item Data");
            int start = System.Environment.TickCount;
            FileStream File = new FileStream(Constants.ItemTypePath, FileMode.Open);
            BinaryReader Reader = new BinaryReader(File);

            uint Amount = Reader.ReadUInt32();

            ItemDetail _IDetail;

            for (int i = 0; i < Amount; i++)
                Reader.ReadUInt32();

            for (int i = 0; i < Amount; i++)
            {
                _IDetail = new ItemDetail();
                _IDetail.ID = Reader.ReadUInt32();
                for (int x = 0; x < 16; x++)
                {
                    _IDetail.Name += (char)Reader.ReadByte();
                }
                _IDetail.Name = _IDetail.Name.Trim('\0');
                _IDetail.Class = Reader.ReadByte();
                _IDetail.Prof = Reader.ReadByte();
                _IDetail.Level = Reader.ReadUInt16();
                _IDetail.Vit_Req = Reader.ReadUInt16();
                _IDetail.Str_Req = Reader.ReadUInt16();
                _IDetail.Dex_Req = Reader.ReadUInt16();
                _IDetail.Spi_Req = Reader.ReadUInt16();
                _IDetail.TradeType = (byte)Reader.ReadUInt32();
                _IDetail.Price = Reader.ReadUInt32();

                File.Seek(4, SeekOrigin.Current);

                _IDetail.Damage_Max = Reader.ReadUInt16();
                _IDetail.Damage_Min = Reader.ReadUInt16();
                _IDetail.Defense_Add = Reader.ReadUInt16();
                _IDetail.Dex_Add = Reader.ReadUInt16();
                _IDetail.Dodge_Add = Reader.ReadUInt16();
                _IDetail.HP_Add = Reader.ReadUInt16();
                _IDetail.MP_Add = Reader.ReadUInt16(); ;
                _IDetail.Dura = Reader.ReadUInt16();
                _IDetail.MaxDura = Reader.ReadUInt16();
                _IDetail.Magic_Attack = Reader.ReadUInt16();
                _IDetail.MDefense_Add = Reader.ReadUInt16();

                File.Seek(6, SeekOrigin.Current);

                _IDetail.Range = (byte)Reader.ReadUInt16();
                _IDetail.Frequency = Reader.ReadUInt16();

                for (int x = 0; x < 16; x++)
                {
                    _IDetail.Description += (char)Reader.ReadByte();
                }

                _IDetail.Description = _IDetail.Description.Trim('\0');

                if (!_Itemdata.ContainsKey(_IDetail.ID))
                    _Itemdata.Add(_IDetail.ID, _IDetail);

                File.Seek(112, SeekOrigin.Current);
            }

            Console.WriteLine("[Database] Loaded {0} ItemDetails in {1}ms", _Itemdata.Count, Environment.TickCount - start);

            File.Dispose();
            File.Close();
            Reader.Close();
        }
Average loading time on my pc is 180ms. Due to the way the itemtype.dat is layed out i would recommend that you be extremely careful when modifying this method, there it all has to line up otherwise you will end up loading a large amount of useless data.

The dictionary is where the data is stored and can be accessed like this:

Code:
            _Itemdata[ItemID];
You can access the data directly, or by assigning it to anouther object:

Code:
            _Itemdata[ItemID].Class;

            ItemDetail _IDetail = _Itemdata[ItemID];
            _IDetail.Class;
Some of you maybe wondering why this is at the beginning of the method:

Code:
            for (int i = 0; i < Amount; i++)
                Reader.ReadUInt32();
The itemtype.dat contains every itemid at the beginning of the file which you need to get past, this could also be replaced with a seek.

Anyways i think thats everything, any questions feel free to ask.

Thanks are appreciated. :)
01/29/2010 12:21 coreymills#2
nice work korvacs
01/29/2010 15:57 copz1337#3
good job
01/30/2010 05:21 hunterman01#4
Finally a useful release

Thanks brah
04/06/2012 12:50 funhacker#5
Quote:
Originally Posted by Korvacs View Post

Some of you maybe wondering why this is at the beginning of the method:

Code:
            for (int i = 0; i < Amount; i++)
                Reader.ReadUInt32();
The itemtype.dat contains every itemid at the beginning of the file which you need to get past, this could also be replaced with a seek.

Anyways i think thats everything, any questions feel free to ask.

Thanks are appreciated. :)
Just thought you'd like to know what I found with EO.

The part you skip (I refer to as an 'Index Table') contains the IDs that will be used in a Dictionary style variable as keys. Where as the IDs found in the item structure latter on only influence such things as the look of the item. I used this to my advantage when I needed 100s of robes that appeared the same but had different stats. So the itemtype.dat had all the different IDs in the index table but had all the same ids in the item structure.
04/07/2012 14:18 Korvacs#6
Quote:
Originally Posted by funhacker View Post
Just thought you'd like to know what I found with EO.

The part you skip (I refer to as an 'Index Table') contains the IDs that will be used in a Dictionary style variable as keys. Where as the IDs found in the item structure latter on only influence such things as the look of the item. I used this to my advantage when I needed 100s of robes that appeared the same but had different stats. So the itemtype.dat had all the different IDs in the index table but had all the same ids in the item structure.
Im aware of its use, its not required for this guide however.
04/08/2012 10:54 funhacker#7
Quote:
Originally Posted by Korvacs View Post

Some of you maybe wondering why this is at the beginning of the method:

Code:
            for (int i = 0; i < Amount; i++)
                Reader.ReadUInt32();
The itemtype.dat contains every itemid at the beginning of the file which you need to get past, this could also be replaced with a seek.

Anyways i think thats everything, any questions feel free to ask.

Thanks are appreciated. :)
Quote:
Originally Posted by Korvacs View Post
Im aware of its use, its not required for this guide however.
According to your previous post, it seemed you weren't entirely sure of this, I made this assumption as you also only load 16bytes of the description instead of the entire 128 that is given for an item.
04/09/2012 13:27 Korvacs#8
Quote:
Originally Posted by funhacker View Post
According to your previous post, it seemed you weren't entirely sure of this, I made this assumption as you also only load 16bytes of the description instead of the entire 128 that is given for an item.
Why mention something thats not neccassery for a simple guide on how to get the item data out of the itemtype.dat, if i wished to make a complete guide i would have, consider this more of an idiots guide to doing it.

And why would i bother loading the full 128byte description when the server never -ever- uses this data, so at most a developer would need to glance at this information while debugging, beyond that its a complete waste to load it. So by all means if you wish to load the description and use up a load of memory in the process be my guest, but again for the purpose of this basic guide on how to load data from a file like the itemtype.dat, this is perfectly fine.

But thank you for making assuptions and bumping a 2 year old thread.