Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Reply
 
Thread Tools Display Modes
  #1  
Old 01-12-2011, 03:54 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Thanks for the extra testing. Sounds like we should be all set to get this added in.

If the client is deleting lore items, it would be nice to know which one it will delete (the existing/old one(s) or the newly acquired one). Either way, it sounds like we just need to make sure that the scenario of duplicate lore items never happens such as this case. Makes me wonder if there may be other cases of this out there as well. I haven't seen any zone crashes in relation to augmenting items in quite a while, but I have definitely had reports of item loss while augmenting. This fix sounds like it should resolve the issue with the new inventory based aug sealer, but we may still have more aug code changes needed to really remove the possibility of item loss during augmentation.

I noticed a few things in the augmenting code that could probably use some rewriting. Some of it stood out as potential issues, but it will take another closer look to make sure changes are required. Maybe I will do a rewrite of some of it when I have some time.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #2  
Old 01-12-2011, 04:57 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Ok, here is my rewrite of the function, including the changes from l0stmancd. I highlighted the section I changed in green (can't make a normal diff atm).

tradeskills.cpp
Code:
void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augment, Object *worldo)
{
	if (!user || !in_augment)
	{
		LogFile->write(EQEMuLog::Error, "Client or AugmentItem_Struct not set in Object::HandleAugmentation");
		return;
	}

	ItemInst* container = NULL;

	if (worldo)
	{
		container = worldo->m_inst;
	} 
	else
	{
		// Check to see if they have an inventory container type 53 that is used for this.
		Inventory& user_inv = user->GetInv();
		ItemInst* inst = NULL;
		
		inst = user_inv.GetItem(in_augment->container_slot);
		if (inst)
		{
			const Item_Struct* item = inst->GetItem();
			if (item && inst->IsType(ItemClassContainer) && item->BagType == 53)
			{
				// We have found an appropriate inventory augmentation sealer
				container = inst;

				// Verify that no more than two items are in container to guarantee no inadvertant wipes.
				uint8 itemsFound = 0;
				for (uint8 i=0; i<10; i++)
				{
					const ItemInst* inst = container->GetItem(i);
					if (inst)
					{
						itemsFound++;
					}
				}

				if (itemsFound != 2)
				{
					user->Message(13, "Error:  Too many/few items in augmentation container.");
					return;
				}
			}
		}
	}

	if(!container)
	{
		LogFile->write(EQEMuLog::Error, "Player tried to augment an item without a container set.");
		user->Message(13, "Error: This item is not a container!");
		return;
	}
	
	ItemInst *tobe_auged, *auged_with = NULL;
	sint8 slot=-1;

	// Verify 2 items in the augmentation device
	if (container->GetItem(0) && container->GetItem(1))
	{
		// Verify 1 item is augmentable and the other is not
		if (container->GetItem(0)->IsAugmentable() && !container->GetItem(1)->IsAugmentable())
		{
			tobe_auged = container->GetItem(0);
			auged_with = container->GetItem(1);
		}
		else if (!container->GetItem(0)->IsAugmentable() && container->GetItem(1)->IsAugmentable())
		{
			tobe_auged = container->GetItem(1);
			auged_with = container->GetItem(0);
		}
		else
		{
			// Either 2 augmentable items found or none found
			// This should never occur due to client restrictions, but prevent in case of a hack
			user->Message(13, "Error: Must be 1 augmentable item in the sealer");
			// May want to user->Kick() them to prevent potential inventory sync issues if it happened legitimately
			return;
		}
	}
	else
	{
		// Less than 2 items in the augmentation device
		// This should never occur due to client restrictions, but prevent in case of a hack
		if (!container->GetItem(0))
		{
			user->Message(13, "Error: No item in slot 0 of sealer");
		}
		if (!container->GetItem(1))
		{
			user->Message(13, "Error: No item in slot 1 of sealer");
		}
		// May want to user->Kick() them to prevent potential inventory sync issues if it happened legitimately
		return;
	}

	bool deleteItems = false;

	ItemInst *itemOneToPush = NULL, *itemTwoToPush = NULL;

	// Adding augment
	if (in_augment->augment_slot == -1)
	{
		if (((slot=tobe_auged->AvailableAugmentSlot(auged_with->GetAugmentType()))!=-1) && (tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots)))
		{
			tobe_auged->PutAugment(slot,*auged_with);
			itemOneToPush = tobe_auged->Clone();
			deleteItems = true;
		}
		else
		{
			user->Message(13, "Error: No available slot for augment");
		}
	}
	else
	{
		ItemInst *old_aug=NULL;
		const uint32 id=auged_with->GetID();
		if (id==40408 || id==40409 || id==40410)
			tobe_auged->DeleteAugment(in_augment->augment_slot);
		else
			old_aug=tobe_auged->RemoveAugment(in_augment->augment_slot);

		itemOneToPush = tobe_auged->Clone();
		if (old_aug)
			itemTwoToPush = old_aug->Clone();

		deleteItems = true;
	}

	if (deleteItems)
	{
		if (worldo)
		{
			container->Clear();
			EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClearObject, sizeof(ClearObject_Struct));
			ClearObject_Struct *cos = (ClearObject_Struct *)outapp->pBuffer;
			cos->Clear = 1;
			user->QueuePacket(outapp);
			safe_delete(outapp);
			database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID());
		}
		else
		{
			// Delete items in our inventory container... 
			for (uint8 i=0; i<10; i++)
			{
				const ItemInst* inst = container->GetItem(i);
				if (inst)
				{
					user->DeleteItemInInventory(Inventory::CalcSlotId(in_augment->container_slot,i),0,true);
				}
			}
			// Explicitly mark container as cleared.
			container->Clear();
		}
	}

	// Must push items after the items in inventory are deleted - necessary due to lore items...
	if (itemOneToPush)
	{
		user->PushItemOnCursor(*itemOneToPush,true);
	}
	if (itemTwoToPush)
	{
		user->PushItemOnCursor(*itemTwoToPush,true);
	}

}
Hopefully I have some time to actually test these changes myself. I dunno if that will be soon or when. If l0stmancd or anyone else wants to run it through some decent testing, feel free. I will probably run it on my server for a day or so to make sure there are no major issues with it before committing it. If anyone sees any potential issues with the code, lemme know as well.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 01-13-2011 at 02:38 AM..
Reply With Quote
  #3  
Old 01-12-2011, 11:08 AM
l0stmancd
Fire Beetle
 
Join Date: Apr 2005
Posts: 23
Default

Reviewed change - off hand I do not see an issue.

Will do a full test on the augmentation sealer and the bird bath later today and post findings.
Reply With Quote
  #4  
Old 01-12-2011, 06:41 PM
l0stmancd
Fire Beetle
 
Join Date: Apr 2005
Posts: 23
Default

Hi Trevius,

Spent about 30 minutes testing the change today. Everything seems good in the code as it is except maybe fixing the indent on the "itemOneToPush = tobe_auged->Clone()" unless this was introduced just on the forums when you posted.

Testing conducted in both aug pool + aug inventory container:
Augment / Deaugmenting with lore sword / augment in different slots each time.
Introduced server lag and was able to still augment / deaugment without an issue.

NOTE: there is still the chance to cause client oddities if a user calls the augment procedure, the server lags out, and then a client picks up one of the items in the augmentation pool / inventory. This has always been here and is present for tradeskills also so I dont think its something to worry about. Just mentioning it to be complete. Very rare that this would happen. Wish there was a way to stop the user from taking items out of a pack / container after they send the client command for combine or aug. Not to stop hackers but to stop legit people who may make a mistake when the server is lagging.

NOTE: Was able to get into one of the areas that you have marked "// Less than 2 items in the augmentation device ... in case of a hack ..." It is actually pretty easy to get in here if the server lags out long enough for you to press the augment/deaugment button twice. You have a note saying you may wish to kick a user due to sync issues - would not necessarily suggest kicking a user in that case as the server could be (in another thread) about to pass down the users newly augmented items. You don't have a user->Kick() call (this was just a note you made) but wanted to mention it.

Your other area above it ("Either 2 augmentable items found or none found") - yeah, I cannot think of a single way that this could be done legitimately. Would not be a bad thing to either kick() or log to the hackers table but, frankly, I dont see a harm in leaving it the way you have it.

Everything seems good.
Reply With Quote
  #5  
Old 01-13-2011, 02:59 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Thanks for reviewing and testing that

I will get it on my server and then put it on the SVN if no issues. I will just remove the comments about kicking users, as it doesn't seem to be needed. If there are any other item loss issues, they are probably related to something else like SwapItem, or something else that the client handles a bit differently than the server.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
Reply

Thread Tools
Display Modes

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 07:10 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