⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stall network.cpp.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
字号:


#include "StdAfx.h"

void Stall::DeleteFromDB()
{
	CharacterDatabase.WaitExecute("DELETE FROM STALL WHERE StallId = %u", Id);
}

void Stall::SaveToDB(uint32 STALLId)
{
	CharacterDatabase.Execute("INSERT INTO STALL VALUES(%u, %u, "I64FMTD", %u, %u, %u, %u, %u, %u)",
		Id, STALLId, pItem->GetGUID(), Owner, BuyoutPrice, ExpiryTime, HighestBidder, HighestBid,
		DepositAmount);
}

void Stall::UpdateInDB()
{
	CharacterDatabase.Execute("UPDATE STALL SET bidder = %u WHERE StallId = %u", HighestBidder, Id);
	CharacterDatabase.Execute("UPDATE STALL SET bid = %u WHERE StallId = %u", HighestBid, Id);
}

STALL::STALL(uint32 ID)
{
	dbc = dbcSTALL.LookupEntry(ID);
	assert(dbc);

	cut_percent = float( float(dbc->tax) / 100.0f );
	deposit_percent = float( float(dbc->fee ) / 100.0f );
}

STALL::~STALL()
{
	HM_NAMESPACE::hash_map<uint32, Stall*>::iterator itr = STALL.begin();
	for(; itr != STALL.end(); ++itr)
		delete itr->second;
}

void STALL::QueueDeletion(Stall * auct, uint32 Reason)
{
	if(auct->Deleted)
		return;

	auct->Deleted = true;
	auct->DeletedReason = Reason;
	removalLock.Acquire();
	removalList.push_back(auct);
	removalLock.Release();
}

void STALL::UpdateDeletionQueue()
{
	removalLock.Acquire();
	Stall * auct;

	list<Stall*>::iterator it = removalList.begin();
	for(; it != removalList.end(); ++it)
	{
		auct = *it;
		assert(auct->Deleted);
		RemoveStall(auct);
	}

	removalList.clear();
	removalLock.Release();
}

void STALL::UpdateSTALL()
{
	StallLock.AcquireReadLock();
	removalLock.Acquire();

	uint32 t = (uint32)UNIXTIME;
	HM_NAMESPACE::hash_map<uint32, Stall*>::iterator itr = STALL.begin();
	Stall * auct;
	for(; itr != STALL.end();)
	{
		auct = itr->second;
		++itr;

		if(t >= auct->ExpiryTime)
		{
			if(auct->HighestBidder == 0)
				auct->DeletedReason = Stall_REMOVE_EXPIRED;
			else
				auct->DeletedReason = Stall_REMOVE_WON;

			auct->Deleted = true;
			removalList.push_back(auct);
		}
	}

	removalLock.Release();
	StallLock.ReleaseReadLock();
}

void STALL::AddStall(Stall * auct)
{
	// add to the map
	StallLock.AcquireWriteLock();
	STALL.insert( HM_NAMESPACE::hash_map<uint32, Stall*>::value_type( auct->Id , auct ) );
	StallLock.ReleaseWriteLock();

	// add the item
	itemLock.AcquireWriteLock();
	StalledItems.insert( HM_NAMESPACE::hash_map<uint64, Item*>::value_type( auct->pItem->GetGUID(), auct->pItem ) );
	itemLock.ReleaseWriteLock();

	Log.Debug("STALL", "%u: Add Stall %u, expire@ %u.", dbc->id, auct->Id, auct->ExpiryTime);
}

Stall * STALL::GetStall(uint32 Id)
{
	Stall * ret;
	HM_NAMESPACE::hash_map<uint32, Stall*>::iterator itr;
	StallLock.AcquireReadLock();
	itr = STALL.find(Id);
	ret = (itr == STALL.end()) ? 0 : itr->second;
	StallLock.ReleaseReadLock();
	return ret;
}

