Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Bug Reports

Development::Bug Reports Post detailed bug reports and what you would like to see next in the emu here.

Reply
 
Thread Tools Display Modes
  #31  
Old 07-19-2012, 01:22 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

I'm having an idiot moment...

Can someone point me to where the client packet stream is processed and a 'trade' or a 'swap' call is directed to Client::SwapItem?

VC 'find' is not cooperating... (('swapitem' == ':swapitem') != '.swapitem' != '>swapitem')
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #32  
Old 07-19-2012, 01:32 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,743
Default

Client::Handle_OP_MoveItem

I just searched for "SwapItem" and looked at all 5 places where a function of that name is called. I have no idea what the search you posted is supposed to do.
Reply With Quote
  #33  
Old 07-19-2012, 02:33 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Lol! Sorry about that! I'm on my latop..very old laptop..that's boasting a 2.4 GHz, non-HT cpu, and a whopping 1-Gig of ram...

For some reason my 'searches' are not finding things they way it should when I search for specific criteria.

That thing at the end is what my search results say is equal and not equal..not my actual criteria line.

searching for 'swapitem' will find ':swapitem', but does not return '>swapitem' or '.swapitem' hits for some reason.

Even with the above four criteria, 'Client::Handle_OP_MoveItem' never came up..even when searching 'Entire Solution...'

Thanks for the info!

EDIT: Yes, I searched up and down, but something just isn't right about my searching or my laptop..or both...
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #34  
Old 07-20-2012, 06:36 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

I finally managed to bug an 'empty' corpse the other night so that it would not go away.

The strings of the corpses in the backup appeared different than the one that was still active. I think this CSD issue
is creeping into this area too.

Could someone with knowledge of corspe inventory strings and access to an active database check to see if there are
corpses that players can't loot anything else off of, but that the corspe will not decay after looting?

I'm looking for it having items stored on it that have zero charges, resulting in the client not seeing them, but the server
saying they are there..hence the reason a corpse will not decay properly when bugged...


Thanks!
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #35  
Old 07-20-2012, 03:14 PM
sorvani
Dragon
 
Join Date: May 2010
Posts: 966
Default

You can duplicate this by having an item on the cursor when you die.

Make a rogue.
fill up the inventory.
use pickpocket to get an item on the cursor.
use pickpocket again and you should get the message that it won't work with an item on your cursor.
die.
get rez.
loot corpse.
corpse will not rot.

this of course also is easy to do with foragers, but it should be repeatable with any character and a full inventory and an item on the cursor. I am semi confident it does not happen if the inventory is not 100% full.

as for look at corpse items.. those are in a blob, so need to parse it out of there. I vaguely recall seeing a script to check blobs once but do not recall if it was on corpses or players. i'll poke at it later if no one gets back to you sooner.
Reply With Quote
  #36  
Old 07-27-2012, 06:43 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

(Sorvani, that almost sounds like when a player dies with an item in the cursor queue, past [0], the server knows
that it's there, but the loot routine is only grabbing [0] and sending it to the client and not sending queue slots...
I'll add it to the list... It might be fixable by doing a cursor iteration when sending the loot window packets, if that's
what is happening.)


Anyways, I've been distracted by r/l and am starting to get back into this.

