本文整理汇总了C++中WorldPacket::size方法的典型用法代码示例。如果您正苦于以下问题:C++ WorldPacket::size方法的具体用法?C++ WorldPacket::size怎么用?C++ WorldPacket::size使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类WorldPacket
的用法示例。
在下文中一共展示了WorldPacket::size方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: HandleMovementOpcodes
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
uint32 opcode = recv_data.GetOpcode();
DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
recv_data.hexlike();
Unit *mover = _player->m_mover;
Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if(plMover && plMover->IsBeingTeleported())
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
/* extract packet */
ObjectGuid guid;
MovementInfo movementInfo;
recv_data >> guid.ReadAsPacked();
recv_data >> movementInfo;
/*----------------*/
if (!MaNGOS::IsValidMapCoord(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o))
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
/* handle special cases */
if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT) && !mover->GetVehicleGUID())
{
// transports size limited
// (also received at zeppelin/lift leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if( movementInfo.GetTransportPos()->x > 50 || movementInfo.GetTransportPos()->y > 50 || movementInfo.GetTransportPos()->z > 100 )
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
if( !MaNGOS::IsValidMapCoord(movementInfo.GetPos()->x + movementInfo.GetTransportPos()->x, movementInfo.GetPos()->y + movementInfo.GetTransportPos()->y,
movementInfo.GetPos()->z + movementInfo.GetTransportPos()->z, movementInfo.GetPos()->o + movementInfo.GetTransportPos()->o) )
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
// if we boarded a transport, add us to it
if (plMover && !plMover->m_transport)
{
// elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
{
if ((*iter)->GetObjectGuid() == movementInfo.GetTransportGuid())
{
plMover->m_transport = (*iter);
(*iter)->AddPassenger(plMover);
break;
}
}
}
}
else if (plMover && plMover->m_transport) // if we were on a transport, leave
{
plMover->m_transport->RemovePassenger(plMover);
plMover->m_transport = NULL;
movementInfo.ClearTransportData();
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
plMover->HandleFall(movementInfo);
if (plMover && (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING) != plMover->IsInWater()))
{
// now client not include swimming flag in case jumping under water
plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z) );
}
if (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING))
{
if(mover->GetTypeId() == TYPEID_UNIT)
{
if(((Creature*)mover)->isVehicle() && !((Creature*)mover)->canSwim())
{
// NOTE : we should enter evade mode here, but...
((Vehicle*)mover)->SetSpawnDuration(1);
}
}
}
/*----------------------*/
/* process position-change */
movementInfo.UpdateTime(getMSTime());
WorldPacket data(opcode, recv_data.size());
data.appendPackGUID(mover->GetGUID()); // write guid
movementInfo.Write(data); // write data
mover->SendMessageToSetExcept(&data, _player);
//.........这里部分代码省略.........
示例2: HandleMovementOpcodes
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
uint32 opcode = recv_data.GetOpcode();
sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
if(GetPlayer()->GetDontMove())
return;
/* extract packet */
MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
/*----------------*/
if(recv_data.size() != recv_data.rpos())
{
sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is %u bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos());
KickPlayer();
return;
}
if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
return;
/* handle special cases */
if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 )
return;
if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y+movementInfo.t_y,
movementInfo.z+movementInfo.t_z, movementInfo.o+movementInfo.t_o) )
return;
// if we boarded a transport, add us to it
if (!GetPlayer()->m_transport)
{
// elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
{
GetPlayer()->m_transport = (*iter);
(*iter)->AddPassenger(GetPlayer());
break;
}
}
}
}
else if (GetPlayer()->m_transport) // if we were on a transport, leave
{
GetPlayer()->m_transport->RemovePassenger(GetPlayer());
GetPlayer()->m_transport = NULL;
movementInfo.t_x = 0.0f;
movementInfo.t_y = 0.0f;
movementInfo.t_z = 0.0f;
movementInfo.t_o = 0.0f;
movementInfo.t_time = 0;
movementInfo.t_seat = -1;
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())
GetPlayer()->HandleFall(movementInfo);
if(((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater())
{
// now client not include swimming flag in case jumping under water
GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
}
/*----------------------*/
/* process position-change */
Unit *mover = _player->m_mover;
recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2)
WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size()));
data.append(_player->m_mover->GetPackGUID()); // use mover guid
data.append(recv_data.contents(), recv_data.size());
GetPlayer()->SendMessageToSet(&data, false);
if(!_player->GetCharmGUID()) // nothing is charmed
{
_player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
_player->m_movementInfo = movementInfo;
_player->SetUnitMovementFlags(movementInfo.flags);
}
else
{
if(mover->GetTypeId() != TYPEID_PLAYER) // unit, creature, pet, vehicle...
{
if(Map *map = mover->GetMap())
map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
mover->SetUnitMovementFlags(movementInfo.flags);
}
else // player
{
((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
((Player*)mover)->m_movementInfo = movementInfo;
//.........这里部分代码省略.........
示例3: HandlePetSetAction
void WorldSession::HandlePetSetAction(WorldPacket & recvData)
{
sLog->outInfo(LOG_FILTER_NETWORKIO, "HandlePetSetAction. CMSG_PET_SET_ACTION");
uint64 petguid;
uint8 count;
recvData >> petguid;
Unit* pet = ObjectAccessor::GetUnit(*_player, petguid);
if (!pet || pet != _player->GetFirstControlled())
{
sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetSetAction: Unknown pet (GUID: %u) or pet owner (GUID: %u)", GUID_LOPART(petguid), _player->GetGUIDLow());
return;
}
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
return;
}
count = (recvData.size() == 24) ? 2 : 1;
uint32 position[2];
uint32 data[2];
bool move_command = false;
for (uint8 i = 0; i < count; ++i)
{
recvData >> position[i];
recvData >> data[i];
uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]);
//ignore invalid position
if (position[i] >= MAX_UNIT_ACTION_BAR_INDEX)
return;
// in the normal case, command and reaction buttons can only be moved, not removed
// at moving count == 2, at removing count == 1
// ignore attempt to remove command|reaction buttons (not possible at normal case)
if (act_state == ACT_COMMAND || act_state == ACT_REACTION)
{
if (count == 1)
return;
move_command = true;
}
}
// check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness)
if (move_command)
{
uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]);
if (act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION)
{
uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]);
UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]);
if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() ||
act_state_0 != actionEntry_1->GetType())
return;
}
uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]);
if (act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION)
{
uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]);
UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]);
if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() ||
act_state_1 != actionEntry_0->GetType())
return;
}
}
for (uint8 i = 0; i < count; ++i)
{
uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]);
uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]);
sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X",
_player->GetName().c_str(), position[i], spell_id, uint32(act_state));
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id)))
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id))
{
//sign for autocast
if (act_state == ACT_ENABLED)
{
if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet())
((Pet*)pet)->ToggleAutocast(spellInfo, true);
else
for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == pet->GetEntry())
(*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, true);
}
//.........这里部分代码省略.........
示例4: SizeError
void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const
{
sLog.outError("Client (account %u) send packet %s (%u) with size %u but expected %u (attempt crash server?), skipped",
GetAccountId(),LookupOpcodeName(packet.GetOpcode()),packet.GetOpcode(),packet.size(),size);
}
示例5: HandleUseItemOpcode
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
uint8 bagIndex, slot;
uint8 cast_flags; // flags (if 0x02 - some additional data are received)
uint8 cast_count; // next cast if exists (single or not)
ObjectGuid itemGuid;
uint32 glyphIndex; // something to do with glyphs?
uint32 spellid; // casted spell id
recvPacket >> bagIndex >> slot >> cast_count >> spellid >> itemGuid >> glyphIndex >> cast_flags;
// TODO: add targets.read() check
Player* pUser = _player;
// ignore for remote control state
if (!pUser->IsSelfMover())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
return;
}
// reject fake data
if (glyphIndex >= MAX_GLYPH_SLOT_INDEX)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
Item *pItem = pUser->GetItemByPos(bagIndex, slot);
if (!pItem)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
if (pItem->GetObjectGuid() != itemGuid)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
DETAIL_LOG("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = " SIZEFMTD, bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, cast_flags, recvPacket.size());
ItemPrototype const *proto = pItem->GetProto();
if (!proto)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
return;
}
// some item classes can be used only in equipped state
if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
return;
}
InventoryResult msg = pUser->CanUseItem(pItem);
if (msg != EQUIP_ERR_OK)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError( msg, pItem, NULL );
return;
}
// not allow use item from trade (cheat way only)
if (pItem->IsInTrade())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
return;
}
// only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB)
if (proto->Class == ITEM_CLASS_CONSUMABLE &&
!(proto->Flags & ITEM_FLAG_USEABLE_IN_ARENA) &&
pUser->InArena())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL);
return;
}
if ((proto->Area && proto->Area != pUser->GetAreaId()) ||
(proto->Map && proto->Map != pUser->GetMapId()))
{
if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid))
Spell::SendCastResult(pUser, spellInfo, cast_count, SPELL_FAILED_INCORRECT_AREA);
return;
}
if (pUser->isInCombat())
{
for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
//.........这里部分代码省略.........
示例6: HandleCastSpellOpcode
void WorldSession::HandleCastSpellOpcode(WorldPacket & recvPacket)
{
CHECK_INWORLD_RETURN
uint32 spellId;
uint8 cn, unk; //Alice : Added to 3.0.2
recvPacket >> cn >> spellId >> unk;
// check for spell id
SpellEntry* spellInfo = dbcSpell.LookupEntryForced(spellId);
if(!spellInfo)
{
LOG_ERROR("WORLD: unknown spell id %i", spellId);
return;
}
if(!_player->isAlive() && _player->GetShapeShift() != FORM_SPIRITOFREDEMPTION && !(spellInfo->Attributes & ATTRIBUTES_DEAD_CASTABLE)) //They're dead, not in spirit of redemption and the spell can't be cast while dead.
return;
LOG_DETAIL("WORLD: got cast spell packet, spellId - %i (%s), data length = %i",
spellId, spellInfo->Name, recvPacket.size());
// Cheat Detection only if player and not from an item
// this could fuck up things but meh it's needed ALOT of the newbs are using WPE now
// WPE allows them to mod the outgoing packet and basically choose what ever spell they want :(
if(!GetPlayer()->HasSpell(spellId))
{
sCheatLog.writefromsession(this, "Cast spell %lu but doesn't have that spell.", spellId);
LOG_DETAIL("WORLD: Spell isn't cast because player \'%s\' is cheating", GetPlayer()->GetName());
return;
}
if(spellInfo->Attributes & ATTRIBUTES_PASSIVE)
{
sCheatLog.writefromsession(this, "Cast passive spell %lu.", spellId);
LOG_DETAIL("WORLD: Spell isn't cast because player \'%s\' is cheating", GetPlayer()->GetName());
return;
}
if(GetPlayer()->GetOnMeleeSpell() != spellId)
{
//autoshot 75
if((spellInfo->AttributesExB & ATTRIBUTESEXB_ACTIVATE_AUTO_SHOT) /*spellInfo->Attributes == 327698*/) // auto shot..
{
//sLog.outString( "HandleSpellCast: Auto Shot-type spell cast (id %u, name %s)" , spellInfo->Id , spellInfo->Name );
Item* weapon = GetPlayer()->GetItemInterface()->GetInventoryItem(EQUIPMENT_SLOT_RANGED);
if(!weapon)
return;
uint32 spellid;
switch(weapon->GetProto()->SubClass)
{
case 2: // bows
case 3: // guns
case 18: // crossbow
spellid = SPELL_RANGED_GENERAL;
break;
case 16: // thrown
spellid = SPELL_RANGED_THROW;
break;
case 19: // wands
spellid = SPELL_RANGED_WAND;
break;
default:
spellid = 0;
break;
}
if(!spellid)
spellid = spellInfo->Id;
if(!_player->m_onAutoShot)
{
_player->m_AutoShotTarget = _player->GetSelection();
uint32 duration = _player->GetBaseAttackTime(RANGED);
SpellCastTargets targets(recvPacket, GetPlayer()->GetGUID());
if(!targets.m_unitTarget)
{
LOG_DEBUG("Cancelling auto-shot cast because targets.m_unitTarget is null!");
return;
}
SpellEntry* sp = dbcSpell.LookupEntry(spellid);
_player->m_AutoShotSpell = sp;
_player->m_AutoShotDuration = duration;
//This will fix fast clicks
if(_player->m_AutoShotAttackTimer < 500)
_player->m_AutoShotAttackTimer = 500;
_player->m_onAutoShot = true;
}
return;
}
if(_player->m_currentSpell)
{
if(_player->m_currentSpell->getState() == SPELL_STATE_CASTING)
{
// cancel the existing channel spell, cast this one
_player->m_currentSpell->cancel();
//.........这里部分代码省略.........
示例7: HandleMovementOpcodes
//.........这里部分代码省略.........
}
}
else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid)
{
bool foundNewTransport = false;
plrMover->m_transport->RemovePassenger(plrMover);
if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
{
foundNewTransport = true;
plrMover->m_transport = transport;
transport->AddPassenger(plrMover);
}
if (!foundNewTransport)
{
plrMover->m_transport = NULL;
movementInfo.ResetTransport();
}
}
}
if (!mover->GetTransport() && !mover->GetVehicle())
{
GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
movementInfo.transport.guid = 0;
}
}
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
{
plrMover->m_transport->RemovePassenger(plrMover);
plrMover->m_transport = NULL;
movementInfo.ResetTransport();
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
plrMover->HandleFall(movementInfo);
if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
{
// now client not include swimming flag in case jumping under water
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
}
uint32 mstime = getMSTime();
/*----------------------*/
if (m_clientTimeDelay == 0)
m_clientTimeDelay = mstime - movementInfo.time;
/* process position-change */
movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY;
movementInfo.guid = mover->GetGUID();
mover->m_movementInfo = movementInfo;
/*----------------------*/
/* process position-change */
// this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
if (mover->GetVehicle())
{
mover->SetOrientation(movementInfo.pos.GetOrientation());
return;
}
mover->UpdatePosition(movementInfo.pos);
WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size());
mover->WriteMovementInfo(data);
mover->SendMessageToSet(&data, _player);
if (plrMover) // nothing is charmed, or player charmed
{
if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING)))
plrMover->SetStandState(UNIT_STAND_STATE_STAND);
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId());
float depth = zone ? zone->MaxDepth : -500.0f;
if (movementInfo.pos.GetPositionZ() < depth)
{
if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
{
// NOTE: this is actually called many times while falling
// even after the player has been teleported away
/// @todo discard movement packets after the player is rooted
if (plrMover->IsAlive())
{
plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
// player can be alive if GM/etc
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
if (!plrMover->IsAlive())
plrMover->KillPlayer();
}
}
}
}
}
示例8: HandlePing
int WorldSocket::HandlePing (WorldPacket& recvPacket)
{
uint32 ping;
uint32 latency;
if (recvPacket.size () < 8)
{
sLog.outError ("WorldSocket::_HandlePing wrong packet size");
return -1;
}
// Get the ping packet content
recvPacket >> ping;
recvPacket >> latency;
if (m_LastPingTime == ACE_Time_Value::zero)
m_LastPingTime = ACE_OS::gettimeofday (); // for 1st ping
else
{
ACE_Time_Value cur_time = ACE_OS::gettimeofday ();
ACE_Time_Value diff_time (cur_time);
diff_time -= m_LastPingTime;
m_LastPingTime = cur_time;
if (diff_time < ACE_Time_Value (27))
{
++m_OverSpeedPings;
uint32 max_count = sWorld.getConfig (CONFIG_MAX_OVERSPEED_PINGS);
if (max_count && m_OverSpeedPings > max_count)
{
ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
if (m_Session && m_Session->GetSecurity () == SEC_PLAYER)
{
sLog.outError ("WorldSocket::HandlePing: Player kicked for "
"overspeeded pings address = %s",
GetRemoteAddress ().c_str ());
return -1;
}
}
}
else
m_OverSpeedPings = 0;
}
// critical section
{
ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
if (m_Session)
m_Session->SetLatency (latency);
else
{
sLog.outError ("WorldSocket::HandlePing: peer sent CMSG_PING, "
"but is not authenticated or got recently kicked,"
" address = %s",
GetRemoteAddress ().c_str ());
return -1;
}
}
WorldPacket packet (SMSG_PONG, 4);
packet << ping;
return SendPacket (packet);
}
示例9: HandleAuctionListBidderItems
//called when player lists his bids
void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data,8+4+4);
uint64 guid; //NPC guid
uint32 listfrom; //page of auctions
uint32 outbiddedCount; //count of outbidded auctions
recv_data >> guid;
recv_data >> listfrom; // not used in fact (this list not have page control in client)
recv_data >> outbiddedCount;
if (recv_data.size() != (16 + outbiddedCount * 4 ))
{
sLog.outError("Client sent bad opcode!!! with count: %u and size : %d (mustbe: %d", outbiddedCount, recv_data.size(),(16 + outbiddedCount * 4 ));
outbiddedCount = 0;
}
Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER);
if (!pCreature)
{
sLog.outDebug( "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
return;
}
// remove fake death
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
uint32 location = AuctioneerFactionToLocation(pCreature->getFaction());
AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location );
WorldPacket data( SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4) );
Player *pl = GetPlayer();
data << (uint32) 0; //add 0 as count
uint32 count = 0;
uint32 totalcount = 0;
while ( outbiddedCount > 0) //add all data, which client requires
{
--outbiddedCount;
uint32 outbiddedAuctionId;
recv_data >> outbiddedAuctionId;
AuctionEntry * auction = mAuctions->GetAuction( outbiddedAuctionId );
if ( auction && SendAuctionInfo(data, auction))
{
++totalcount;
++count;
}
}
for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr)
{
AuctionEntry *Aentry = itr->second;
if( Aentry && Aentry->bidder == pl->GetGUIDLow() )
{
if (SendAuctionInfo(data, itr->second))
++count;
++totalcount;
}
}
data.put<uint32>( 0, count ); // add count to placeholder
data << totalcount;
data << (uint32)300; //unk 2.3.0
SendPacket(&data);
}
示例10: HandleMovementOpcodes
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
uint32 opcode = recv_data.GetOpcode();
sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
recv_data.hexlike();
Unit *mover = _player->m_mover;
Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if(plMover && plMover->IsBeingTeleported())
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
/* extract packet */
uint64 guid;
if(!recv_data.readPackGUID(guid))
return;
MovementInfo movementInfo;
movementInfo.guid = guid;
ReadMovementInfo(recv_data, &movementInfo);
/*----------------*/
if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
/* handle special cases */
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 )
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y,
movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o) )
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
// if we boarded a transport, add us to it
if (plMover && !plMover->m_transport)
{
// elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
{
plMover->m_transport = (*iter);
(*iter)->AddPassenger(plMover);
break;
}
}
}
}
else if (plMover && plMover->m_transport) // if we were on a transport, leave
{
plMover->m_transport->RemovePassenger(plMover);
plMover->m_transport = NULL;
movementInfo.t_x = 0.0f;
movementInfo.t_y = 0.0f;
movementInfo.t_z = 0.0f;
movementInfo.t_o = 0.0f;
movementInfo.t_time = 0;
movementInfo.t_seat = -1;
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
plMover->HandleFall(movementInfo);
if (plMover && (movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING) != plMover->IsInWater()))
{
// now client not include swimming flag in case jumping under water
plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
}
/*----------------------*/
/* process position-change */
WorldPacket data(opcode, recv_data.size());
movementInfo.time = getMSTime();
movementInfo.guid = mover->GetGUID();
WriteMovementInfo(&data, &movementInfo);
GetPlayer()->SendMessageToSet(&data, false);
if(plMover) // nothing is charmed, or player charmed
{
plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
//.........这里部分代码省略.........
示例11: HandleAuthSession
int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
{
// NOTE: ATM the socket is singlethread, have this in mind ...
uint8 digest[20];
uint32 clientSeed;
uint32 unk2;
uint32 BuiltNumberClient;
uint32 id, security;
uint8 expansion = 0;
LocaleConstant locale;
std::string account;
Sha1Hash sha1;
BigNumber v, s, g, N, x, I;
WorldPacket packet, SendAddonPacked;
BigNumber K;
if (recvPacket.size () < (4 + 4 + 1 + 4 + 20))
{
sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size");
return -1;
}
// Read the content of the packet
recvPacket >> BuiltNumberClient; // for now no use
recvPacket >> unk2;
recvPacket >> account;
if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20))
{
sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check");
return -1;
}
recvPacket >> clientSeed;
recvPacket.read (digest, 20);
DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u",
BuiltNumberClient,
unk2,
account.c_str (),
clientSeed);
// Get the account information from the realmd database
std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below
loginDatabase.escape_string (safe_account);
// No SQL injection, username escaped.
QueryResult *result =
loginDatabase.PQuery ("SELECT "
"id, " //0
"gmlevel, " //1
"sessionkey, " //2
"last_ip, " //3
"locked, " //4
"sha_pass_hash, " //5
"v, " //6
"s, " //7
"expansion, " //8
"mutetime, " //9
"locale " //10
"FROM account "
"WHERE username = '%s'",
safe_account.c_str ());
// Stop if the account is not found
if (!result)
{
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
SendPacket (packet);
sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
return -1;
}
Field* fields = result->Fetch ();
expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[8].GetUInt8()) ? fields[8].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION));
N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
g.SetDword (7);
I.SetHexStr (fields[5].GetString ());
//In case of leading zeros in the I hash, restore them
uint8 mDigest[SHA_DIGEST_LENGTH];
memset (mDigest, 0, SHA_DIGEST_LENGTH);
if (I.GetNumBytes () <= SHA_DIGEST_LENGTH)
memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ());
std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH);
s.SetHexStr (fields[7].GetString ());
sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ());
sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH);
sha1.Finalize ();
x.SetBinary (sha1.GetDigest (), sha1.GetLength ());
v = g.ModExp (x, N);
//.........这里部分代码省略.........
示例12: HandleCastSpellOpcode
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
uint32 spellId;
uint8 cast_count, unk_flags;
recvPacket >> cast_count;
recvPacket >> spellId;
recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received)
// ignore for remote control state (for player case)
Unit* mover = _player->GetMover();
if (mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i",
spellId, cast_count, unk_flags, (uint32)recvPacket.size());
// vehicle spells are handled by CMSG_PET_CAST_SPELL,
// but player is still able to cast own spells
if(_player->GetCharmGUID() && _player->GetCharmGUID() == _player->GetVehicleGUID())
mover = _player;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
if(!spellInfo)
{
sLog.outError("WORLD: unknown spell id %u", spellId);
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
if (mover->GetTypeId()==TYPEID_PLAYER)
{
// not have spell in spellbook or spell passive and not casted by client
if (!((Player*)mover)->HasActiveSpell (spellId) || IsPassiveSpell(spellInfo))
{
sLog.outError("World: Player %u casts spell %u which he shouldn't have", mover->GetGUIDLow(), spellId);
//cheater? kick? ban?
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
}
else
{
// not have spell in spellbook or spell passive and not casted by client
if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellInfo))
{
//cheater? kick? ban?
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
}
// client provided targets
SpellCastTargets targets;
recvPacket >> targets.ReadForCaster(mover);
// some spell cast packet including more data (for projectiles?)
if (unk_flags & 0x02)
{
uint8 unk1;
recvPacket >> Unused<float>(); // unk1, coords?
recvPacket >> Unused<float>(); // unk1, coords?
recvPacket >> unk1; // >> 1 or 0
if(unk1)
{
ObjectGuid guid; // guid - unused
MovementInfo movementInfo;
recvPacket >> Unused<uint32>(); // >> MSG_MOVE_STOP
recvPacket >> guid.ReadAsPacked();
recvPacket >> movementInfo;
}
}
示例13: Update
/// Update the WorldSession (triggered by World update)
bool WorldSession::Update(PacketFilter& updater)
{
///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed
WorldPacket* packet = NULL;
while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater))
{
/*#if 1
sLog.outError( "MOEP: %s (0x%.4X)",
LookupOpcodeName(packet->GetOpcode()),
packet->GetOpcode());
#endif*/
DEBUG_LOG("Received packet %u %s from %s", packet->GetOpcode(), LookupOpcodeName(packet->GetOpcode()), GetPlayer() ? GetPlayer()->GetGuidStr().c_str() : "<unknown>");
OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
try
{
if (GetPlayer())
DEBUG_LOG("Received packet %s (size %u) from %s", opHandle.name, packet->size(), GetPlayer()->GetGuidStr().c_str());
switch (opHandle.status)
{
case STATUS_LOGGEDIN:
if(!_player)
{
// skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
if(!m_playerRecentlyLogout)
LogUnexpectedOpcode(packet, "the player has not logged in yet");
}
else if(_player->IsInWorld())
ExecuteOpcode(opHandle, packet);
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
// playerbot mod
if (!sWorld.getConfig(CONFIG_BOOL_PLAYERBOT_DISABLE))
if (_player && _player->GetPlayerbotMgr())
_player->GetPlayerbotMgr()->HandleMasterIncomingPacket(*packet);
// playerbot mod end
break;
case STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT:
if(!_player && !m_playerRecentlyLogout)
{
LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout");
}
else
// not expected _player or must checked in packet hanlder
ExecuteOpcode(opHandle, packet);
break;
case STATUS_TRANSFER:
if(!_player)
LogUnexpectedOpcode(packet, "the player has not logged in yet");
else if(_player->IsInWorld())
LogUnexpectedOpcode(packet, "the player is still in world");
else
ExecuteOpcode(opHandle, packet);
break;
case STATUS_AUTHED:
// prevent cheating with skip queue wait
if(m_inQueue)
{
LogUnexpectedOpcode(packet, "the player not pass queue yet");
break;
}
// single from authed time opcodes send in to after logout time
// and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes.
if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL)
m_playerRecentlyLogout = false;
ExecuteOpcode(opHandle, packet);
break;
case STATUS_NEVER:
sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)",
LookupOpcodeName(packet->GetOpcode()),
packet->GetOpcode());
break;
case STATUS_UNHANDLED:
DEBUG_LOG("SESSION: received unhandled opcode %s (0x%.4X) (real value may be not shown there)",
LookupOpcodeName(packet->GetOpcode()),
packet->GetOpcode());
break;
default:
sLog.outError("SESSION: received wrong-status-req opcode %s (0x%.4X)",
LookupOpcodeName(packet->GetOpcode()),
packet->GetOpcode());
break;
}
}
catch (ByteBufferException &)
{
sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: 0x%.4X, %s) from client %s, accountid = %i.",
packet->GetOpcode(), LookupOpcodeName(packet->GetOpcode()), GetRemoteAddress().c_str(), GetAccountId());
if (sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
{
DEBUG_LOG("Dumping error causing packet:");
packet->hexlike();
}
//.........这里部分代码省略.........
示例14: SendPacket
int WorldSocket::SendPacket(WorldPacket const& pct)
{
ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1);
if (closing_)
return -1;
// Dump outgoing packet
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(pct, SERVER_TO_CLIENT);
WorldPacket const* pkt = &pct;
// Empty buffer used in case packet should be compressed
// Disable compression for now :)
/* WorldPacket buff;
if (m_Session && pkt->size() > 0x400)
{
buff.Compress(m_Session->GetCompressionStream(), pkt);
pkt = &buff;
}*/
if (m_Session)
TC_LOG_TRACE("network.opcode", "S->C: %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(pkt->GetOpcode()).c_str());
sScriptMgr->OnPacketSend(this, *pkt);
ServerPktHeader header(!m_Crypt.IsInitialized() ? pkt->size() + 2 : pct.size(), pkt->GetOpcode(), &m_Crypt);
if (m_OutBuffer->space() >= pkt->size() + header.getHeaderLength() && msg_queue()->is_empty())
{
// Put the packet on the buffer.
if (m_OutBuffer->copy((char*) header.header, header.getHeaderLength()) == -1)
ACE_ASSERT (false);
if (!pkt->empty())
if (m_OutBuffer->copy((char*) pkt->contents(), pkt->size()) == -1)
ACE_ASSERT (false);
}
else
{
// Enqueue the packet.
ACE_Message_Block* mb;
ACE_NEW_RETURN(mb, ACE_Message_Block(pkt->size() + header.getHeaderLength()), -1);
mb->copy((char*) header.header, header.getHeaderLength());
if (!pkt->empty())
mb->copy((const char*)pkt->contents(), pkt->size());
if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
{
TC_LOG_ERROR("network", "WorldSocket::SendPacket enqueue_tail failed");
mb->release();
return -1;
}
}
return 0;
}
示例15: HandleUseItemOpcode
void WorldSession::HandleUseItemOpcode(WorldPacket & recvPacket)
{
CHECK_INWORLD_RETURN
typedef std::list<Aura*> AuraList;
Player* p_User = GetPlayer();
LOG_DETAIL("WORLD: got use Item packet, data length = %i", recvPacket.size());
int8 tmp1, slot;
uint8 unk; //Alice : added in 3.0.2
uint64 item_guid;
uint8 cn;
uint32 spellId = 0;
uint32 glyphIndex;
bool found = false;
recvPacket >> tmp1;
recvPacket >> slot;
recvPacket >> cn;
recvPacket >> spellId;
recvPacket >> item_guid;
recvPacket >> glyphIndex;
recvPacket >> unk;
Item* tmpItem = NULL;
tmpItem = p_User->GetItemInterface()->GetInventoryItem(tmp1, slot);
if(!tmpItem)
tmpItem = p_User->GetItemInterface()->GetInventoryItem(slot);
if(!tmpItem)
return;
ItemPrototype* itemProto = tmpItem->GetProto();
// only some consumable items can be used in arenas
if( ( itemProto->Class == ITEM_CLASS_CONSUMABLE ) &&
!itemProto->HasFlag( ITEM_FLAG_USEABLE_IN_ARENA ) &&
( GetPlayer()->m_bg != NULL ) &&
IS_ARENA( GetPlayer()->m_bg->GetType() ) )
{
GetPlayer()->GetItemInterface()->BuildInventoryChangeError(tmpItem, NULL, INV_ERR_NOT_DURING_ARENA_MATCH);
return;
}
if(tmpItem->IsSoulbound()) // SouldBind item will be used after SouldBind()
{
if(sScriptMgr.CallScriptedItem(tmpItem, _player))
return;
}
if(_player->getDeathState() == CORPSE)
return;
if(itemProto->Bonding == ITEM_BIND_ON_USE)
tmpItem->SoulBind();
if(sScriptMgr.CallScriptedItem(tmpItem, _player))
return;
if(itemProto->InventoryType != 0 && !_player->GetItemInterface()->IsEquipped(itemProto->ItemId)) //Equipable items cannot be used before they're equipped. Prevents exploits
return;//Prevents exploits such as keeping an on-use trinket in your bag and using WPE to use it from your bag in mid-combat.
if(itemProto->QuestId)
{
// Item Starter
Quest* qst = QuestStorage.LookupEntry(itemProto->QuestId);
if(!qst)
return;
WorldPacket data;
sQuestMgr.BuildQuestDetails(&data, qst, tmpItem, 0, language, _player);
SendPacket(&data);
}
// Let's check if the item even has that spell
for(int i = 0; i < 5; ++i)
{
if(itemProto->Spells[i].Trigger == USE && itemProto->Spells[i].Id == spellId)
{
found = true;
break;//found 1 already
}
}
// Let's see if it is an onuse spellid
if(tmpItem->HasOnUseSpellID(spellId))
found = true;
// We didn't find the spell, so the player is probably trying to cheat
// with an edited itemcache.wdb
//
// Altough this could also happen after a DB update
// if he/she didn't delete his/her cache.
if(found == false)
{
this->Disconnect();
Anticheat_Log->writefromsession(this, "Player tried to use an item with a spell that didn't match the spell in the database.");
Anticheat_Log->writefromsession(this, "Possibly corrupted or intentionally altered itemcache.wdb");
Anticheat_Log->writefromsession(this, "Itemid: %lu", itemProto->ItemId);
Anticheat_Log->writefromsession(this, "Spellid: %lu", spellId);
Anticheat_Log->writefromsession(this, "Player was disconnected");
//.........这里部分代码省略.........