void STALL::RemoveStall(Stall * auct)
{
	Log.Debug("STALL", "%u: Removing Stall %u, reason %u.", dbc->id, auct->Id, auct->DeletedReason);

	char subject[100];
	char body[200];
	switch(auct->DeletedReason)
	{
	case Stall_REMOVE_EXPIRED:
		{
			// ItemEntry:0:3
			snprintf(subject, 100, "%u:0:3", (unsigned int)auct->pItem->GetEntry());

			// Stall expired, resend item, no money to owner.
			sMailSystem.SendAutomatedMessage(Stall, dbc->id, auct->Owner, subject, "", 0, 0, auct->pItem->GetGUID(), 62);
		}break;

	case Stall_REMOVE_WON:
		{
			// ItemEntry:0:1
			snprintf(subject, 100, "%u:0:1", (unsigned int)auct->pItem->GetEntry());

			// <owner player guid>:bid:buyout
			snprintf(body, 200, "%X:%u:%u", (unsigned int)auct->Owner, (unsigned int)auct->HighestBid, (unsigned int)auct->BuyoutPrice);

			// Stall won by highest bidder. He gets the item.
			sMailSystem.SendAutomatedMessage(Stall, dbc->id, auct->HighestBidder, subject, body, 0, 0, auct->pItem->GetGUID(), 62);

			// Send a mail to the owner with his cut of the price.
			uint32 Stall_cut = FL2UINT(float(cut_percent * float(auct->HighestBid)));
			int32 amount = auct->HighestBid - Stall_cut + auct->DepositAmount;
			if(amount < 0)
				amount = 0;

			// ItemEntry:0:2
			snprintf(subject, 100, "%u:0:2", (unsigned int)auct->pItem->GetEntry());

			// <hex player guid>:bid:0:deposit:cut
			if(auct->HighestBid == auct->BuyoutPrice)	   // Buyout
				snprintf(body, 200, "%X:%u:%u:%u:%u", (unsigned int)auct->HighestBidder, (unsigned int)auct->HighestBid, (unsigned int)auct->BuyoutPrice, (unsigned int)auct->DepositAmount, (unsigned int)Stall_cut);
			else
				snprintf(body, 200, "%X:%u:0:%u:%u", (unsigned int)auct->HighestBidder, (unsigned int)auct->HighestBid, (unsigned int)auct->DepositAmount, (unsigned int)Stall_cut);

			// send message away.
			sMailSystem.SendAutomatedMessage(Stall, dbc->id, auct->Owner, subject, body, amount, 0, 0, 62);
		}break;
	case Stall_REMOVE_CANCELLED:
		{
			snprintf(subject, 100, "%u:0:5", (unsigned int)auct->pItem->GetEntry());
			uint32 cut = uint32(float(cut_percent * auct->HighestBid));
			Player * plr = objmgr.GetPlayer(auct->Owner);
			if(cut && plr && plr->GetUInt32Value(PLAYER_FIELD_COINAGE) >= cut)
				plr->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -((int32)cut));
			
			sMailSystem.SendAutomatedMessage(Stall, GetID(), auct->Owner, subject, "", 0, 0, auct->pItem->GetGUID(), 62);
			
			// return bidders money
			if(auct->HighestBidder)
			{
				sMailSystem.SendAutomatedMessage(Stall, GetID(), auct->HighestBidder, subject, "", auct->HighestBid, 
					0, 0, 62);
			}
			
		}break;
	}

	// Remove the Stall from the hashmap.
	StallLock.AcquireWriteLock();
	itemLock.AcquireWriteLock();
	
	STALL.erase(auct->Id);
	StalledItems.erase(auct->pItem->GetGUID());

	StallLock.ReleaseWriteLock();
	itemLock.ReleaseWriteLock();

	// Destroy the item from memory (it still remains in the db)
	delete auct->pItem;

	// Finally destroy the Stall instance.
	auct->DeleteFromDB();
	delete auct;
}

void WorldSession::HandleStallListBidderItems( WorldPacket & recv_data )
{
	if(!_player->IsInWorld())
		return;

	uint64 guid;
	recv_data >> guid;

	Creature * pCreature = _player->GetMapMgr()->GetCreature(GET_LOWGUID_PART(guid));
	if(!pCreature || !pCreature->STALL)
		return;

	pCreature->STALL->SendBidListPacket(_player, &recv_data);
}

void Stall::AddToPacket(WorldPacket & data)
{
	data << Id;
	data << pItem->GetEntry();

	for (uint32 i = 0; i < 6; i++)
	{
		data << pItem->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + (3 * i));   // Enchantment ID
		data << uint32(pItem->GetEnchantmentApplytime(i));						 // Unknown / maybe ApplyTime
		data << pItem->GetUInt32Value(ITEM_FIELD_SPELL_CHARGES + i);	   // Charges
	}

	data << pItem->GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID);		 // -ItemRandomSuffix / random property	 : If the value is negative its ItemRandomSuffix if its possitive its RandomItemProperty
	data << pItem->GetUInt32Value(ITEM_FIELD_PROPERTY_SEED);			  // when ItemRandomSuffix is used this is the modifier

	/******************** ItemRandomSuffix***************************
	* For what I have seen ItemRandomSuffix is like RandomItemProperty
	* The only difference is has is that it has a modifier.
	* That is the result of jewelcrafting, the effect is that the
	* enchantment is variable. That means that a enchantment can be +1 and 
	* with more Jem's +12 or so.
	* Decription for lookup: You get the enchantmentSuffixID and search the
	* DBC for the last 1 - 3 value's(depending on the enchantment).
	* That value is what I call EnchantmentValue. You guys might find a 
	* better name but for now its good enough. The formula to calculate
	* The ingame "GAIN" is:
	* (Modifier / 10000) * enchantmentvalue = EnchantmentGain;	
	*/
	
	data << pItem->GetUInt32Value(ITEM_FIELD_STACK_COUNT); // Amount
	data << uint32(0);				  // Unknown
	data << uint32(0);				  // Unknown
	data << uint64(Owner);			  // Owner guid
	data << HighestBid;				 // Current prize
	// hehe I know its evil, this creates a nice trough put of money
	data << uint32(50);				 // Next bid value modifier, like current bid + this value
	data << BuyoutPrice;				// Buyout
	data << uint32((ExpiryTime - UNIXTIME) * 1000); // Time left
	data << uint64(HighestBidder);	  // Last bidder
	data << HighestBid;				 // The bid of the last bidder
}

void STALL::SendBidListPacket(Player * plr, WorldPacket * packet)
{
	uint32 count = 0;

	WorldPacket data(SMSG_Stall_BIDDER_LIST_RESULT, 1024);
	data << uint32(0);										  // Placeholder

	Stall * auct;
	StallLock.AcquireReadLock();
	HM_NAMESPACE::hash_map<uint32, Stall*>::iterator itr = STALL.begin();
	for(; itr != STALL.end(); ++itr)
	{
		auct = itr->second;
		if(auct->HighestBidder == plr->GetGUID())
		{
			if(auct->Deleted) continue;

			auct->AddToPacket(data);
			(*(uint32*)&data.contents()[0])++;
			++count;
		}			
	}
#ifdef USING_BIG_ENDIAN
	swap32((uint32*)&data.contents()[0]);
#endif
	data << count;
	StallLock.ReleaseReadLock();
	plr->GetSession()->SendPacket(&data);
}

void STALL::SendOwnerListPacket(Player * plr, WorldPacket * packet)
{
	uint32 count = 0;

	WorldPacket data(SMSG_Stall_OWNER_LIST_RESULT, 1024);
	data << uint32(0);										  // Placeholder

	Stall * auct;
	StallLock.AcquireReadLock();
	HM_NAMESPACE::hash_map<uint32, Stall*>::iterator itr = STALL.begin();
	for(; itr != STALL.end(); ++itr)
	{
		auct = itr->second;
		if(auct->Owner == plr->GetGUID())
		{
			if(auct->Deleted) continue;

			auct->AddToPacket(data);
			(*(uint32*)&data.contents()[0])++;
			++count;
		}			
	}
	data << count;
#ifdef USING_BIG_ENDIAN
	swap32((uint32*)&data.contents()[0]);
#endif
	StallLock.ReleaseReadLock();
	plr->GetSession()->SendPacket(&data);
}

void STALL::SendStallNotificationPacket(Player * plr, Stall * auct)
{
	WorldPacket data(SMSG_Stall_BIDDER_NOTIFICATION, 32);
	data << GetID(); 
	data << auct->Id;
	data << uint64(auct->HighestBidder);
	data << uint32(0);
	data << uint32(0);
	data << auct->pItem->GetEntry();
	data << uint32(0);
	
	plr->GetSession()->SendPacket(&data);
}

void WorldSession::HandleStallPlaceBid( WorldPacket & recv_data )
{
	if(!_player->IsInWorld())
		return;

	uint64 guid;
	recv_data >> guid;

	uint32 Stall_id, price;
	recv_data >> Stall_id >> price;

	Creature * pCreature = _player->GetMapMgr()->GetCreature(GET_LOWGUID_PART(guid));
	if(!pCreature || !pCreature->STALL)
		return;

	// Find Item
	STALL * ah = pCreature->STALL;
	Stall * auct = ah->GetStall(Stall_id);
	if(auct == 0 || !auct->Owner || !_player || auct->Owner == _player->GetGUID())
		return;

	if(auct->HighestBid > price && price != auct->BuyoutPrice)
		return;

	if(_player->GetUInt32Value(PLAYER_FIELD_COINAGE) < price)
		return;

	_player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -((int32)price));
	if(auct->HighestBidder != 0)
	{
		// Return the money to the last highest bidder.
		char subject[100];
		snprintf(subject, 100, "%u:0:0", (int)auct->pItem->GetEntry());
		sMailSystem.SendAutomatedMessage(Stall, ah->GetID(), auct->HighestBidder, subject, "", auct->HighestBid,
			0, 0, 62);
	}

	if(auct->BuyoutPrice == price)
	{
		auct->HighestBidder = _player->GetLowGUID();
		auct->HighestBid = price;

		// we used buyout on the item.
		ah->QueueDeletion(auct, Stall_REMOVE_WON);

		// send response packet
		WorldPacket data(SMSG_Stall_COMMAND_RESULT, 12);
		data << auct->Id << uint32(Stall_CANCEL) << uint32(0) << uint32(0);
		SendPacket(&data);
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -