Go Back   EQEmulator Home > EQEmulator Forums > Support > Support::Windows Servers

Support::Windows Servers Support forum for Windows EQEMu users.

Reply
 
Thread Tools Display Modes
  #1  
Old 01-22-2012, 01:44 AM
blackdragonsdg
Dragon
 
Join Date: Dec 2008
Location: Tennessee
Posts: 656
Default Item stacksize

I am encountering weird issues with item stack sizes over 244. I have several items on my server set between 500-1000 and it will work flawlessly one minute then the next it is reverting the stack size back to 244 or even 232. Some times I can log out and back in and the previously reverted stack will display correctly again. This behavior seems to be fairly random. At first I thought I had corrupted something in my database or even the emulator but after a complete wipe of my database and a new emulator compile the stacksize issue continues to happen at random. I only recently started using stack sizes over 100 which is why I never saw this until now. I am using emulator rev2097 and peqdb rev2092 with the SoD client.

Has anyone else seen anything like this before? If so how do I fix it?
Reply With Quote
  #2  
Old 01-22-2012, 02:01 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,742
Default

Stack size was fairly recently updated to allow for stacks of more than 255. It's possible something was missed, so if you had a stack over that size and whatever wasn't updated happens you'd end up with the old stack size mod 256. So, if you had 500 you'd end up with 244, and if you had 1000 you'd end up with 232.

If you limited yourself to stacks of 255 or less you wouldn't have any issues. If you're looking to track it down you'd need to find everywhere that the stacksize is assigned to a variable or passed into a function and make sure none of those places is using an unsigned char instead of a uint16.
Reply With Quote
  #3  
Old 01-22-2012, 04:42 AM
blackdragonsdg
Dragon
 
Join Date: Dec 2008
Location: Tennessee
Posts: 656
Default

Since the stacksize change was made in rev2004 I used the file list from that as a reference on where to look for any unsigned char being used with stacksize and I am sorry to say I did not see any.

Guess I will have to lower my stack sizes down below 255 till I can track down the culprit in the code or where ever it is or until someone beats me to it.
Reply With Quote
  #4  
Old 01-22-2012, 05:45 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,742
Default

If I had to guess I'd say it might be one of these:

Code:
Inventory
	bool DeleteItem(sint16 slot_id, uint8 quantity=0);
	sint16 HasItem(uint32 item_id, uint8 quantity=0, uint8 where=0xFF);
	sint16 HasItemByUse(uint8 use, uint8 quantity=0, uint8 where=0xFF);
	sint16 _HasItem(map<sint16, ItemInst*>& bucket, uint32 item_id, uint8 quantity);
	sint16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity);
	sint16 _HasItemByUse(map<sint16, ItemInst*>& bucket, uint8 use, uint8 quantity);
	sint16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity);
But I'd say the most likely candidate is this:

Code:
	void Client::DeleteItemInInventory(sint16 slot_id, sint8 quantity, bool client_update, bool update_db)
Reply With Quote
  #5  
Old 01-22-2012, 10:54 PM
blackdragonsdg
Dragon
 
Join Date: Dec 2008
Location: Tennessee
Posts: 656
Default

So I took your idea on the potentital problem and ran with. After more than a few changes and function overload errors and fixes I am at a loss again.

The following did not fix the problem nor did the changes cause any other issues that I am aware of atm.

Code:
-------------------------------------------------------------------
zone/inventory.cpp
-------------------------------------------------------------------

void Client::DeleteItemInInventory(sint16 slot_id, sint8 quantity, bool client_update, bool update_db)

changed to

void Client::DeleteItemInInventory(sint16 slot_id, sint16 quantity, bool client_update, bool update_db)


uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {

changed to

uint32 Client::NukeItem(uint32 itemnum, uint16 where_to_check) {

-------------------------------------------------------------------
zone/client.h
-------------------------------------------------------------------

void	DeleteItemInInventory(sint16 slot_id, sint8 quantity = 0, bool client_update = false, bool update_db = true);

changed to

void	DeleteItemInInventory(sint16 slot_id, sint16 quantity = 0, bool client_update = false, bool update_db = true);


uint32	NukeItem(uint32 itemnum, uint8 where_to_check = 

changed to

uint32	NukeItem(uint32 itemnum, uint16 where_to_check = 

-------------------------------------------------------------------
common/item.cpp
-------------------------------------------------------------------

// Remove item from inventory (with memory delete)
bool Inventory::DeleteItem(sint16 slot_id, uint8 quantity)

changed to 

// Remove item from inventory (with memory delete)
bool Inventory::DeleteItem(sint16 slot_id, uint16 quantity)


sint16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where)

changed to

sint16 Inventory::HasItem(uint32 item_id, uint16 quantity, uint16 where)


sint16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where)

changed to

sint16 Inventory::HasItemByUse(uint8 use, uint16 quantity, uint16 where)


sint16 Inventory::_HasItem(map<sint16, ItemInst*>& bucket, uint32 item_id, uint8 quantity)

changed to

sint16 Inventory::_HasItem(map<sint16, ItemInst*>& bucket, uint32 item_id, uint16 quantity)


sint16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)

changed to

sint16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint16 quantity)


sint16 Inventory::_HasItemByUse(map<sint16, ItemInst*>& bucket, uint8 use, uint8 quantity)

changed to

sint16 Inventory::_HasItemByUse(map<sint16, ItemInst*>& bucket, uint8 use, uint16 quantity)


sint16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)

changed to

sint16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint16 quantity)









-------------------------------------------------------------------
common/item.h
-------------------------------------------------------------------

	// Remove item from inventory
	bool DeleteItem(sint16 slot_id, uint8 quantity=0);

changed to 

	// Remove item from inventory
	bool DeleteItem(sint16 slot_id, uint16 quantity=0);


	// Check whether item exists in inventory
	// where argument specifies OR'd list of invWhere constants to look
	sint16 HasItem(uint32 item_id, uint8 quantity=0, uint8 where=0xFF);

changed to

	// Check whether item exists in inventory
	// where argument specifies OR'd list of invWhere constants to look
	sint16 HasItem(uint32 item_id, uint16 quantity=0, uint16 where=0xFFFF);


	// Check whether item exists in inventory
	// where argument specifies OR'd list of invWhere constants to look
	sint16 HasItemByUse(uint8 use, uint16 quantity=0, uint8 where=0xFF);

changed to

	// Check whether item exists in inventory
	// where argument specifies OR'd list of invWhere constants to look
	sint16 HasItemByUse(uint8 use, uint16 quantity=0, uint16 where=0xFFFF);

	// Checks an inventory bucket for a particular item
	sint16 _HasItem(map<sint16, ItemInst*>& bucket, uint32 item_id, uint8 quantity);
	sint16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity);
	sint16 _HasItemByUse(map<sint16, ItemInst*>& bucket, uint8 use, uint8 quantity);
	sint16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity);

changed to

	// Checks an inventory bucket for a particular item
	sint16 _HasItem(map<sint16, ItemInst*>& bucket, uint32 item_id, uint16 quantity);
	sint16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint16 quantity);
	sint16 _HasItemByUse(map<sint16, ItemInst*>& bucket, uint8 use, uint16 quantity);
	sint16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint16 quantity);
Reply With Quote
  #6  
Old 01-23-2012, 12:10 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,742
Default

Some of the things you changed wouldn't have anything to do with this issue, specifically the "where to look" params. Presumably it won't hurt anything to have changed them.

Changing the quantities on those functions is a start, but you need to look at where they are called as well. As an example,
Code:
bool Client::DecreaseByID(int32 type, int8 amt)
has the potential to cause issues, although it is only called from Perl, and I didn't dig through any quest scripts to see if it is even used.

If you are able to narrow down specifically what you do to cause the problem it would probably help to narrow it down where in the code it might be occurring.
Reply With Quote
  #7  
Old 01-23-2012, 01:37 AM
blackdragonsdg
Dragon
 
Join Date: Dec 2008
Location: Tennessee
Posts: 656
Default

I am not exactly an expert with C++ so some of the changes I made were purely a guess. Obviously I may have guessed wrong on somethings but it didn't hurt to try.
Today I focused on this error instead of trying to actually play EQ which was the case at the time I made my initial post on this issue. It didn't take long to find a trigger which allowed me to cause the error at will. The trigger is very simple...put an arrow on a merchant...set its stacksize to 1000 then purchase 1000 of them. When the purchased item is placed into the characters inventory automatically the stacksize is reduced to 232.
Reply With Quote
  #8  
Old 01-23-2012, 02:08 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,742
Default

Try changing this:

Code:
struct Merchant_Sell_Struct {
/*000*/    int32 npcid;			// Merchant NPC's entity id
/*004*/    int32 playerid;		// Player's entity id
/*008*/    int32 itemslot;
           int32 unknown12;
/*016*/    int8  quantity;		// Already sold
/*017*/    int8  Unknown016[3];
/*020*/    int32 price;
};
To this:

Code:
struct Merchant_Sell_Struct {
/*000*/    int32 npcid;			// Merchant NPC's entity id
/*004*/    int32 playerid;		// Player's entity id
/*008*/    int32 itemslot;
           int32 unknown12;
/*016*/    int32 quantity;		// Already sold
/*020*/    int32 price;
};
That might actually break something, but cross your fingers and prepare to change it back.
Reply With Quote
  #9  
Old 01-23-2012, 02:14 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,742
Default

Looks like you'll also need to change the Merchant_Sell_Struct for each patch. Same basic idea though, remove the int8 x[3] placeholder and change the quantity to an int32.
Reply With Quote
  #10  
Old 01-23-2012, 02:34 AM
blackdragonsdg
Dragon
 
Join Date: Dec 2008
Location: Tennessee
Posts: 656
Default

Quote:
Originally Posted by lerxst2112 View Post
Try changing this:

Code:
struct Merchant_Sell_Struct {
/*000*/    int32 npcid;			// Merchant NPC's entity id
/*004*/    int32 playerid;		// Player's entity id
/*008*/    int32 itemslot;
           int32 unknown12;
/*016*/    int8  quantity;		// Already sold
/*017*/    int8  Unknown016[3];
/*020*/    int32 price;
};
To this:

Code:
struct Merchant_Sell_Struct {
/*000*/    int32 npcid;			// Merchant NPC's entity id
/*004*/    int32 playerid;		// Player's entity id
/*008*/    int32 itemslot;
           int32 unknown12;
/*016*/    int32 quantity;		// Already sold
/*020*/    int32 price;
};
That might actually break something, but cross your fingers and prepare to change it back.
This did not fix the problem but at the same time it didn't appear to break anything either.
Maybe this will help narrow it down further and I just tried this.....I can summon stacks of 1000 random arrows and they can be placed into my inventory with no problem. I can manipulate those stacks without any reverting issues. I tried this with three different item id's of the same arrow name and type.
Reply With Quote
  #11  
Old 01-23-2012, 03:04 AM
blackdragonsdg
Dragon
 
Join Date: Dec 2008
Location: Tennessee
Posts: 656
Default

Quote:
Originally Posted by lerxst2112 View Post
Looks like you'll also need to change the Merchant_Sell_Struct for each patch. Same basic idea though, remove the int8 x[3] placeholder and change the quantity to an int32.
Now doing this broke something somewhere. I purchased the 1000 arrows from the same merchant like I had been doing this whole time and then the problem occured. I could not access my inventory or use the merchant again. I tried clicking the blightfire stone just to zone and nothing happened so I used the zone command just to zone. After I zoned I was able to use my inventory again and well the arrows that I had purchased were not there. I checked my log files hoping for hint but found nothing useful.
Reply With Quote
  #12  
Old 01-23-2012, 03:23 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,742
Default

Yeah, when you start messing around with the packet structs in the patches it gets a little problematic. If you break one of those then you're most likely stuck until you zone.

The most important thing with those is to never change the size, so if you change the int8 to an int32 you need to remove the array of unknown right after it so it stays the same size. It's also possible that whichever client you are using doesn't read those bits, or has a problem if they are changed.

Unless someone has a packet capture of buying 1000 of something on live when that particular client was being used to match up with it's all just guessing.
Reply With Quote
  #13  
Old 01-23-2012, 05:36 AM
blackdragonsdg
Dragon
 
Join Date: Dec 2008
Location: Tennessee
Posts: 656
Default

After my initial failure with the changing of the structs I decided to give it one more shot. So I dumped all the changes I had made up to this point and started over. This time I only used the struct changes and it worked so either something was interferring or I made a typo in one of those last changes. Gonna use this version of the compile for a while to see if the good fortune holds up.

Thanks for all the help lerxst2112.
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 02:23 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3