Wytter Report post Posted August 12, 2005 In 1.0.2 trading will change slightly, i.e. to make quantities 32-bit instead of 16 bit, and to reduce the chance of scamming. When you want to trade with a player it will be the normal procedure: str[0]=TRADE_WITH; *((Uint16*)(str+1)) = 5; *((Uint32*)(str+3)) = player_id; This will cause the other player to get the same trade request string as with 1.0.1. str[0]=127+c_yellow2; *((Uint16*)(str+1))=length; str+3="<player_name> wants to trade with you. Use the trade icon then click on him/her in order to accept the trade."; With multi-channel chat it will be sent to CHAT_SERVER. Once both parties have accepted the server will send GET_YOUR_TRADEOBJECTS in order to make sure that the items are in sync: str[0]=GET_YOUR_TRADEOBJECTS; *((Uint16*)(str+1)) = length; *((Uint8*)(str+3)) = no_items; ptr=str+4; for(i=0;i<no_items;i++){ *((Uint8*)(ptr+i*8+6))=pos;//The position in the items list *((Uint16*)(ptr+i*8)) = item_list[pos].image_id; *((Uint32*)(ptr+i*8+2)) = item_list[pos].quantity; *((Uint8*)(ptr+i*8+7)) = item_list[pos].flags; } If you are near a storage, the server will also send the storage categories (see http://www.eternal-lands.com/forum/index.php?showtopic=16313 for more info): *((Uint8*)(str+0)=STORAGE_LIST; *((Uint16*)(str+1)=length; *((Uint8*)(str+3)=no_categories; ptr=str+4; for(i=0;i<length-3;i++){ *((Uint8*)(ptr+0))=category_id; ((Uint8*)(ptr+1))=category_name; //terminated by \0 increase(ptr); } If you've previously opened a category it'll send you the items in that category as well: *((Uint8*)(str+0))=STORAGE_ITEMS; *((Uint16*)(str+1))=length; *((Uint8*)(str+3))=no_items; if(no_items==255){ //It's just an update containing 1 item for the current category *((Uint8*)((str+4))=category; *((Uint16*)(str+5))=image_id; *((Uint32*)(str+7))=quantity; *((Uint8*)(str+11))=storage_pos;//Position in the server-side storage } else { *((Uint8*)(str+4))=category; ptr=str+5; for(i=0;i<no_items;i++){ *((Uint16*)(ptr))=image_id; *((Uint32*)(ptr+2))=quantity; *((Uint8*)(ptr+6))=storage_pos; increase(ptr); } } Next you will recieve the name of the trade partner. This has changed slightly, since the server will actually tell you whether you have storage available or not (a bit redundant): str[0]=GET_TRADE_PARTNER_NAME; *((Uint16*)(str+1))=length; *((Uint8*)(str+3))=storage_available;//0 for FALSE, 1 for TRUE ((Uint8 *) str+4)="<trade partner name>";//Terminated by \0 Once this is in place, the trade session can begin. You add an item to trade using this: str[0]=PUT_OBJECT_ON_TRADE; *((Uint16*)(str+1))=7 *((Uint8*)(str+3))=ITEM_INVENTORY || ITEM_BANK; //Depending on whether you're adding an item from your bank or from your inventory. *((Uint8*)(str+4))=pos;//The position in either your inventory or your bank *((Uint32*)(str+5))=quantity; Adding an object to the trade will either remove it from your inventory or storage or just reduce the quantity. If the quantity is 0 after adding the item, it will be completely removed from your inventory: str[0]=REMOVE_ITEM_FROM_INVENTORY; *((Uint16*)(str+1))=2; *((Uint8*)(str+3))=pos; If the quantity is >0 after adding the item the inventory item will be updated str[0]=GET_NEW_INVENTORY_ITEM; *((Uint16*)(str+1))=9; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=pos; *((Uint8*)(str+10))=flags; If it's a storage item and you are in the same category as the item, the following will be sent: str[0]=STORAGE_ITEMS; *((Uint16*)(str+1))=10; *((Uint8*)(str+3))=255;//Indicates an update *((Uint8*)(str+4))=category; *((Uint16*)(str+5))=image_id; *((Uint32*)(str+7))=quantity; *((Uint8*)(str+11))=pos; To remove a tradeobject do the following: str[0]=REMOVE_ITEM_FROM_TRADE; *((Uint16*)(str+1))=6; *((Uint8*)(str+3))=pos; *((Uint32*)(str+4))=quantity; This will add an item to the inventory or storage: str[0]=GET_NEW_INVENTORY_ITEM; *((Uint16*)(str+1))=9; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=pos; *((Uint8*)(str+10))=flags; The storage item will only be sent if you are in that category. str[0]=STORAGE_ITEMS; *((Uint16*)(str+1))=10; *((Uint8*)(str+3))=255;//Indicates an update *((Uint8*)(str+4))=category; *((Uint16*)(str+5))=image_id; *((Uint32*)(str+7))=quantity; *((Uint8*)(str+11))=pos; If you want to see the item string for that given object, do the following: #define YOUR_TRADE_LIST 0 #define OTHERS_TRADE_LIST 1 str[0]=LOOK_AT_TRADE_ITEM; *((Uint16*)(str+1))=length; *((Uint8*)(str+3))=pos; *((Uint8*)(str+4))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST;//Whether you want to see the item from your or the others trade list. Whenever a trade object is added the following will be sent to the client: str[0]=GET_TRADE_OBJECT; *((Uint16*)(str+1))=10; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=type; *((Uint8*)(str+10))=pos; *((Uint8*)(str+11))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST; If an object is removed the following will be sent: str[0]=REMOVE_TRADE_OBJECT; *((Uint16*)(str+1))=7; *((Uint32*)(str+3))=quantity; *((Uint8*)(str+7))=pos; *((Uint8*)(str+8))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST; To accept the trade, send the following to the server: str[0]=ACCEPT_TRADE; *((Uint16*)(str+1))=1; If you have already accepted the trade once, you have to send the targets for all of the items as well: #define ITEM_INVENTORY 1 #define ITEM_BANK 2 str[0]=ACCEPT_TRADE; *((Uint16*)(str+1))=17; for(i=0;i<16;i++){ *((Uint8*)(str+3+i))=ITEM_INVENTORY || ITEM_BANK; } Whenever a trade accept is recieved by the server it will send the following to the clients: str[0]=GET_TRADE_ACCEPT; *((Uint16*)(str+1))=2; *((Uint8*)(str+3))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST;//Whether it's you or your trade partner that has accepted. In 1.0.2 the accept works slightly different than in 1.0.1. As soon as both parties have pressed ACCEPT_TRADE, the trade session will be locked - this means that nothing will be put on trade or removed from the trade - this will give you time to evaluate all items and see that they are correct. Once you've evaluated the trade session and accepted it you can send another ACCEPT_TRADE, then wait for your trade partner to do the same - once this is done you will get your new items: str[0]=GET_YOUR_ITEMS; *((Uint16*)(str+1)) = length; *((Uint8*)(str+3)) = no_items; ptr=str+4; for(i=0;i<no_items;i++){ *((Uint8*)(ptr+i*8+6))=pos;//The position in the items list *((Uint16*)(ptr+i*8)) = item_list[pos].image_id; *((Uint32*)(ptr+i*8+2)) = item_list[pos].quantity; *((Uint8*)(ptr+i*8+7)) = item_list[pos].flags; } And the last storage category you opened will be resend: *((Uint8*)(str+0))=STORAGE_ITEMS; *((Uint16*)(str+1))=length; *((Uint8*)(str+3))=no_items; if(no_items==255){ //It's just an update containing 1 item for the current category *((Uint8*)((str+4))=category; *((Uint16*)(str+5))=image_id; *((Uint32*)(str+7))=quantity; *((Uint8*)(str+11))=storage_pos;//Position in the server-side storage } else { *((Uint8*)(str+4))=category; ptr=str+5; for(i=0;i<no_items;i++){ *((Uint16*)(ptr))=image_id; *((Uint32*)(ptr+2))=quantity; *((Uint8*)(ptr+6))=storage_pos; increase(ptr); } } If you wish to reject the trade, send the following to the server: str[0]=REJECT_TRADE; *((Uint16*)(str+1))=1; Whenever the server recieves a REJECT_TRADE it will send the following to the clients: str[0]=GET_TRADE_REJECT; *((Uint16*)(str+1))=2; *((Uint8*)(str+3))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST;//Whether it's you or your trade partner that has rejected. Once rejecting your trade partner will also automatically reject the trade in order to reduce scamming. When the trade has ended you'll recieve: str[0]=GET_TRADE_EXIT; *((Uint16*)(str+1))=1; Hope this will help you. Share this post Link to post Share on other sites
Wytter Report post Posted August 18, 2005 Did anyone try to implement this yet? And did you succeed? If you need more info, please ask - I think I added all of it, but you never know . Share this post Link to post Share on other sites
Grum Report post Posted August 23, 2005 Ugh... *blows the dust off Nera's code Guess I'd better get to it... Share this post Link to post Share on other sites
the_antiroot Report post Posted August 23, 2005 Ugh...*blows the dust off Nera's code Guess I'd better get to it... 190249[/snapback] My Hero! I had just realised Nera ws gong to need updated, and your coding style is conceptually alien to me. (Im mean how to you make loops interesting if i isnt a global variable as well ;-) ) Share this post Link to post Share on other sites
thunderous Report post Posted September 1, 2005 I've tried to implement the new trade system on our bot. The trading works, but the bot dont get the stuff from trading My testplayer trade for example 5 lilacs for 5gc. He get the coins, but the bot not the 5 lilacs, and also the player have no longer the 5 lilacs. Where are the lilacs gone ? I make a little break now, maybe i find the solution some days later greetings thunderous Share this post Link to post Share on other sites
ttlanhil Report post Posted September 1, 2005 check that the bot isn't overloaded (yes, this is a NASTY bug. overloaded trades still go ahead and discard half the trade last I checked) Share this post Link to post Share on other sites
crusadingknight Report post Posted September 1, 2005 Looks like I have to haul out the storebot code soon... erk Share this post Link to post Share on other sites
Placid Report post Posted September 1, 2005 Looks like I have to haul out the storebot code soon... erk 192517[/snapback] Do what I do. Half implement a trade function in your bot, so that everytime you get a trade request, you get a proken pipe. Now THATS programming xD Share this post Link to post Share on other sites
Grum Report post Posted September 1, 2005 check that the bot isn't overloaded (yes, this is a NASTY bug. overloaded trades still go ahead and discard half the trade last I checked) 192514[/snapback] When was the last time you checked? I thought I fixed that. Share this post Link to post Share on other sites
thunderous Report post Posted September 1, 2005 nah it wasnt overloaded, i don't know why this happens maybe i make a mistake in code, but the loss of stuff is strange Share this post Link to post Share on other sites
ttlanhil Report post Posted September 1, 2005 eh, ignore my last post then. must be something else Share this post Link to post Share on other sites
Wicca Report post Posted September 8, 2005 When the trade has ended you'll recieve: str[0]=GET_TRADE_EXIT; *((Uint16*)(str+1))=1; Hope this will help you. Thank you for the details.. very much Share this post Link to post Share on other sites
WizzKidd Report post Posted September 9, 2005 I saw the question asking if anyone has succeeded with the implementation.. Charn is up and running!! ready for the update Share this post Link to post Share on other sites
Wicca Report post Posted September 12, 2005 I'm seeing an extra byte at the end of this from the server which throws off str+10 Is it just the beer, or is this still a work in progress? My bot code wants to know. Thanks str[0]=GET_TRADE_OBJECT; *((Uint16*)(str+1))=9; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=pos; *((Uint8*)(str+10))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST; Share this post Link to post Share on other sites
Learner Report post Posted September 12, 2005 I'm seeing an extra byte at the end of this from the server which throws off str+10 Is it just the beer, or is this still a work in progress? My bot code wants to know. Thanks 195580[/snapback] The trading with the new clients works. So now you just need to implement what was described here and also shown in the new client code in CVS. Share this post Link to post Share on other sites
Wytter Report post Posted September 12, 2005 Damn, you're right - it's: str[0]=GET_TRADE_OBJECT; *((Uint16*)(str+1))=10; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=type; *((Uint8*)(str+10))=pos; *((Uint8*)(str+11))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST; Where the type is determining whether it should be in the storage or in the inventory. Share this post Link to post Share on other sites
Wicca Report post Posted September 15, 2005 Damn, you're right - it's: str[0]=GET_TRADE_OBJECT; *((Uint16*)(str+1))=10; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=type; *((Uint8*)(str+10))=pos; *((Uint8*)(str+11))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST; Where the type is determining whether it should be in the storage or in the inventory. 195705[/snapback] It's okay, I'm mostly looking for concept changes, and your post helped a lot. Thanks much. last time it was Tcl, this time I think I'll try Lisp! I like a challenge Share this post Link to post Share on other sites
WizzKidd Report post Posted September 27, 2005 So, after both parties have accepted two times and the trade is to be accepted.. what happens when the person recieving the goods can not carry them all? Is there a message that says trade failed? Share this post Link to post Share on other sites
Placid Report post Posted October 4, 2005 So, after both parties have accepted two times and the trade is to be accepted.. what happens when the person recieving the goods can not carry them all? Is there a message that says trade failed? 202030[/snapback] Yeah, RAW_TEXT I would assume, saying: "Trade session failed. <Playername> could not carry all the items" Share this post Link to post Share on other sites
Artem Report post Posted October 13, 2005 str[0]=GET_TRADE_OBJECT; *((Uint16*)(str+1))=10; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=type; *((Uint8*)(str+10))=pos; *((Uint8*)(str+11))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST; What is *((Uint8*)(str+9))=type; identifing? Is it the same as the item flags? Share this post Link to post Share on other sites
Wytter Report post Posted October 13, 2005 Damn, you're right - it's: str[0]=GET_TRADE_OBJECT; *((Uint16*)(str+1))=10; *((Uint16*)(str+3))=image_id; *((Uint32*)(str+5))=quantity; *((Uint8*)(str+9))=type; *((Uint8*)(str+10))=pos; *((Uint8*)(str+11))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST; Where the type is determining whether it should be in the storage or in the inventory. 195705[/snapback] Share this post Link to post Share on other sites
Artem Report post Posted October 13, 2005 thx, I've overseen it somehow Share this post Link to post Share on other sites
Lege The Dragonei Report post Posted October 13, 2005 Yes this is very Helpful Share this post Link to post Share on other sites
WizzKidd Report post Posted October 14, 2005 If you want to see the item string for that given object, do the following: #define YOUR_TRADE_LIST 0 #define OTHERS_TRADE_LIST 1 str[0]=LOOK_AT_TRADE_ITEM; *((Uint16*)(str+1))=length; *((Uint8*)(str+3))=pos; *((Uint8*)(str+4))=YOUR_TRADE_LIST || OTHERS_TRADE_LIST;//Whether you want to see the item from your or the others trade list. You never mentioned what the reply to this looks like. Also, Since the image ID's are not unique, how are we to know what item is really in a given slot? do a look at trade item in that slot.. ok, then we get the reply but the reply does not say what slot the reply is for. So, if I send a look at every slot in inventory to determine what each item is (by description) then when the replies come back, there is no way for me to map them to the correct item slot. Since TCPIP messaging is async, there is not even a guarentee that my messages will get to the server in order. So I am having major difficulty telling the difference between different books which use the same image and items like LE and ELE. If there is currently no solution to this, can I propose implementing a UNIQUE id for each item? then also having an imageID. And add the unique ID to the all packets dealing with inventory and looking at an item? OR, add the slot to the reply for LOOK_AT_TRADE_ITEM (you would also have to add who's list, storage, inventory, bag, etc). Any help would be greatly appreciated... Share this post Link to post Share on other sites
Learner Report post Posted October 14, 2005 You never mentioned what the reply to this looks like. Also, Since the image ID's are not unique, how are we to know what item is really in a given slot? do a look at trade item in that slot.. ok, then we get the reply but the reply does not say what slot the reply is for. So, if I send a look at every slot in inventory to determine what each item is (by description) then when the replies come back, there is no way for me to map them to the correct item slot. Since TCPIP messaging is async, there is not even a guarentee that my messages will get to the server in order. So I am having major difficulty telling the difference between different books which use the same image and items like LE and ELE. If there is currently no solution to this, can I propose implementing a UNIQUE id for each item? then also having an imageID. And add the unique ID to the all packets dealing with inventory and looking at an item? OR, add the slot to the reply for LOOK_AT_TRADE_ITEM (you would also have to add who's list, storage, inventory, bag, etc). Any help would be greatly appreciated... 209402[/snapback] TCP/IP is guaranteed to that the packets will be received in the same order as sent. UDP is the protocol where the packets might be processed in a different order. Share this post Link to post Share on other sites