I'm posting an ALPHA patch here for some minor issues. I didn't want to start a new thread in another forum with a portion
of this not tested. (#summonitem was modified to report lore conflict failures with augments properly (imo) and I haven't
looked up any augment item id's just yet to test it out.) The rest of the code is tested and should work as intended.


[CSD Patch 1]
Code:
Index: command.cpp
===================================================================
--- command.cpp	(revision 2171)
+++ command.cpp	(working copy)
@@ -456,7 +456,8 @@
         command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", 0, command_sensetrap) ||
         command_add("picklock", "Analog for ldon pick lock for the newer clients since we still don't have it working.", 0, command_picklock) ||
 		command_add("mysql", "Mysql CLI, see 'help' for options.", 250, command_mysql) ||
-		command_add("xtargets", "Show your targets Extended Targets and optionally set how many xtargets they can have.", 250, command_xtargets) 
+		command_add("xtargets", "Show your targets Extended Targets and optionally set how many xtargets they can have.", 250, command_xtargets) ||
+		command_add("zopp", "Troubleshooting command - Sends a fake item packet to you. No server reference is created.", 250, command_zopp)
 		)
 	{
 		command_deinit();
@@ -3013,6 +3014,7 @@
 		c->Message(0, "Usage: (targted) #nukeitem itemnum - removes the item from the player's inventory");
 }
 
+// 'CSD 1' - Made modifications to show charge count of items as well - other changes are noted where they occur
 void command_peekinv(Client *c, const Seperator *sep)
 {
 	// Displays what the server thinks the user has in inventory
@@ -3035,15 +3037,17 @@
 			item = (inst) ? inst->GetItem() : NULL;
 			if (c->GetClientVersion() >= EQClientSoF)
 			{
-				c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 			else
 			{
-				c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 		}
 	}
@@ -3055,15 +3059,17 @@
 			item = (inst) ? inst->GetItem() : NULL;
 			if (c->GetClientVersion() >= EQClientSoF)
 			{
-				c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 			else
 			{
-				c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 			
 			if (inst && inst->IsType(ItemClassContainer)) {
@@ -3072,17 +3078,19 @@
 					item = (instbag) ? instbag->GetItem() : NULL;
 					if (c->GetClientVersion() >= EQClientSoF)
 					{
-						c->Message((item==0), "   InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:instbag->GetCharges()));
 					}
 					else
 					{
-						c->Message((item==0), "   InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:instbag->GetCharges()));
 					}
 				}
 			}
@@ -3091,50 +3099,73 @@
 		{
 			const ItemInst* inst = client->GetInv().GetItem(9999);
 			item = (inst) ? inst->GetItem() : NULL;
-			c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", 9999,
+			c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", 9999,
 			((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-			((item==0)?"null":item->Name), 0x12);
+			((item==0)?"null":item->Name), 0x12,
+			((item==0)?0:inst->GetCharges()));
 		}
 	}
+
+	// 'CSD 1' - Changed to show 'empty' cursors and not to show bag slots on 'queued' cursor slots (cursor bag slots 331 to 340 are not queued...)
+	// - was pointless to show bags on anything after slot 30[0], because they don't exist and only repeat the 30[0] bag items.
 	if (bAll || (strcasecmp(sep->arg[1], "cursor")==0)) {
 		// Personal inventory items
 		bFound = true;
 		iter_queue it;
 		int i=0;
-		for(it=client->GetInv().cursor_begin();it!=client->GetInv().cursor_end();it++,i++) {
-			const ItemInst* inst = *it;
-			item = (inst) ? inst->GetItem() : NULL;
+
+		if(client->GetInv().CursorEmpty()) { // 'CSD 1' - Display 'front' cursor slot even if 'empty' (item(30[0]) == null)
 			if (c->GetClientVersion() >= EQClientSoF)
 			{
-				c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", SLOT_CURSOR,i,
-					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+				c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+					0, 0x12, 0, "null", 0x12, 0);
 			}
 			else
 			{
-				c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", SLOT_CURSOR,i,
-					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+				c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+					0, 0x12, 0, "null", 0x12, 0);
 			}
+		}
+		else {
+			for(it=client->GetInv().cursor_begin();it!=client->GetInv().cursor_end();it++,i++) {
+				const ItemInst* inst = *it;
+				item = (inst) ? inst->GetItem() : NULL; // 'CSD 1' - (item == null) will not include an 'empty' cursor (30[0])
+				if (c->GetClientVersion() >= EQClientSoF)
+				{
+					c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+						((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+						((item==0)?"null":item->Name), 0x12,
+						((item==0)?0:inst->GetCharges()));
+				}
+				else
+				{
+					c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+						((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+						((item==0)?"null":item->Name), 0x12,
+						((item==0)?0:inst->GetCharges()));
+				}
 			
-			if (inst && inst->IsType(ItemClassContainer)) {
-				for (uint8 j=0; j<10; j++) {
-					const ItemInst* instbag = client->GetInv().GetItem(SLOT_CURSOR, j);
-					item = (instbag) ? instbag->GetItem() : NULL;
-					if (c->GetClientVersion() >= EQClientSoF)
-					{
-						c->Message((item==0), "   CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
-							Inventory::CalcSlotId(SLOT_CURSOR, j),
-							SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+				if (inst && inst->IsType(ItemClassContainer) && i==0) { // 'CSD 1' - only display contents of slot 30[0] container..higher ones don't exist
+					for (uint8 j=0; j<10; j++) {
+						const ItemInst* instbag = client->GetInv().GetItem(SLOT_CURSOR, j);
+						item = (instbag) ? instbag->GetItem() : NULL;
+						if (c->GetClientVersion() >= EQClientSoF)
+						{
+							c->Message((item==0), "   CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
+								Inventory::CalcSlotId(SLOT_CURSOR, j),
+								SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+								((item==0)?"null":item->Name), 0x12,
+								((item==0)?0:instbag->GetCharges()));
+						}
+						else
+						{
+							c->Message((item==0), "   CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
+								Inventory::CalcSlotId(SLOT_CURSOR, j),
+								SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+								((item==0)?"null":item->Name), 0x12,
+								((item==0)?0:instbag->GetCharges()));
+						}
 					}
-					else
-					{
-						c->Message((item==0), "   CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
-							Inventory::CalcSlotId(SLOT_CURSOR, j),
-							SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
-					}
 				}
 			}
 		}
@@ -3148,15 +3179,17 @@
 			item = (inst) ? inst->GetItem() : NULL;
 			if (c->GetClientVersion() >= EQClientSoF)
 			{
-				c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
 				((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-				((item==0)?"null":item->Name), 0x12);
+				((item==0)?"null":item->Name), 0x12,
+				((item==0)?0:inst->GetCharges()));
 			}
 			else
 			{
-			c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+			c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
 				((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-				((item==0)?"null":item->Name), 0x12);
+				((item==0)?"null":item->Name), 0x12,
+				((item==0)?0:inst->GetCharges()));
 			}
 		}
 	}
@@ -3170,15 +3203,17 @@
 			item = (inst) ? inst->GetItem() : NULL;
 			if (c->GetClientVersion() >= EQClientSoF)
 			{
-				c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
 				((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-				((item==0)?"null":item->Name), 0x12);
+				((item==0)?"null":item->Name), 0x12,
+				((item==0)?0:inst->GetCharges()));
 			}
 			else
 			{
-			c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+			c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
 				((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-				((item==0)?"null":item->Name), 0x12);
+				((item==0)?"null":item->Name), 0x12,
+				((item==0)?0:inst->GetCharges()));
 			}
 				
 			if (inst && inst->IsType(ItemClassContainer)) {
@@ -3187,17 +3222,19 @@
 					item = (instbag) ? instbag->GetItem() : NULL;
 					if (c->GetClientVersion() >= EQClientSoF)
 					{
-						c->Message((item==0), "   BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:inst->GetCharges()));
 					}
 					else
 					{
-						c->Message((item==0), "   BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:inst->GetCharges()));
 					}
 				}
 			}
@@ -3207,15 +3244,17 @@
 			item = (inst) ? inst->GetItem() : NULL;
 			if (c->GetClientVersion() >= EQClientSoF)
 			{
-				c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 			else
 			{
-				c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 			
 			if (inst && inst->IsType(ItemClassContainer)) {
@@ -3224,17 +3263,19 @@
 					item = (instbag) ? instbag->GetItem() : NULL;
 					if (c->GetClientVersion() >= EQClientSoF)
 					{
-						c->Message((item==0), "   ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:inst->GetCharges()));
 					}
 					else
 					{
-						c->Message((item==0), "   ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:inst->GetCharges()));
 					}
 				}
 			}
@@ -3248,15 +3289,17 @@
 			item = (inst) ? inst->GetItem() : NULL;
 			if (c->GetClientVersion() >= EQClientSoF)
 			{
-				c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 			else
 			{
-				c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+				c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
 					((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-					((item==0)?"null":item->Name), 0x12);
+					((item==0)?"null":item->Name), 0x12,
+					((item==0)?0:inst->GetCharges()));
 			}
 			
 			if (inst && inst->IsType(ItemClassContainer)) {
@@ -3265,17 +3308,19 @@
 					item = (instbag) ? instbag->GetItem() : NULL;
 					if (c->GetClientVersion() >= EQClientSoF)
 					{
-						c->Message((item==0), "   TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:inst->GetCharges()));
 					}
 					else
 					{
-						c->Message((item==0), "   TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+						c->Message((item==0), "   TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
 							Inventory::CalcSlotId(i, j),
 							i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
-							((item==0)?"null":item->Name), 0x12);
+							((item==0)?"null":item->Name), 0x12,
+							((item==0)?0:inst->GetCharges()));
 					}
 				
 				}
@@ -3286,7 +3331,7 @@
 	if (!bFound)
 	{
 		c->Message(0, "Usage: #peekinv [worn|cursor|inv|bank|trade|trib|all]");
-		c->Message(0, "  Displays a portion of the targetted user's inventory");
+		c->Message(0, "  Displays a portion of the targeted user's inventory");
 		c->Message(0, "  Caution: 'all' is a lot of information!");
 	}
 }
@@ -11529,3 +11581,40 @@
 	else
 		t->ShowXTargets(c);
 }
+
+// 'CSD 3' - Troubleshooting command used to send a fake item to the client..server item not created.
+// - Owner only command..non-targetable to eliminate malicious or mischievious activities.
+void command_zopp(Client *c, const Seperator *sep)
+{
+	if (sep->argnum < 2 || sep->argnum > 3)
+		c->Message(0, "Usage: #zopp [slot id] [item id] [*charges]");
+	else if (!sep->IsNumber(1) || !sep->IsNumber(2) || (sep->argnum == 3 && !sep->IsNumber(3)))
+		c->Message(0, "Usage: #zopp [slot id] [item id] [*charges]");
+	else {
+		sint16 slotid = atoi(sep->arg[1]);
+		int32 itemid = atoi(sep->arg[2]);
+		sint16 charges = sep->argnum == 3 ? atoi(sep->arg[3]) : 1; // defaults to 1 charge if not specified
+
+		const Item_Struct* FakeItem = database.GetItem(itemid);
+		
+		if (!FakeItem) {
+			c->Message(13, "Error: Item [%u] is not a valid item id.", itemid);
+			return;
+		}
+				
+		if (database.GetItemStatus(itemid) > c->Admin()) {
+			c->Message(13, "Error: Insufficient status to use this command.");
+			return;
+		}
+
+		if (charges < 0 || charges > FakeItem->StackSize) {
+			c->Message(13, "Warning: The specified charge count does not meet expected criteria!");
+			c->Message(0, "Processing request..results may be unpredictable or cause instability.");
+		}
+
+		ItemInst* FakeItemInst = database.CreateItem(FakeItem, charges);
+		c->SendItemPacket(slotid, FakeItemInst, ItemPacketTrade);
+		c->Message(0, "Sending zephyr op packet to client - %s (%u) with %i %s to slot %i.", FakeItem->Name, itemid, charges, abs(charges==1)?"charge":"charges", slotid);
+		safe_delete(FakeItemInst);
+		}
+}
\ No newline at end of file
Index: command.h
===================================================================
--- command.h	(revision 2171)
+++ command.h	(working copy)
@@ -320,6 +320,7 @@
 void command_qtest(Client *c, const Seperator *sep);
 void command_mysql(Client *c, const Seperator *sep);
 void command_xtargets(Client *c, const Seperator *sep);
+void command_zopp(Client *c, const Seperator *sep);
 
 #ifdef EMBPERL
 void command_embperl_plugin(Client *c, const Seperator *sep);
Index: inventory.cpp
===================================================================
--- inventory.cpp	(revision 2171)
+++ inventory.cpp	(working copy)
@@ -222,6 +222,14 @@
 				inst->SetCharges(1);
 			if ((inst->GetCharges()>0))
 				inst->SetCharges(inst->GetCharges());
+
+			// 'CSD 7' - This reduces overcharged items to maximum stacksize
+			if ((inst->GetCharges()>inst->GetItem()->StackSize)) {
+				inst->SetCharges(inst->GetItem()->StackSize);
+				Message(0, "Your summoned item is charged beyond maximum allowable - adjusting to %i charges!", inst->GetCharges());
+			}
+
+			// 'CSD 7' - Corrected the augment references to reflect augment name/id instead of base item name/id
 			if (aug1) {
 				const Item_Struct* augitem1 = database.GetItem(aug1);
 				if (augitem1) {
@@ -229,7 +237,7 @@
 						inst->PutAugment(&database, 0, aug1);
 					}
 					else {
-						Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+						Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem1->Name, aug1);
 					}
 				}
 			}
@@ -240,7 +248,7 @@
 						inst->PutAugment(&database, 1, aug2);
 					}
 					else {
-						Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+						Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem2->Name, aug2);
 					}
 				}
 			}
@@ -251,7 +259,7 @@
 						inst->PutAugment(&database, 2, aug3);
 					}
 					else {
-						Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+						Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem3->Name, aug3);
 					}
 				}
 			}
@@ -262,7 +270,7 @@
 						inst->PutAugment(&database, 3, aug4);
 					}
 					else {
-						Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+						Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem4->Name, aug4);
 					}
 				}
 			}
@@ -273,7 +281,7 @@
 						inst->PutAugment(&database, 4, aug5);
 					}
 					else {
-						Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+						Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem5->Name, aug5);
 					}
 				}
 			}

If this isn't committed, that's fine. I'll include it in a later patch.


I think I have a pretty good idea of what's happening now, but if anyone still has any suggestions... (constructive... I know how to do THAT already!)
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #37  
Old 07-27-2012, 12:36 PM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Here's another 'in-work' mod...

(Remember, I'm trying to find ALL occurences of CSDs/bugged inventories.)


Code:
Index: client_packet.cpp
===================================================================
--- client_packet.cpp	(revision 2173)
+++ client_packet.cpp	(working copy)
@@ -3278,6 +3278,8 @@
 	return;
 }
 
+// 'CSD 11' - Added checks for illegal bagslot swaps..should help with certain cheats
+// - If a player has used a cheat that allows illegal item placement, they could beomce bugged at some point (especially lore items.)
 void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
 {
 	if(!CharacterID())
@@ -3291,6 +3293,7 @@
 	}
 
 	MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer;
+
 	if(spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id))
 	{
 		if(mi->from_slot != mi->to_slot && (mi->from_slot < 30 || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot))
@@ -3310,6 +3313,53 @@
 			return;
 		}
 	}
+
+	// REMOVE OR REMARK OUT BEGIN FOR ALLOWING ILLEGAL BAGSLOT USE
+	bool hackflag = false;
+
+	if (mi->from_slot >=251 && mi->from_slot <=340) {
+		if (mi->from_slot > 330)
+			hackflag = true; // why are we moving from a cursor bagslot when you can't open it?
+		else {
+			sint16 invslot = Inventory::CalcSlotId(mi->from_slot);
+			const ItemInst *invslotitem = GetInv().GetItem(invslot); 
+
+			if (invslotitem->GetItem()->ItemClass==1) { // checking the parent inventory slot for container
+				if (Inventory::CalcBagIdx(mi->from_slot) > invslotitem->GetItem()->BagSlots)
+					hackflag = true; // trying to move from slots beyond container size
+			}
+			else { // trying to move from bag slots when inventory item is not a container
+				hackflag = true;
+			}
+		}
+	}
+
+	if (mi->to_slot >= 251 && mi->to_slot <=340) {
+		bool hackflag = false;
+
+		if (mi->to_slot > 330)
+			hackflag = true; // why are we moving to a cursor bagslot when you can't open it?
+		else {
+			sint16 invslot = Inventory::CalcSlotId(mi->to_slot);
+			const ItemInst *invslotitem = GetInv().GetItem(invslot);
+
+			if (invslotitem->GetItem()->ItemClass==1) { // checking the parent inventory slot for container
+				if (Inventory::CalcBagIdx(mi->from_slot) > invslotitem->GetItem()->BagSlots)
+					hackflag = true; // trying to move into slots beyond container size
+			}
+			else { // trying to move into bag slots when inventory item is not a container
+				hackflag = true;
+			}
+		}
+	}
+
+	if (hackflag) {
+		Message(13, "Hack attempt detected - Illegal use of inventory bagslots!");
+		// TODO: Decide whether to log player as hacker
+		// Kick();
+	}
+	// REMOVE OR REMARK OUT END FOR ALLOWING ILLEGAL BAGSLOT USE */
+
 	SwapItem(mi);
 	return;
 }

Tested with legal trades, but untested for illegal...

This is still in a crude state, but any input is appreciated!
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #38  
Old 07-28-2012, 12:34 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

I missed removing that second 'hackflag' definition..they were originally internal.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #39  
Old 07-28-2012, 05:20 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

I always forget to check for 'null' values on new stuff..usually that is already done...

I also changed the pointer reference when I was trying to figure this out..it currently works, but it could have the other way as well... (didn't check it.)


This is an ALPHA patch as well since it more proof of concept than a finished product.

[CSD Patch 2]
Code:
Index: client_packet.cpp
===================================================================
--- client_packet.cpp	(revision 2173)
+++ client_packet.cpp	(working copy)
@@ -3278,6 +3278,8 @@
 	return;
 }
 
+// 'CSD 11' - Added checks for illegal bagslot swaps..should help with certain cheats
+// - If a player has used a cheat that allows illegal item placement, they could beomce bugged at some point (especially lore items.)
 void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
 {
 	if(!CharacterID())
@@ -3291,6 +3293,7 @@
 	}
 
 	MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer;
+
 	if(spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id))
 	{
 		if(mi->from_slot != mi->to_slot && (mi->from_slot < 30 || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot))
@@ -3310,6 +3313,58 @@
 			return;
 		}
 	}
+
+	//* REMOVE OR REMARK OUT BEGIN FOR ALLOWING ILLEGAL BAGSLOT USE
+	bool hackflag = false;
+
+	if (mi->from_slot >=251 && mi->from_slot <=340) {
+		if (mi->from_slot > 330)
+			hackflag = true; // why are we moving from a cursor bagslot when you can't open it?
+		else {			
+			sint16 from_invslot = this->m_inv.CalcSlotId(mi->from_slot);
+			const ItemInst *from_invslotitem = GetInv().GetItem(from_invslot); 
+
+			if (!from_invslotitem) { // trying to move from bag slots when parent inventory slot is empty
+				hackflag = true;
+			}
+			else if (from_invslotitem->GetItem()->ItemClass==1) { // checking the parent inventory slot for container
+				if (this->m_inv.CalcBagIdx(mi->from_slot) > (from_invslotitem->GetItem()->BagSlots - 1))
+					hackflag = true; // trying to move from slots beyond parent container size
+			}
+			else { // trying to move from bag slots when inventory slot item is not a container
+				hackflag = true;
+			}
+		}
+	}
+
+	if (mi->to_slot >= 251 && mi->to_slot <=340) {
+		if (mi->to_slot > 330)
+			hackflag = true; // why are we moving to a cursor bagslot when you can't open it?
+		else {
+			sint16 to_invslot = this->m_inv.CalcSlotId(mi->to_slot);
+			const ItemInst *to_invslotitem = GetInv().GetItem(to_invslot);
+
+			if (!to_invslotitem) { // trying to move into bag slots when parent inventory slot is empty
+				hackflag = true;
+			}
+			else if (to_invslotitem->GetItem()->ItemClass==1) { // checking the parent inventory slot for container
+				if (this->m_inv.CalcBagIdx(mi->from_slot) > (to_invslotitem->GetItem()->BagSlots - 1))
+					hackflag = true; // trying to move into slots beyond parent container size
+			}
+			else { // trying to move into bag slots when inventory slot item is not a container
+				hackflag = true;
+			}
+		}
+	}
+
+	if (hackflag) {
+		Message(13, "Hack attempt detected: Illegal use of inventory bagslots!");
+		// TODO: Decide whether to log player as hacker
+		// Kick();
+		// return;
+	}
+	// REMOVE OR REMARK OUT END FOR ALLOWING ILLEGAL BAGSLOT USE */
+
 	SwapItem(mi);
 	return;
 }

Still looking for feedback
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #40  
Old 07-28-2012, 08:45 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

(I know you guys get tired of reading my rantings..but I have to keep it out here in case something happens to me or my notes...)

Back in this post - http://www.eqemulator.org/forums/sho...2&postcount=19 - I mentioned how the cursor is slot 30 and
the queue begins at 8001, per database observation. Slot 8000 is apparently not used for the active cursor.

It is, however, referenced several times in the code..here's one instance:


[PlayerCorpse.cpp]
Code:
Corpse::Corpse(Client* client, sint32 in_rezexp)
...
		for(i = 0; i <= 30; i++)
		{
			item = client->GetInv().GetItem(i);
			if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent))
			{
				MoveItemToCorpse(client, item, i);
                removed_list.push_back(i);
			}
		}

		// cursor queue
		iter_queue it;
		for(it=client->GetInv().cursor_begin(),i=8000; it!=client->GetInv().cursor_end(); it++,i++) {
			item = *it;
			if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent))
			{
				MoveItemToCorpse(client, item, i);
                cursor = true;
			}
		}
...
Obviously, the first loop catches the cursor slot 30. How does slot 8000 not being occupied actually affect the operation
of the second loop?

And, what would happen if both slot 30 and slot 8000 were occupied? We should lose one of them, right?


Muse it over and let me know if you think this is an issue. It's on my list, so I'll eventually find a way to test what is happening.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #41  
Old 07-28-2012, 04:53 PM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,743
Default

Quote:
Obviously, the first loop catches the cursor slot 30. How does slot 8000 not being occupied actually affect the operation
of the second loop?
They appear to be two separate unrelated loops. One moves items in slots 0-30, and the second moves items from the cursor queue to 8000-(8000 + N). I didn't look at how MoveItemToCorpse works, but I would guess since the slot numbers don't overlap it isn't an issue.

Quote:
And, what would happen if both slot 30 and slot 8000 were occupied? We should lose one of them, right?
Sounds like a good thing to test for.
Reply With Quote
  #42  
Old 07-30-2012, 01:39 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

They are seperate, but they're not... I had to include both for reference.

The first one handles the 'visible' cursor slot 30. The second handles slot 8000, which supposedly is also the visible cursor slot.
(There are several references in the code that indicate this..mostly in remark statements.)


Here's a little test, with validation checks, to induce a bugged corpse:

- Ensure no items are on your cursor

- #summonitem 13201 (Blackbox A Series)
- #summonitem 13202 (Blackbox B Series)
- #summonitem 13203 (Blackbox C Series)
- #summonitem 13204 (Blackbox D Series)

- Open your database tool software and look at this character's inventory..it should read:
-- Slot 30 - 13201
-- Slot 8001 - 13202
-- Slot 8002 - 13203
-- Slot 8003 - 13204

- Now, #kill yourself..it should crash your client.

- Refresh you database table and reinspect the values:
-- Slot 30 - 13202
-- Slot 8001 - 13203
-- Slot 8002 - 13204

- At this point, we can assume that item 13201 made it to the corpse, or that it was deleted for some reason.

- Now, revive and you should have cursor items. (Best to do all of this next to your bind point...)
-- Three items total, Blackboxes B, C & D.

- Loot your corpse..in addition to your equipment, you will find Blackbox A at the end.

- You didn't actually lose anything this time, but now your corpse is bugged.


Something is crashing the client..probably while trying to process slot 8000.

I will have to work up an in-depth test to figure out what's going on exactly..or learn how to actually use the
debug feature...

I suspect the blob data of the corpse will contain either a bugged item 13201 or slot 8000 of some type.

IF tradeskilling is using slot 8000 for combines or returns, I suspect this same issue is at the root of that problem too.
(Not death, but the use of slot 8000...)


Since the problem could reach back into the kernel, I don't wan't to simply 'fix' it here. Some more research
is needed..but it is on the list for sure now...
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #43  
Old 07-30-2012, 04:00 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Ok, I managed to get EQ Editor 1.30 to work enough to be able to inspect a corpse's inventory.

What I found was that my bugged corpse had two items on it...

Item 1 - CHARM slot (0) -> ITEM ID 0
Item 2 - CHARM slot (0) -> ITEM ID 0


Obviously, something is not right with the way the server currently handles loot transfers to a corpse. Whether it is in the
cursor queue or elsewhere, the corpse DOES contain entries in the blob that keeps the server from properly decaying it.

(EQ Editor looks pretty thorough..Sorry George, I still haven't tried your tools yet... I was looking specifically for some code
to incorporate into a '#command' that can be used in-game and ran across this. AndMetal seems to have something on
the wiki that could be adapted to a 'live' command for checking blobs..I'd like to add that as well. I need to find out who
wrote EQ Editor and see if I can use thier code too since it would only have to be converted from php to c++ or perl.)


http://code.google.com/p/ultraeqeditor/ will take you to this program.

To get this working, in the interim, you will need to make at least three changes:

1 - edit login.php and remove the 'md5()' wrapper from the password check at the beginning
2 - edit functions.php and remove the 'md5()' wrapper from the password check in 'CheckAuth()'
3 - edit corpse.php and change 'parent_corpse_id' to 'id'

I had to remove the wrappers because I can't log into the world server when my http password is security hashed...
And account passwords seem to be encrypted with SHA and not MD5 anyways...


These changes will let you at least see the items on the bugged corpse that was created in the last post.

Of course, you will need the same setup installed and running that's required for AllaClone. I just moved my
AllaClone files out and copied these in. You will need to edit the configuration.php file as well.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #44  
Old 07-30-2012, 05:20 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Apparently, this needs some more work..I can't seem to find newer corpses...

This corpse I was looking at was several weeks old, so I'll see what I can do with the search criteria.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #45  
Old 07-30-2012, 06:30 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

I was able to finally get to my recent corpses and see that they actually had three items of slot (0) -> itemid (0).

This matches the amount of queued items that I had on the cursor when I died (Blackboxes B, C & D.)


Ouside of the 'slot 8000' possibility, I need to follow the calls back and see if any of the queued items are actually
being allowed since these methods are processing them.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
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 12:52 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 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3