A Way To Understand Server Response

Hello, I am working on a plugin for a better consignment experience.
I am sending a request to the server to get attribute stones. Everything seems to work.
I am also listening to server responses to get items after the consignment search. It gives me bunch of hexadecimal numbers such as:

(Opcode) 0xB50C
(Data) 01 02 01 BB 00 00 00 07 00 4E 69 63 6B 73 69 7A 00 6E 1B 00 00 0B 00 00 00 20 A1 07 00 00 00 00 00 54 40 AF 61 00 00 00 00 1A 00 00 00 0A 00 44 61 72 6B 56 6F 6F 44 6F 6F 00 32 1B 00 00 14 00 00 00 47 F4 10 00 00 00 00 00 34 70 AE 61 00 00 00 00

I am planning to listen to opcode “0xB50C”. However, I couldn’t figure out the data. I know some parts of the data like item price, item count, seller name, etc. However, the length of the data keeps changing. For example, sometimes 1 item is described with 40 tuples, sometimes 41 and I think it keeps changing. To be precise, the above example is a response for 3 items with 120x2=240 characters. Is there a way to handle those kinds of responses?

Because the name length is not the same for everyone… look at the two bytes before the name that should be the name length

I guess you will have some trouble to get the required data from the phBot API to be able to parse the Items correctly but maybe you will find a way :smiley:

Here is your example with some notes:

01 //RESPONSE SUCCESS
02 //ITEM COUNT
01 //PAGE COUNT

BB 00 00 00 							//PersonalID
07 00 4E 69 63 6B 73 69 7A 				//NAME -> Nicksiz
00 										//SALE STATUS
6E 1B 00 00 							//REFITEMID -> Attribute stone of dodging(Lvl.8)
------------
0B 00 //STACK COUNT -> 11
00 00									//ITEM CONTENT(DEPENDS OF ITEM TYPEID)
------------ 
20 A1 07 00 00 00 00 00 				//MONEY -> 500.000
54 40 AF 61								//REGDATE
00 00 00 00
 
1A 00 00 00 							//PersonalID
0A 00 44 61 72 6B 56 6F 6F 44 6F 6F 	//NAME -> DarkVooDoo
00 										//SALE STATUS
32 1B 00 00 							//REFITEMID -> Attribute stone of focus(Lvl.8)
------------
14 00 //STACK COUNT -> 20
00 00 									//ITEM CONTENT(DEPENDS OF ITEM TYPEID)
------------ 
47 F4 10 00 00 00 00 00 				//MONEY -> 1.111.111
34 70 AE 61 							//REGDATE
00 00 00 00

Here some pseudocode written in C#

public void AnalyzeConsignment(Packet p)
{
    byte statusCode = p.ReadByte();
    if(statusCode == 1)
    {
        int itemCount = p.ReadByte();
        int pagesCount = p.ReadByte();
        for(int i = 0; i < itemCount; i++)
        {
            p.ReadUInt32();                     //PersonalID
            string playerName = p.ReadAscii();  //PlayerName
            p.ReadByte();                       //SaleStatus
            uint itemID = p.ReadUInt32();       //RefItemID
            Item item = new Item(itemID,p);     //ItemReader based on ItemTypeID
            ulong money = p.ReadUInt64();       //Costs
            p.ReadUInt32();                     //RegDate
            p.ReadUInt32();                     //Normally not here, IDK why for your server
        }
    }  
}

The part with “Item item = new Item(itemID)” is the part where you get the problems. You will have to know which ItemType the RefItemID belongs and have to read it depending what it is. For example a attribute stone only contains the “stack” and a armor/weapon item contains more information like plus,attributes,blues. So these item data are longer.

Have fun

You took away the fun from him

1 Like

But I took some fun out of it :stuck_out_tongue:
There is a lot of “fun” left, depends how he wants to build it. I didnt post a single line of python code so to get this working, even without beeing variable(ItemReader), he has to write a bit.

That is going to be helpful! Thank you so much @Delirus :slight_smile:

Just a demonstration to handle “attributes stones” in consignment:

import struct
import time

def int2str(number):
    return chr(number)
    
def epoch2Date(epoch):
	return time.strftime("%d-%m-%Y %H:%M:%S", time.localtime(epoch))
	
def analyzeData(data):
	result = {}
	packIndex = 0
	response = struct.unpack_from("B", data, packIndex)[0]
	packIndex += 1
	if response == 1:
		itemCount = struct.unpack_from("B", data, packIndex)[0]
		packIndex += 1
		pageCount = struct.unpack_from("B", data, packIndex)[0]
		packIndex += 1
		result['response'] = response
		result['itemCount'] = itemCount
		result['pageCount'] = pageCount
		result['items'] = []
		for i in range(0, itemCount):
			personalID = struct.unpack_from("I", data, packIndex)[0]
			packIndex += 4
			nameLength = struct.unpack_from("H", data, packIndex)[0]
			packIndex += 2
			charName = ""
			for i in range(0, nameLength):
				nameCharacterHex = struct.unpack_from("B", data, packIndex)[0]
				charName += int2str(nameCharacterHex)
				packIndex += 1

			saleStatus = struct.unpack_from("B", data, packIndex)[0]
			packIndex += 1
			refItemId = struct.unpack_from("I", data, packIndex)[0]
			packIndex += 4
			stackCount = struct.unpack_from("H", data, packIndex)[0]
			packIndex += 2
			itemContent = struct.unpack_from("H", data, packIndex)[0]
			packIndex += 2
			price = struct.unpack_from("Q", data, packIndex)[0]
			packIndex += 8
			regDate = epoch2Date(struct.unpack_from("Q", data, packIndex)[0])
			packIndex += 8
			resultItem = {
				'personalID': personalID,
				'charName': charName,
				'refItemId': refItemId,
				'itemContent': itemContent,
				'price': price,
				'regDate': regDate
			}
			result['items'].append(resultItem)

	return result
	
data = b'\x01\x02\x01\xBB\x00\x00\x00\x07\x00\x4E\x69\x63\x6B\x73\x69\x7A\x00\x6E\x1B\x00\x00\x0B\x00\x00\x00\x20\xA1\x07\x00\x00\x00\x00\x00\x54\x40\xAF\x61\x00\x00\x00\x00\x1A\x00\x00\x00\x0A\x00\x44\x61\x72\x6B\x56\x6F\x6F\x44\x6F\x6F\x00\x32\x1B\x00\x00\x14\x00\x00\x00\x47\xF4\x10\x00\x00\x00\x00\x00\x34\x70\xAE\x61\x00\x00\x00\x00'

print(analyzeData(data))

And result:

{
   "response":1,
   "itemCount":2,
   "pageCount":1,
   "items":[
      {
         "personalID":187,
         "charName":"Nicksiz",
         "refItemId":7022,
         "itemContent":0,
         "price":500000,
         "regDate":"07-12-2021 11:07:00"
      },
      {
         "personalID":26,
         "charName":"DarkVooDoo",
         "refItemId":6962,
         "itemContent":0,
         "price":1111111,
         "regDate":"06-12-2021 20:19:00"
      }
   ]
}

Now, I have to come up with a solution to handle different item types :slight_smile: