/// %Realm List command handler bool AuthSocket::_HandleRealmList() { DEBUG_LOG("Entering _HandleRealmList"); if (ibuf.GetLength() < 5) return false; ibuf.Remove(5); ///- Get the user id (else close the connection) // No SQL injection (escaped user name) QueryResult *result = loginDatabase.PQuery("SELECT id,sha_pass_hash FROM account WHERE username = '******'",_safelogin.c_str()); if (!result) { sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str()); SetCloseAndDelete(); return false; } uint32 id = (*result)[0].GetUInt32(); std::string rI = (*result)[1].GetCppString(); delete result; ///- Update realm list if need m_realmList.UpdateIfNeed(); RealmList::RealmMap::const_iterator rlm; RealmList built_realmList; for (rlm = m_realmList.begin(); rlm != m_realmList.end(); ++rlm) { if ( _expversion & POST_BC_EXP_FLAG )//2.4.3 and 3.1.3 cliens { if (rlm->second.gamebuild == _build) built_realmList.AddRealm(rlm->second); } else if ( _expversion & PRE_BC_EXP_FLAG )//1.12.1 and 1.12.2 clients are compatible with eachother { if ( AuthHelper::IsPreBCAcceptedClientBuild ( rlm->second.gamebuild ) ) built_realmList.AddRealm(rlm->second); } } ///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) ByteBuffer pkt; pkt << (uint32) 0; if ( _expversion & POST_BC_EXP_FLAG )//only 2.4.3 and 3.1.3 cliens pkt << (uint16) built_realmList.size(); else pkt << (uint32) built_realmList.size(); RealmList::RealmMap::const_iterator i; for (i = built_realmList.begin(); i != built_realmList.end(); ++i) { uint8 AmountOfCharacters; // No SQL injection. id of realm is controlled by the database. result = loginDatabase.PQuery("SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); if (result) { Field *fields = result->Fetch(); AmountOfCharacters = fields[0].GetUInt8(); delete result; } else AmountOfCharacters = 0; uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; pkt << i->second.icon; // realm type if ( _expversion & POST_BC_EXP_FLAG )//only 2.4.3 and 3.1.3 cliens pkt << lock; // if 1, then realm locked pkt << i->second.color; // if 2, then realm is offline pkt << i->first; pkt << i->second.address; pkt << i->second.populationLevel; pkt << AmountOfCharacters; pkt << i->second.timezone; // realm category if ( _expversion & POST_BC_EXP_FLAG )//2.4.3 and 3.1.3 clients pkt << (uint8) 0x2C; // unk, may be realm number/id? else pkt << (uint8) 0x0; //1.12.1 and 1.12.2 clients } if ( _expversion & POST_BC_EXP_FLAG )//2.4.3 and 3.1.3 cliens { pkt << (uint8) 0x10; pkt << (uint8) 0x00; }else{//1.12.1 and 1.12.2 clients pkt << (uint8) 0x00; pkt << (uint8) 0x02; } ByteBuffer hdr; hdr << (uint8) REALM_LIST; hdr << (uint16)pkt.size(); hdr.append(pkt); SendBuf((char const*)hdr.contents(), hdr.size()); return true; }
void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) { DEBUG_LOG( "WORLD: SendTrainerList" ); Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TRAINER); if (!unit) { DEBUG_LOG("WORLD: SendTrainerList - %s not found or you can't interact with him.", guid.GetString().c_str()); return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); // trainer list loaded at check; if (!unit->IsTrainerOf(_player,true)) return; CreatureInfo const *ci = unit->GetCreatureInfo(); if (!ci) return; TrainerSpellData const* cSpells = unit->GetTrainerSpells(); TrainerSpellData const* tSpells = unit->GetTrainerTemplateSpells(); if (!cSpells && !tSpells) { DEBUG_LOG("WORLD: SendTrainerList - Training spells not found for %s", guid.GetString().c_str()); return; } uint32 maxcount = (cSpells ? cSpells->spellList.size() : 0) + (tSpells ? tSpells->spellList.size() : 0); uint32 trainer_type = cSpells && cSpells->trainerType ? cSpells->trainerType : (tSpells ? tSpells->trainerType : 0); WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+maxcount*38 + strTitle.size()+1); data << ObjectGuid(guid); data << uint32(trainer_type); size_t count_pos = data.wpos(); data << uint32(maxcount); // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; uint32 count = 0; if (cSpells) { for(TrainerSpellMap::const_iterator itr = cSpells->spellList.begin(); itr != cSpells->spellList.end(); ++itr) { TrainerSpell const* tSpell = &itr->second; uint32 reqLevel = 0; if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &reqLevel)) continue; reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel); TrainerSpellState state = _player->GetTrainerSpellState(tSpell, reqLevel); SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, reqLevel); ++count; } } if (tSpells) { for(TrainerSpellMap::const_iterator itr = tSpells->spellList.begin(); itr != tSpells->spellList.end(); ++itr) { TrainerSpell const* tSpell = &itr->second; uint32 reqLevel = 0; if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &reqLevel)) continue; reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel); TrainerSpellState state = _player->GetTrainerSpellState(tSpell, reqLevel); SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, reqLevel); ++count; } } data << strTitle; data.put<uint32>(count_pos,count); SendPacket(&data); }
void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; DEBUG_LOG(SCEDISPLAY, "Enter VBlank %i", vbCount); isVblank = 1; vCount++; // vCount increases at each VBLANK. hCountBase += hCountPerVblank; // This is the "accumulated" hcount base. if (hCountBase > 0x7FFFFFFF) { hCountBase -= 0x80000000; } frameStartTicks = CoreTiming::GetTicks(); // Wake up threads waiting for VBlank u32 error; for (size_t i = 0; i < vblankWaitingThreads.size(); i++) { if (--vblankWaitingThreads[i].vcountUnblock == 0) { // Only wake it if it wasn't already released by someone else. SceUID waitID = __KernelGetWaitID(vblankWaitingThreads[i].threadID, WAITTYPE_VBLANK, error); if (waitID == 1) { __KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0); } vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i--); } } // Trigger VBlank interrupt handlers. __TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL); CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1); gpuStats.numVBlanks++; numVBlanksSinceFlip++; // TODO: Should this be done here or in hleLeaveVblank? if (framebufIsLatched) { DEBUG_LOG(SCEDISPLAY, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr); framebuf = latchedFramebuf; framebufIsLatched = false; gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); } // We flip only if the framebuffer was dirty. This eliminates flicker when using // non-buffered rendering. The interaction with frame skipping seems to need // some work. if (gpu->FramebufferDirty()) { if (g_Config.iShowFPSCounter && g_Config.iShowFPSCounter < 4) { CalculateFPS(); } // Setting CORE_NEXTFRAME causes a swap. // Check first though, might've just quit / been paused. if (gpu->FramebufferReallyDirty()) { if (coreState == CORE_RUNNING) { coreState = CORE_NEXTFRAME; gpu->CopyDisplayToOutput(); actualFlips++; } } gpuStats.numFlips++; bool throttle, skipFrame; // 1.001f to compensate for the classic 59.94 NTSC framerate that the PSP seems to have. DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * (1.001f / 60.0f)); int maxFrameskip = 8; if (throttle) { if (g_Config.iFrameSkip == 1) { // 4 here means 1 drawn, 4 skipped - so 12 fps minimum. maxFrameskip = 4; } else { maxFrameskip = g_Config.iFrameSkip - 1; } } if (numSkippedFrames >= maxFrameskip) { skipFrame = false; } if (skipFrame) { gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME; numSkippedFrames++; } else { gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME; numSkippedFrames = 0; } // Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame). // Right after, we regain control for a little bit in hleAfterFlip. I think that's a great // place to do housekeeping. CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); numVBlanksSinceFlip = 0; } }
void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recv_data) { ObjectGuid guid; uint32 quest; recv_data >> guid >> quest; if (!CanInteractWithQuestGiver(guid, "CMSG_QUESTGIVER_ACCEPT_QUEST")) return; DEBUG_LOG("WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST - for %s to %s, quest = %u", _player->GetGuidStr().c_str(), guid.GetString().c_str(), quest); Object* pObject = _player->GetObjectByTypeMask(guid, TYPEMASK_CREATURE_GAMEOBJECT_PLAYER_OR_ITEM); // no or incorrect quest giver if (!pObject || (pObject->GetTypeId() != TYPEID_PLAYER && !pObject->HasQuest(quest)) || (pObject->GetTypeId() == TYPEID_PLAYER && !((Player*)pObject)->CanShareQuest(quest)) ) { _player->PlayerTalkClass->CloseGossip(); _player->ClearDividerGuid(); return; } Quest const* qInfo = sObjectMgr.GetQuestTemplate(quest); if (qInfo) { // prevent cheating if (!GetPlayer()->CanTakeQuest(qInfo, true)) { _player->PlayerTalkClass->CloseGossip(); _player->ClearDividerGuid(); return; } if (Player* pPlayer = ObjectAccessor::FindPlayer(_player->GetDividerGuid())) { pPlayer->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); _player->ClearDividerGuid(); } if (_player->CanAddQuest(qInfo, true)) { _player->AddQuest(qInfo, pObject); // pObject (if it item) can be destroyed at call if (qInfo->HasQuestFlag(QUEST_FLAGS_PARTY_ACCEPT)) { if (Group* pGroup = _player->GetGroup()) { for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pPlayer = itr->getSource(); if (!pPlayer || pPlayer == _player) // not self continue; if (pPlayer->CanTakeQuest(qInfo, true)) { pPlayer->SetDividerGuid(_player->GetObjectGuid()); // need confirmation that any gossip window will close pPlayer->PlayerTalkClass->CloseGossip(); _player->SendQuestConfirmAccept(qInfo, pPlayer); } } } } if (_player->CanCompleteQuest(quest)) _player->CompleteQuest(quest); _player->PlayerTalkClass->CloseGossip(); if (qInfo->GetSrcSpell() > 0) _player->CastSpell(_player, qInfo->GetSrcSpell(), true); return; } } _player->PlayerTalkClass->CloseGossip(); }
void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPacket& /*recvPacket*/) { DEBUG_LOG("WORLD: Received CMSG_QUESTGIVER_QUEST_AUTOLAUNCH"); }
void sceKernelSetGPO(u32 ledAddr) { // Sets debug LEDs. DEBUG_LOG(HLE,"sceKernelSetGPO(%02x)", ledAddr); }
int sceKernelIcacheInvalidateRange(u32 addr, int size) { DEBUG_LOG(HLE,"sceKernelIcacheInvalidateRange(%08x, %i)", addr, size); // TODO: Make the JIT hash and compare the touched blocks. return 0; }
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_BATTLEFIELD_PORT"); uint8 type; // arenatype if arena uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 uint32 bgTypeId_; // type id from dbc uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action; if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog.outError("BattlegroundHandler: invalid bgtype (%u) received.", bgTypeId_); return; } if (type && !IsArenaTypeValid(ArenaType(type))) { sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), arena type wrong: %u.", _player->GetGUIDLow(), type); return; } if (!_player->InBattleGroundQueue()) { sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player->GetGUIDLow()); return; } // get GroupQueueInfo from BattleGroundQueue BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, ArenaType(type)); BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; // we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function GroupQueueInfo ginfo; if (!bgQueue.GetPlayerGroupInfoData(_player->GetObjectGuid(), &ginfo)) { sLog.outError("BattlegroundHandler: itrplayerstatus not found."); return; } // if action == 1, then instanceId is required if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) { sLog.outError("BattlegroundHandler: instance not found."); return; } BattleGround* bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); // bg template might and must be used in case of leaving queue, when instance is not created yet if (!bg && action == 0) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) { sLog.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); return; } // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; // some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it if (action == 1 && ginfo.arenaType == ARENA_TYPE_NONE) { // if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue if (!_player->CanJoinToBattleground()) { // send bg command result to show nice message WorldPacket data2; sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->GetSession()->SendPacket(&data2); action = 0; DEBUG_LOG("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); } // if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue if (_player->getLevel() > bg->GetMaxLevel()) { sLog.outError("Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID()); action = 0; } } uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); WorldPacket data; switch (action) { case 1: // port to battleground if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) return; // cheating? if (!_player->InBattleGround()) _player->SetBattleGroundEntryPoint(); // resurrect the player if (!_player->isAlive()) { _player->ResurrectPlayer(1.0f); _player->SpawnCorpseBones(); } // stop taxi flight at port if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->m_taxi.ClearTaxiDestinations(); } sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), _player->GetBGTeam()); _player->GetSession()->SendPacket(&data); // remove battleground queue status from BGmgr bgQueue.RemovePlayer(_player->GetObjectGuid(), false); // this is still needed here if battleground "jumping" shouldn't add deserter debuff // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new if (BattleGround* currentBg = _player->GetBattleGround()) currentBg->RemovePlayerAtLeave(_player->GetObjectGuid(), false, true); // set the destination instance id _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId); // set the destination team _player->SetBGTeam(ginfo.GroupTeam); // bg->HandleBeforeTeleportToBattleGround(_player); sBattleGroundMgr.SendToBattleGround(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); // add only in HandleMoveWorldPortAck() // bg->AddPlayer(_player,team); DEBUG_LOG("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId); break; case 0: // leave queue // if player leaves rated arena match before match start, it is counted as he played but he lost if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID) { ArenaTeam* at = sObjectMgr.GetArenaTeamById(ginfo.ArenaTeamId); if (at) { DEBUG_LOG("UPDATING memberLost's personal arena rating for %s by opponents rating: %u, because he has left queue!", _player->GetGuidStr().c_str(), ginfo.OpponentsTeamRating); at->MemberLost(_player, ginfo.OpponentsTeamRating); at->SaveToDB(); } } _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, ARENA_TYPE_NONE, TEAM_NONE); bgQueue.RemovePlayer(_player->GetObjectGuid(), true); // player left queue, we should update it - do not update Arena Queue if (ginfo.arenaType == ARENA_TYPE_NONE) sBattleGroundMgr.ScheduleQueueUpdate(ginfo.ArenaTeamRating, ginfo.arenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); SendPacket(&data); DEBUG_LOG("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId); break; default: sLog.outError("Battleground port: unknown action %u", action); break; } }
void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket& /*recv_data*/) { // empty opcode DEBUG_LOG("WORLD: Battleground status"); WorldPacket data; // we must update all queues here BattleGround* bg = NULL; for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) { BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); if (!bgQueueTypeId) continue; BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); ArenaType arenaType = BattleGroundMgr::BGArenaType(bgQueueTypeId); // bgTypeId is always BATTLEGROUND_AA for arena whereas GetBattleGroundTypeId() is the actual arena map type if (bgTypeId == _player->GetBattleGroundTypeId() || (bgTypeId == BATTLEGROUND_AA && sBattleGroundMgr.IsArenaType(_player->GetBattleGroundTypeId()))) { bg = _player->GetBattleGround(); // i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena // so i must use bg pointer to get that information if (bg && bg->GetArenaType() == arenaType) { // this line is checked, i only don't know if GetStartTime is changing itself after bg end! // send status in BattleGround sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType, _player->GetBGTeam()); SendPacket(&data); continue; } } // we are sending update to player about queue - he can be invited there! // get GroupQueueInfo for queue status BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; GroupQueueInfo ginfo; if (!bgQueue.GetPlayerGroupInfoData(_player->GetObjectGuid(), &ginfo)) continue; if (ginfo.IsInvitedToBGInstanceGUID) { bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); if (!bg) continue; uint32 remainingTime = WorldTimer::getMSTimeDiff(WorldTimer::getMSTime(), ginfo.RemoveInviteTime); // send status invited to BattleGround sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType, TEAM_NONE); SendPacket(&data); } else { bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) continue; // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) continue; uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId()); // send status in BattleGround Queue sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, WorldTimer::getMSTimeDiff(ginfo.JoinTime, WorldTimer::getMSTime()), arenaType, TEAM_NONE); SendPacket(&data); } } }
void WorldSession::Handle_NULL(WorldPacket& recvPacket) { DEBUG_LOG("SESSION: received unimplemented opcode %s (0x%.4X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode()); }
void WorldSession::HandleBattleGroundPlayerPositionsOpcode(WorldPacket& /*recv_data*/) { // empty opcode DEBUG_LOG("WORLD: Received opcode MSG_BATTLEGROUND_PLAYER_POSITIONS"); BattleGround* bg = _player->GetBattleGround(); if (!bg) // can't be received if player not in battleground return; switch (bg->GetTypeID()) { case BATTLEGROUND_WS: { uint32 flagCarrierCount = 0; Player* flagCarrierAlliance = sObjectMgr.GetPlayer(((BattleGroundWS*)bg)->GetAllianceFlagCarrierGuid()); if (flagCarrierAlliance) ++flagCarrierCount; Player* flagCarrierHorde = sObjectMgr.GetPlayer(((BattleGroundWS*)bg)->GetHordeFlagCarrierGuid()); if (flagCarrierHorde) ++flagCarrierCount; WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, 4 + 4 + 16 * flagCarrierCount); data << uint32(0); data << uint32(flagCarrierCount); if (flagCarrierAlliance) { data << flagCarrierAlliance->GetObjectGuid(); data << float(flagCarrierAlliance->GetPositionX()); data << float(flagCarrierAlliance->GetPositionY()); } if (flagCarrierHorde) { data << flagCarrierHorde->GetObjectGuid(); data << float(flagCarrierHorde->GetPositionX()); data << float(flagCarrierHorde->GetPositionY()); } SendPacket(&data); break; } case BATTLEGROUND_EY: { uint32 flagCarrierCount = 0; Player* flagCarrier = sObjectMgr.GetPlayer(((BattleGroundEY*)bg)->GetFlagCarrierGuid()); if (flagCarrier) flagCarrierCount = 1; WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, 4 + 4 + 16 * flagCarrierCount); data << uint32(0); data << uint32(flagCarrierCount); if (flagCarrier) { data << flagCarrier->GetObjectGuid(); data << float(flagCarrier->GetPositionX()); data << float(flagCarrier->GetPositionY()); } SendPacket(&data); break; } case BATTLEGROUND_AB: case BATTLEGROUND_AV: { // for other BG types - send default WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, 4 + 4); data << uint32(0); data << uint32(0); SendPacket(&data); break; } default: // maybe it is sent also in arena - do nothing break; } }
/// %Log the player out void WorldSession::LogoutPlayer(bool Save) { // finish pending transfers before starting the logout while (_player && _player->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); m_playerLogout = true; m_playerSave = Save; if (_player) { sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (guid: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() , _player->GetGUIDLow()); if (ObjectGuid lootGuid = GetPlayer()->GetLootGuid()) DoLootRelease(lootGuid); ///- If the player just died before logging out, make him appear as a ghost // FIXME: logout must be delayed in case lost connection with client in time of combat if (_player->GetDeathTimer()) { _player->getHostileRefManager().deleteReferences(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } else if (!_player->getAttackers().empty()) { _player->CombatStop(); _player->getHostileRefManager().setOnlineOfflineState(false); _player->RemoveAllAurasOnDeath(); // build set of player who attack _player or who have pet attacking of _player std::set<Player*> aset; for (Unit::AttackerSet::const_iterator itr = _player->getAttackers().begin(); itr != _player->getAttackers().end(); ++itr) { Unit* owner = (*itr)->GetOwner(); // including player controlled case if (owner) { if (owner->GetTypeId() == TYPEID_PLAYER) aset.insert((Player*)owner); } else if ((*itr)->GetTypeId() == TYPEID_PLAYER) aset.insert((Player*)(*itr)); } _player->SetPvPDeath(!aset.empty()); _player->KillPlayer(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); // give honor to all attackers from set like group case for (std::set<Player*>::const_iterator itr = aset.begin(); itr != aset.end(); ++itr) (*itr)->RewardHonor(_player, aset.size()); // give bg rewards and update counters like kill by first from attackers // this can't be called for all attackers. if (!aset.empty()) if (BattleGround* bg = _player->GetBattleGround()) bg->HandleKillPlayer(_player, *aset.begin()); } else if (_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) { // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION _player->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); //_player->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time _player->KillPlayer(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } // drop a flag if player is carrying it if (BattleGround* bg = _player->GetBattleGround()) bg->EventPlayerLoggedOut(_player); ///- Teleport to home if the player is in an invalid instance if (!_player->m_InstanceValid && !_player->isGameMaster()) { _player->TeleportToHomebind(); // this is a bad place to call for far teleport because we need player to be in world for successful logout // maybe we should implement delayed far teleport logout? } // FG: finish pending transfers after starting the logout // this should fix players beeing able to logout and login back with full hp at death position while (_player->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) { if (BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i)) { _player->RemoveBattleGroundQueueId(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(_player->GetObjectGuid(), true); } } ///- Reset the online field in the account table // no point resetting online in character table here as Player::SaveToDB() will set it to 1 since player has not been removed from world at this stage // No SQL injection as AccountID is uint32 static SqlStatementID id; SqlStatement stmt = LoginDatabase.CreateStatement(id, "UPDATE account SET active_realm_id = ? WHERE id = ?"); stmt.PExecute(uint32(0), GetAccountId()); ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members if (Guild* guild = sGuildMgr.GetGuildById(_player->GetGuildId())) { if (MemberSlot* slot = guild->GetMemberSlot(_player->GetObjectGuid())) { slot->SetMemberStats(_player); slot->UpdateLogoutTime(); } guild->BroadcastEvent(GE_SIGNED_OFF, _player->GetObjectGuid(), _player->GetName()); } ///- Remove pet _player->RemovePet(PET_SAVE_AS_CURRENT); ///- empty buyback items and save the player in the database // some save parts only correctly work in case player present in map/player_lists (pets, etc) if (Save) _player->SaveToDB(); ///- Leave all channels before player delete... _player->CleanupChannels(); ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. _player->UninviteFromGroup(); // remove player from the group if he is: // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket) _player->RemoveFromGroup(); ///- Send update to group if (_player->GetGroup()) _player->GetGroup()->SendUpdate(); ///- Broadcast a logout message to the player's friends sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetObjectGuid(), true); sSocialMgr.RemovePlayerSocial(_player->GetGUIDLow()); ///- Remove the player from the world // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes if (_player->IsInWorld()) { Map* _map = _player->GetMap(); _map->Remove(_player, true); } else { _player->CleanupsBeforeDelete(); Map::DeleteFromWorld(_player); } SetPlayer(NULL); // deleted in Remove/DeleteFromWorld call ///- Send the 'logout complete' packet to the client WorldPacket data(SMSG_LOGOUT_COMPLETE, 0); SendPacket(&data); ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline // No SQL injection as AccountId is uint32 static SqlStatementID updChars; stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 0 WHERE account = ?"); stmt.PExecute(GetAccountId()); DEBUG_LOG("SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); } m_playerLogout = false; m_playerSave = false; m_playerRecentlyLogout = true; LogoutRequest(0); }
/// 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)", packet->GetOpcodeName(), 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 { 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 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)", packet->GetOpcodeName(), packet->GetOpcode()); break; case STATUS_UNHANDLED: DEBUG_LOG("SESSION: received not handled opcode %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; default: sLog.outError("SESSION: received wrong-status-req opcode %s (0x%.4X)", packet->GetOpcodeName(), packet->GetOpcode()); break; } } catch (ByteBufferException&) { sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); if (sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) { DEBUG_LOG("Dumping error causing packet:"); packet->hexlike(); } if (sWorld.getConfig(CONFIG_BOOL_KICK_PLAYER_ON_BAD_PACKET)) { DETAIL_LOG("Disconnecting session [account id %u / address %s] for badly formatted packet.", GetAccountId(), GetRemoteAddress().c_str()); KickPlayer(); } } delete packet; } ///- Cleanup socket pointer if need if (m_Socket && m_Socket->IsClosed()) { m_Socket->RemoveReference(); m_Socket = NULL; } // check if we are safe to proceed with logout // logout procedure should happen only in World::UpdateSessions() method!!! if (updater.ProcessLogout()) { ///- If necessary, log the player out time_t currTime = time(NULL); if (!m_Socket || (ShouldLogOut(currTime) && !m_playerLoading)) LogoutPlayer(true); if (!m_Socket) return false; // Will remove this session from the world session map } return true; }
CreatureAI* selectAI(Creature* creature) { const CreatureAICreator *ai_factory = NULL; CreatureAIRegistry &ai_registry(CreatureAIRepository::Instance()); if (creature->isPet()) ai_factory = ai_registry.GetRegistryItem("PetAI"); //scriptname in db if (!ai_factory) if (CreatureAI* scriptedAI = sScriptMgr.GetAI(creature)) return scriptedAI; // AIname in db std::string ainame=creature->GetAIName(); if (!ai_factory && !ainame.empty()) ai_factory = ai_registry.GetRegistryItem(ainame.c_str()); // select by NPC flags if (!ai_factory) { if (creature->HasSummonMask(SUMMON_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER) ai_factory = ai_registry.GetRegistryItem("PetAI"); else if (creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) ai_factory = ai_registry.GetRegistryItem("NullCreatureAI"); else if (creature->isGuard()) ai_factory = ai_registry.GetRegistryItem("GuardAI"); else if (creature->HasSummonMask(SUMMON_MASK_CONTROLABLE_GUARDIAN)) ai_factory = ai_registry.GetRegistryItem("PetAI"); else if (creature->isTotem()) ai_factory = ai_registry.GetRegistryItem("TotemAI"); else if (creature->isTrigger()) { if (creature->m_spells[0]) ai_factory = ai_registry.GetRegistryItem("TriggerAI"); else ai_factory = ai_registry.GetRegistryItem("NullCreatureAI"); } else if (creature->GetCreatureType() == CREATURE_TYPE_CRITTER && !creature->HasSummonMask(SUMMON_MASK_GUARDIAN)) ai_factory = ai_registry.GetRegistryItem("CritterAI"); } // select by permit check if (!ai_factory) { int best_val = -1; typedef CreatureAIRegistry::RegistryMapType RMT; RMT const &l = ai_registry.GetRegisteredItems(); for (RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter) { const CreatureAICreator *factory = iter->second; const SelectableAI *p = dynamic_cast<const SelectableAI *>(factory); ASSERT(p != NULL); int val = p->Permit(creature); if (val > best_val) { best_val = val; ai_factory = p; } } } // select NullCreatureAI if not another cases ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key(); DEBUG_LOG("Creature %u used AI is %s.", creature->GetGUIDLow(), ainame.c_str()); return (ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature)); }
int main(int argc, char *argv[]) { #ifdef _NEED_WIN_GENERATE_DUMP _oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter); #endif InitOpenSSL _init; settingsParseArgs(argc, argv); for (int32 i = 0; i < argc; ++i) { if (string("-fixprevious") == argv[i]) { return psFixPrevious(); } else if (string("-cleanup") == argv[i]) { return psCleanup(); } } logsInit(); Local::readSettings(); if (cFromAutoStart() && !cAutoStart()) { psAutoStart(false, true); Local::stop(); return 0; } DEBUG_LOG(("Application Info: Telegram started, test mode: %1, exe dir: %2").arg(logBool(cTestMode())).arg(cExeDir())); if (cDebug()) { LOG(("Application Info: Telegram started in debug mode")); for (int32 i = 0; i < argc; ++i) { LOG(("Argument: %1").arg(QString::fromLocal8Bit(argv[i]))); } QStringList logs = psInitLogs(); for (int32 i = 0, l = logs.size(); i < l; ++i) { LOG(("Init Log: %1").arg(logs.at(i))); } } psClearInitLogs(); DEBUG_LOG(("Application Info: ideal thread count: %1, using %2 connections per session").arg(QThread::idealThreadCount()).arg(cConnectionsInSession())); psStart(); int result = 0; { QByteArray args[] = { "-style=0" }; // prepare fake args static const int a_cnt = sizeof(args) / sizeof(args[0]); int a_argc = a_cnt + 1; char *a_argv[a_cnt + 1] = { argv[0], args[0].data() }; Application app(a_argc, a_argv); if (!App::quiting()) { result = app.exec(); } } psFinish(); Local::stop(); DEBUG_LOG(("Application Info: Telegram done, result: %1").arg(result)); if (cRestartingUpdate()) { DEBUG_LOG(("Application Info: executing updater to install update..")); psExecUpdater(); } else if (cRestarting()) { DEBUG_LOG(("Application Info: executing Telegram, because of restart..")); psExecTelegram(); } logsClose(); return result; }
void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recv_data) { DEBUG_LOG("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); // recv_data.hexlike(); ObjectGuid guid; // arena Battlemaster guid uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated recv_data >> guid >> arenaslot >> asGroup >> isRated; // ignore if we already in BG or BG queue if (_player->InBattleGround()) return; Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if (!unit->isBattleMaster()) // it's not battle master return; ArenaType arenatype; uint32 arenaRating = 0; switch (arenaslot) { case 0: arenatype = ARENA_TYPE_2v2; break; case 1: arenatype = ARENA_TYPE_3v3; break; case 2: arenatype = ARENA_TYPE_5v5; break; default: sLog.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); return; } // check existence BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA); if (!bg) { sLog.outError("Battleground: template bg (all arenas) not found"); return; } BattleGroundTypeId bgTypeId = bg->GetTypeID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err; Group* grp = NULL; // check queue conditions if (!asGroup) { // you can't join in this way by client if (isRated) return; // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGuid() != _player->GetObjectGuid()) return; // may be Group::CanJoinBattleGroundQueue should be moved to player class... err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); } uint32 ateamId = 0; if (isRated) { ateamId = _player->GetArenaTeamId(arenaslot); // check real arena team existence only here (if it was moved to group->CanJoin .. () then we would have to get it twice) ArenaTeam* at = sObjectMgr.GetArenaTeamById(ateamId); if (!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queue arenaRating = at->GetRating(); // the arena team id must match for everyone in the group // get the personal ratings for queue uint32 avg_pers_rating = 0; for (Group::member_citerator citr = grp->GetMemberSlots().begin(); citr != grp->GetMemberSlots().end(); ++citr) { ArenaTeamMember const* at_member = at->GetMember(citr->guid); if (!at_member) // group member joining to arena must be in leader arena team return; // calc avg personal rating avg_pers_rating += at_member->personal_rating; } avg_pers_rating /= grp->GetMembersCount(); // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating if (avg_pers_rating + 150 < arenaRating) arenaRating = avg_pers_rating; } BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (asGroup) { uint32 avgTime = 0; if (err > 0) { DEBUG_LOG("Battleground: arena join as group start"); if (isRated) DEBUG_LOG("Battleground: arena team id %u, leader %s queued with rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName(), arenaRating, arenatype); // set arena rated type to show correct minimap arena icon bg->SetRated(isRated); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; WorldPacket data; if (err <= 0) { sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype, TEAM_NONE); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName(), member->GetBGTeam()); } DEBUG_LOG("Battleground: arena join as group end"); } else { GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype, TEAM_NONE); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(arenaRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia) { Corpse *corpse = GetCorpseForPlayerGUID(player_guid); if(!corpse) { //in fact this function is called from several places //even when player doesn't have a corpse, not an error //sLog.outError("Try remove corpse that not in map for GUID %ul", player_guid); return NULL; } DEBUG_LOG("Deleting Corpse and spawning bones."); // remove corpse from player_guid -> corpse map RemoveCorpse(corpse); // remove resurrectable corpse from grid object registry (loaded state checked into call) // do not load the map if it's not loaded Map *map = MapManager::Instance().FindMap(corpse->GetMapId(), corpse->GetInstanceId()); if(map) map->Remove(corpse, false); // remove corpse from DB corpse->DeleteFromDB(); Corpse *bones = NULL; // create the bones only if the map and the grid is loaded at the corpse's location // ignore bones creating option in case insignia if (map && (insignia || (map->IsBattleGroundOrArena() ? sWorld.getConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld.getConfig(CONFIG_DEATH_BONES_WORLD))) && !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) { // Create bones, don't change Corpse bones = new Corpse; bones->Create(corpse->GetGUIDLow()); for (int i = 3; i < CORPSE_END; ++i) // don't overwrite guid and object type bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); bones->SetGrid(corpse->GetGrid()); // bones->m_time = m_time; // don't overwrite time // bones->m_inWorld = m_inWorld; // don't overwrite world state // bones->m_type = m_type; // don't overwrite type bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); bones->SetPhaseMask(corpse->GetPhaseMask(), false); bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0); for (int i = 0; i < EQUIPMENT_SLOT_END; ++i) { if(corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); } // add bones in grid store if grid loaded where corpse placed map->Add(bones); } // all references to the corpse should be removed at this point delete corpse; return bones; }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recv_data) { ObjectGuid guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group* grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUIDLow()); return; } BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); DEBUG_LOG("WORLD: Received opcode CMSG_BATTLEMASTER_JOIN from %s", guid.GetString().c_str()); // can do this, since it's battleground, not arena BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, ARENA_TYPE_NONE); // ignore if player is already in BG if (_player->InBattleGround()) return; // get bg instance or bg template if instance not found BattleGround* bg = NULL; if (instanceId) bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); if (!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err; // check queue conditions if (!joinAsGroup) { // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data; sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGuid() != _player->GetObjectGuid()) return; err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH) && (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); } // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (joinAsGroup) { GroupQueueInfo* ginfo = NULL; uint32 avgTime = 0; if (err > 0) { DEBUG_LOG("Battleground: the following players are joining as group:"); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, ARENA_TYPE_NONE, false, isPremade, 0); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; // this should never happen WorldPacket data; if (err <= 0) { sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->arenaType, TEAM_NONE); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName(), member->GetBGTeam()); } DEBUG_LOG("Battleground: group end"); } else { GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, ARENA_TYPE_NONE, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->arenaType, TEAM_NONE); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(0, ARENA_TYPE_NONE, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
u32 sceKernelGetGPI() { // Always returns 0 on production systems. DEBUG_LOG(HLE,"0=sceKernelGetGPI()"); return 0; }
void Write32(const u32 _iValue, const u32 _iAddress) { DEBUG_LOG(DVDINTERFACE, "(w32): 0x%08x @ 0x%08x", _iValue, _iAddress); switch (_iAddress & 0xFF) { case DI_STATUS_REGISTER: { UDISR tmpStatusReg(_iValue); m_DISR.DEINITMASK = tmpStatusReg.DEINITMASK; m_DISR.TCINTMASK = tmpStatusReg.TCINTMASK; m_DISR.BRKINTMASK = tmpStatusReg.BRKINTMASK; m_DISR.BREAK = tmpStatusReg.BREAK; if (tmpStatusReg.DEINT) m_DISR.DEINT = 0; if (tmpStatusReg.TCINT) m_DISR.TCINT = 0; if (tmpStatusReg.BRKINT) m_DISR.BRKINT = 0; if (m_DISR.BREAK) { _dbg_assert_(DVDINTERFACE, 0); } UpdateInterrupts(); } break; case DI_COVER_REGISTER: { UDICVR tmpCoverReg(_iValue); m_DICVR.CVRINTMASK = tmpCoverReg.CVRINTMASK; if (tmpCoverReg.CVRINT) m_DICVR.CVRINT = 0; UpdateInterrupts(); } break; case DI_COMMAND_0: m_DICMDBUF[0].Hex = _iValue; break; case DI_COMMAND_1: m_DICMDBUF[1].Hex = _iValue; break; case DI_COMMAND_2: m_DICMDBUF[2].Hex = _iValue; break; case DI_DMA_ADDRESS_REGISTER: { m_DIMAR.Hex = _iValue & ~0xfc00001f; } break; case DI_DMA_LENGTH_REGISTER: { m_DILENGTH.Hex = _iValue & ~0x1f; } break; case DI_DMA_CONTROL_REGISTER: { m_DICR.Hex = _iValue & 7; if (m_DICR.TSTART) { if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bFastDiscSpeed) { u64 ticksUntilTC = m_DILENGTH.Length * (SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii?DISC_TRANSFER_RATE_WII:DISC_TRANSFER_RATE_GC)) + (SystemTimers::GetTicksPerSecond() * DISC_ACCESS_TIME_MS / 1000); CoreTiming::ScheduleEvent((int)ticksUntilTC, tc); } else { ExecuteCommand(m_DICR); } } } break; case DI_IMMEDIATE_DATA_BUFFER: m_DIIMMBUF.Hex = _iValue; break; case DI_CONFIG_REGISTER: { WARN_LOG(DVDINTERFACE, "Write to DICFG, ignored as it's read-only"); } break; default: _dbg_assert_msg_(DVDINTERFACE, 0, "Write to unknown DI address 0x%08x", _iAddress); break; } }
static void XFRegWritten(int transferSize, u32 baseAddress, DataReader src) { u32 address = baseAddress; u32 dataIndex = 0; while (transferSize > 0 && address < 0x1058) { u32 newValue = src.Peek<u32>(dataIndex * sizeof(u32)); u32 nextAddress = address + 1; switch (address) { case XFMEM_ERROR: case XFMEM_DIAG: case XFMEM_STATE0: // internal state 0 case XFMEM_STATE1: // internal state 1 case XFMEM_CLOCK: case XFMEM_SETGPMETRIC: nextAddress = 0x1007; break; case XFMEM_CLIPDISABLE: //if (data & 1) {} // disable clipping detection //if (data & 2) {} // disable trivial rejection //if (data & 4) {} // disable cpoly clipping acceleration break; case XFMEM_VTXSPECS: //__GXXfVtxSpecs, wrote 0004 break; case XFMEM_SETNUMCHAN: if (xfmem.numChan.numColorChans != (newValue & 3)) VertexManagerBase::Flush(); break; case XFMEM_SETCHAN0_AMBCOLOR: // Channel Ambient Color case XFMEM_SETCHAN1_AMBCOLOR: { u8 chan = address - XFMEM_SETCHAN0_AMBCOLOR; if (xfmem.ambColor[chan] != newValue) { VertexManagerBase::Flush(); VertexShaderManager::SetMaterialColorChanged(chan); } break; } case XFMEM_SETCHAN0_MATCOLOR: // Channel Material Color case XFMEM_SETCHAN1_MATCOLOR: { u8 chan = address - XFMEM_SETCHAN0_MATCOLOR; if (xfmem.matColor[chan] != newValue) { VertexManagerBase::Flush(); VertexShaderManager::SetMaterialColorChanged(chan + 2); } break; } case XFMEM_SETCHAN0_COLOR: // Channel Color case XFMEM_SETCHAN1_COLOR: case XFMEM_SETCHAN0_ALPHA: // Channel Alpha case XFMEM_SETCHAN1_ALPHA: if (((u32*)&xfmem)[address] != (newValue & 0x7fff)) VertexManagerBase::Flush(); break; case XFMEM_DUALTEX: if (xfmem.dualTexTrans.enabled != (newValue & 1)) VertexManagerBase::Flush(); break; case XFMEM_SETMATRIXINDA: //_assert_msg_(GX_XF, 0, "XF matrixindex0"); VertexShaderManager::SetTexMatrixChangedA(newValue); break; case XFMEM_SETMATRIXINDB: //_assert_msg_(GX_XF, 0, "XF matrixindex1"); VertexShaderManager::SetTexMatrixChangedB(newValue); break; case XFMEM_SETVIEWPORT: case XFMEM_SETVIEWPORT+1: case XFMEM_SETVIEWPORT+2: case XFMEM_SETVIEWPORT+3: case XFMEM_SETVIEWPORT+4: case XFMEM_SETVIEWPORT+5: VertexManagerBase::Flush(); VertexShaderManager::SetViewportChanged(); PixelShaderManager::SetViewportChanged(); GeometryShaderManager::SetViewportChanged(); nextAddress = XFMEM_SETVIEWPORT + 6; break; case XFMEM_SETPROJECTION: case XFMEM_SETPROJECTION+1: case XFMEM_SETPROJECTION+2: case XFMEM_SETPROJECTION+3: case XFMEM_SETPROJECTION+4: case XFMEM_SETPROJECTION+5: case XFMEM_SETPROJECTION+6: VertexManagerBase::Flush(); VertexShaderManager::SetProjectionChanged(); GeometryShaderManager::SetProjectionChanged(); nextAddress = XFMEM_SETPROJECTION + 7; break; case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens if (xfmem.numTexGen.numTexGens != (newValue & 15)) VertexManagerBase::Flush(); break; case XFMEM_SETTEXMTXINFO: case XFMEM_SETTEXMTXINFO+1: case XFMEM_SETTEXMTXINFO+2: case XFMEM_SETTEXMTXINFO+3: case XFMEM_SETTEXMTXINFO+4: case XFMEM_SETTEXMTXINFO+5: case XFMEM_SETTEXMTXINFO+6: case XFMEM_SETTEXMTXINFO+7: VertexManagerBase::Flush(); nextAddress = XFMEM_SETTEXMTXINFO + 8; break; case XFMEM_SETPOSMTXINFO: case XFMEM_SETPOSMTXINFO+1: case XFMEM_SETPOSMTXINFO+2: case XFMEM_SETPOSMTXINFO+3: case XFMEM_SETPOSMTXINFO+4: case XFMEM_SETPOSMTXINFO+5: case XFMEM_SETPOSMTXINFO+6: case XFMEM_SETPOSMTXINFO+7: VertexManagerBase::Flush(); nextAddress = XFMEM_SETPOSMTXINFO + 8; break; // -------------- // Unknown Regs // -------------- // Maybe these are for Normals? case 0x1048: //xfmem.texcoords[0].nrmmtxinfo.hex = data; break; ?? case 0x1049: case 0x104a: case 0x104b: case 0x104c: case 0x104d: case 0x104e: case 0x104f: DEBUG_LOG(VIDEO, "Possible Normal Mtx XF reg?: %x=%x", address, newValue); break; case 0x1013: case 0x1014: case 0x1015: case 0x1016: case 0x1017: default: if (newValue != 0) // Ignore writes of zero. WARN_LOG(VIDEO, "Unknown XF Reg: %x=%x", address, newValue); break; } int transferred = nextAddress - address; address = nextAddress; transferSize -= transferred; dataIndex += transferred; } }
void ExecuteCommand(UDICR& _DICR) { // _dbg_assert_(DVDINTERFACE, _DICR.RW == 0); // only DVD to Memory int GCAM = ((SConfig::GetInstance().m_SIDevice[0] == SIDEVICE_AM_BASEBOARD) && (SConfig::GetInstance().m_EXIDevice[2] == EXIDEVICE_AM_BASEBOARD)) ? 1 : 0; if (GCAM) { ERROR_LOG(DVDINTERFACE, "DVD: %08x, %08x, %08x, DMA=addr:%08x,len:%08x,ctrl:%08x", m_DICMDBUF[0].Hex, m_DICMDBUF[1].Hex, m_DICMDBUF[2].Hex, m_DIMAR.Hex, m_DILENGTH.Hex, m_DICR.Hex); // decrypt command. But we have a zero key, that simplifies things a lot. // If you get crazy dvd command errors, make sure 0x80000000 - 0x8000000c is zero'd m_DICMDBUF[0].Hex <<= 24; } switch (m_DICMDBUF[0].CMDBYTE0) { case DVDLowInquiry: if (GCAM) { // 0x29484100... // was 21 i'm not entirely sure about this, but it works well. m_DIIMMBUF.Hex = 0x21000000; } else { // small safety check, dunno if it's needed if ((m_DICMDBUF[1].Hex == 0) && (m_DILENGTH.Length == 0x20)) { u8* driveInfo = Memory::GetPointer(m_DIMAR.Address); // gives the correct output in GCOS - 06 2001/08 (61) // there may be other stuff missing ? driveInfo[4] = 0x20; driveInfo[5] = 0x01; driveInfo[6] = 0x06; driveInfo[7] = 0x08; driveInfo[8] = 0x61; // Just for fun INFO_LOG(DVDINTERFACE, "Drive Info: %02x %02x%02x/%02x (%02x)", driveInfo[6], driveInfo[4], driveInfo[5], driveInfo[7], driveInfo[8]); } } break; // "Set Extension"...not sure what it does case 0x55: INFO_LOG(DVDINTERFACE, "SetExtension"); break; // DMA Read from Disc case 0xA8: if (g_bDiscInside) { switch (m_DICMDBUF[0].CMDBYTE3) { case 0x00: // Read Sector { u32 iDVDOffset = m_DICMDBUF[1].Hex << 2; DEBUG_LOG(DVDINTERFACE, "Read: DVDOffset=%08x, DMABuffer=%08x, SrcLength=%08x, DMALength=%08x", iDVDOffset, m_DIMAR.Address, m_DICMDBUF[2].Hex, m_DILENGTH.Length); _dbg_assert_(DVDINTERFACE, m_DICMDBUF[2].Hex == m_DILENGTH.Length); if (GCAM) { if (iDVDOffset & 0x80000000) // read request to hardware buffer { u32 len = m_DILENGTH.Length / 4; switch (iDVDOffset) { case 0x80000000: ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD STATUS (80000000)"); for (u32 i = 0; i < len; i++) Memory::Write_U32(0, m_DIMAR.Address + i * 4); break; case 0x80000040: ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD STATUS (2) (80000040)"); for (u32 i = 0; i < len; i++) Memory::Write_U32(~0, m_DIMAR.Address + i * 4); Memory::Write_U32(0x00000020, m_DIMAR.Address); // DIMM SIZE, LE Memory::Write_U32(0x4743414D, m_DIMAR.Address + 4); // GCAM signature break; case 0x80000120: ERROR_LOG(DVDINTERFACE, "GC-AM: READ FIRMWARE STATUS (80000120)"); for (u32 i = 0; i < len; i++) Memory::Write_U32(0x01010101, m_DIMAR.Address + i * 4); break; case 0x80000140: ERROR_LOG(DVDINTERFACE, "GC-AM: READ FIRMWARE STATUS (80000140)"); for (u32 i = 0; i < len; i++) Memory::Write_U32(0x01010101, m_DIMAR.Address + i * 4); break; case 0x84000020: ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD STATUS (1) (84000020)"); for (u32 i = 0; i < len; i++) Memory::Write_U32(0x00000000, m_DIMAR.Address + i * 4); break; default: ERROR_LOG(DVDINTERFACE, "GC-AM: UNKNOWN MEDIA BOARD LOCATION %x", iDVDOffset); break; } break; } else if ((iDVDOffset == 0x1f900000) || (iDVDOffset == 0x1f900020)) { ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD COMM AREA (1f900020)"); memcpy(Memory::GetPointer(m_DIMAR.Address), media_buffer + iDVDOffset - 0x1f900000, m_DILENGTH.Length); for (u32 i = 0; i < m_DILENGTH.Length; i += 4) ERROR_LOG(DVDINTERFACE, "GC-AM: %08x", Memory::Read_U32(m_DIMAR.Address + i)); break; } } // Here is the actual Disk Reading if (!DVDRead(iDVDOffset, m_DIMAR.Address, m_DILENGTH.Length)) { PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); } } break; case 0x40: // Read DiscID _dbg_assert_(DVDINTERFACE, m_DICMDBUF[1].Hex == 0); _dbg_assert_(DVDINTERFACE, m_DICMDBUF[2].Hex == m_DILENGTH.Length); _dbg_assert_(DVDINTERFACE, m_DILENGTH.Length == 0x20); if (!DVDRead(m_DICMDBUF[1].Hex, m_DIMAR.Address, m_DILENGTH.Length)) PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); WARN_LOG(DVDINTERFACE, "Read DiscID %08x", Memory::Read_U32(m_DIMAR.Address)) break; default: _dbg_assert_msg_(DVDINTERFACE, 0, "Unknown Read Subcommand"); break; } } else { // there is no disc to read _DICR.TSTART = 0; m_DILENGTH.Length = 0; g_ErrorCode = ERROR_NO_DISK | ERROR_COVER_H; GenerateDIInterrupt(INT_DEINT); return; } break; // GC-AM case 0xAA: if (GCAM) { ERROR_LOG(DVDINTERFACE, "GC-AM: 0xAA, DMABuffer=%08x, DMALength=%08x", m_DIMAR.Address, m_DILENGTH.Length); u32 iDVDOffset = m_DICMDBUF[1].Hex << 2; unsigned int len = m_DILENGTH.Length; int offset = iDVDOffset - 0x1F900000; /* if (iDVDOffset == 0x84800000) { ERROR_LOG(DVDINTERFACE, "firmware upload"); } else*/ if ((offset < 0) || ((offset + len) > 0x40) || len > 0x40) { u32 addr = m_DIMAR.Address; if (iDVDOffset == 0x84800000) { ERROR_LOG(DVDINTERFACE, "FIRMWARE UPLOAD"); } else { ERROR_LOG(DVDINTERFACE, "ILLEGAL MEDIA WRITE"); } while (len >= 4) { ERROR_LOG(DVDINTERFACE, "GC-AM Media Board WRITE (0xAA): %08x: %08x", iDVDOffset, Memory::Read_U32(addr)); addr += 4; len -= 4; iDVDOffset += 4; } } else { u32 addr = m_DIMAR.Address; memcpy(media_buffer + offset, Memory::GetPointer(addr), len); while (len >= 4) { ERROR_LOG(DVDINTERFACE, "GC-AM Media Board WRITE (0xAA): %08x: %08x", iDVDOffset, Memory::Read_U32(addr)); addr += 4; len -= 4; iDVDOffset += 4; } } } break; // Seek (immediate) case DVDLowSeek: if (!GCAM) { // We don't care :) DEBUG_LOG(DVDINTERFACE, "Seek: offset=%08x (ignoring)", m_DICMDBUF[1].Hex << 2); } else { memset(media_buffer, 0, 0x20); media_buffer[0] = media_buffer[0x20]; // ID media_buffer[2] = media_buffer[0x22]; media_buffer[3] = media_buffer[0x23] | 0x80; int cmd = (media_buffer[0x23]<<8)|media_buffer[0x22]; ERROR_LOG(DVDINTERFACE, "GC-AM: execute buffer, cmd=%04x", cmd); switch (cmd) { case 0x00: media_buffer[4] = 1; break; case 0x1: media_buffer[7] = 0x20; // DIMM Size break; case 0x100: { // urgh static int percentage = 0; static int status = 0; percentage++; if (percentage > 100) { status++; percentage = 0; } media_buffer[4] = status; /* status: 0 - "Initializing media board. Please wait.." 1 - "Checking network. Please wait..." 2 - "Found a system disc. Insert a game disc" 3 - "Testing a game program. %d%%" 4 - "Loading a game program. %d%%" 5 - go 6 - error xx */ media_buffer[8] = percentage; media_buffer[4] = 0x05; media_buffer[8] = 0x64; break; } case 0x101: media_buffer[4] = 3; // version media_buffer[5] = 3; media_buffer[6] = 1; // xxx media_buffer[8] = 1; media_buffer[16] = 0xFF; media_buffer[17] = 0xFF; media_buffer[18] = 0xFF; media_buffer[19] = 0xFF; break; case 0x102: // get error code media_buffer[4] = 1; // 0: download incomplete (31), 1: corrupted, other error 1 media_buffer[5] = 0; break; case 0x103: memcpy(media_buffer + 4, "A89E27A50364511", 15); // serial break; #if 0 case 0x301: // unknown memcpy(media_buffer + 4, media_buffer + 0x24, 0x1c); break; case 0x302: break; #endif default: ERROR_LOG(DVDINTERFACE, "GC-AM: execute buffer (unknown)"); break; } memset(media_buffer + 0x20, 0, 0x20); m_DIIMMBUF.Hex = 0x66556677; // just a random value that works. } break; case DVDLowOffset: DEBUG_LOG(DVDINTERFACE, "DVDLowOffset: ignoring..."); break; // Request Error Code case DVDLowRequestError: ERROR_LOG(DVDINTERFACE, "Requesting error... (0x%08x)", g_ErrorCode); m_DIIMMBUF.Hex = g_ErrorCode; break; // Audio Stream (Immediate) // m_DICMDBUF[0].CMDBYTE1 = subcommand // m_DICMDBUF[1].Hex << 2 = offset on disc // m_DICMDBUF[2].Hex = Length of the stream case 0xE1: { u32 pos = m_DICMDBUF[1].Hex << 2; u32 length = m_DICMDBUF[2].Hex; // Start playing if (!g_bStream && m_DICMDBUF[0].CMDBYTE1 == 0 && pos != 0 && length != 0) { AudioPos = pos; CurrentStart = pos; CurrentLength = length; NGCADPCM::InitFilter(); g_bStream = true; } LoopStart = pos; LoopLength = length; g_bStream = (m_DICMDBUF[0].CMDBYTE1 == 0); // This command can start/stop the stream // Stop stream if (m_DICMDBUF[0].CMDBYTE1 == 1) { AudioPos = 0; LoopStart = 0; LoopLength = 0; CurrentStart = 0; CurrentLength = 0; } WARN_LOG(DVDINTERFACE, "(Audio) Stream subcmd = %08x offset = %08x length=%08x", m_DICMDBUF[0].Hex, m_DICMDBUF[1].Hex << 2, m_DICMDBUF[2].Hex); } break; // Request Audio Status (Immediate) case 0xE2: { switch (m_DICMDBUF[0].CMDBYTE1) { case 0x00: // Returns streaming status m_DIIMMBUF.Hex = (AudioPos == 0) ? 0 : 1; break; case 0x01: // Returns the current offset if (g_bStream) m_DIIMMBUF.Hex = (AudioPos - CurrentStart) >> 2; else m_DIIMMBUF.Hex = 0; break; case 0x02: // Returns the start offset if (g_bStream) m_DIIMMBUF.Hex = CurrentStart >> 2; else m_DIIMMBUF.Hex = 0; break; case 0x03: // Returns the total length if (g_bStream) m_DIIMMBUF.Hex = CurrentLength; else m_DIIMMBUF.Hex = 0; break; default: WARN_LOG(DVDINTERFACE, "(Audio): Subcommand: %02x Request Audio status %s", m_DICMDBUF[0].CMDBYTE1, g_bStream? "on":"off"); break; }
void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recv_data*/) { DEBUG_LOG("WORLD: Received CMSG_QUESTGIVER_CANCEL"); _player->PlayerTalkClass->CloseGossip(); }
int Ardb::GeoSearch(Context& ctx, RedisCommandFrame& cmd) { GeoSearchOptions options; std::string err; if (0 != options.Parse(cmd.GetArguments(), err, 1)) { fill_error_reply(ctx.reply, "%s", err.c_str()); return 0; } ValueObject meta; int ret = GetMetaValue(ctx, cmd.GetArguments()[0], ZSET_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, ret); ctx.reply.type = REDIS_REPLY_ARRAY; if (0 != ret) { return 0; } uint64 t1 = get_current_epoch_millis(); uint32 min_radius = 75; //magic number if (options.asc && options.limit > 0 && options.offset == 0 && options.radius > min_radius) { uint32 old_radius = options.radius; options.radius = min_radius; do { ctx.reply.Clear(); int point_num = GeoSearchByOptions(ctx, meta, options); if(point_num < 0) { break; } if (options.radius == old_radius) { break; } if (point_num > 0) { if (point_num >= options.limit) { break; } options.radius *= sqrt((options.limit / point_num) + 1); } else { options.radius *= 8; } if (options.radius > old_radius) { options.radius = old_radius; } } while (options.radius <= old_radius); } else { GeoSearchByOptions(ctx, meta, options); } ctx.reply.type = REDIS_REPLY_ARRAY; uint64 t2 = get_current_epoch_millis(); DEBUG_LOG("####Cost %llums to range geosearch", t2 - t1); return 0; }
void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) { uint32 questId; recvPacket >> questId; DEBUG_LOG("WORLD: Received CMSG_PUSHQUESTTOPARTY quest = %u", questId); if (Quest const* pQuest = sObjectMgr.GetQuestTemplate(questId)) { if (Group* pGroup = _player->GetGroup()) { for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pPlayer = itr->getSource(); if (!pPlayer || pPlayer == _player) // skip self continue; _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST); if (_player->GetDistance(pPlayer) > 10) { _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_TOO_FAR); continue; } if (!pPlayer->SatisfyQuestStatus(pQuest, false)) { _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_HAVE_QUEST); continue; } if (pPlayer->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE) { _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_FINISH_QUEST); continue; } if (!pPlayer->CanTakeQuest(pQuest, false)) { _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_CANT_TAKE_QUEST); continue; } if (!pPlayer->SatisfyQuestLog(false)) { _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_LOG_FULL); continue; } if (pPlayer->GetDividerGuid()) { _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_BUSY); continue; } pPlayer->SetDividerGuid(_player->GetObjectGuid()); if (pPlayer->GetPlayerbotAI()) pPlayer->GetPlayerbotAI()->AcceptQuest( pQuest, _player ); else { pPlayer->PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, _player->GetObjectGuid(), true); pPlayer->SetDividerGuid(_player->GetObjectGuid()); } } } } }
int Ardb::GeoSearchByOptions(Context& ctx, ValueObject& meta, GeoSearchOptions& options) { uint64 start_time = get_current_epoch_micros(); int ret = 0; double x = options.x, y = options.y; if (options.by_member) { Data element, score; element.SetString(options.member, true); ret = ZSetScore(ctx, meta, element, score); if (0 != ret || score.IsNil()) { return -1; } GeoHashHelper::GetMercatorXYByHash(score.value.iv, x, y); } else { if (options.coord_type != GEO_MERCATOR_TYPE) { x = GeoHashHelper::GetMercatorX(options.x); y = GeoHashHelper::GetMercatorY(options.y); } } DEBUG_LOG("####Step1: Cost %lluus", get_current_epoch_micros() - start_time); GeoPointArray points; ZSetRangeByScoreOptions fetch_options; fetch_options.withscores = false; fetch_options.op = OP_GET; fetch_options.fill_reply = false; fetch_options.fetch_geo_location = true; if (options.in_members) { StringSet::iterator it = options.submembers.begin(); while (it != options.submembers.end()) { //GeoPoint point; Data element, score; element.SetString(*it, true); Location loc; ret = ZSetScore(ctx, meta, element, score, &loc); if (0 == ret) { fetch_options.results.push_back(element); //fetch_options.results.push_back(score); fetch_options.locs.push_back(loc); } it++; } } else { GeoHashBitsSet ress; GeoHashHelper::GetAreasByRadiusV2(GEO_MERCATOR_TYPE, y, x, options.radius, ress); /* * Merge areas if possible to avoid disk search */ std::vector<ZRangeSpec> range_array; GeoHashBitsSet::iterator rit = ress.begin(); typedef TreeMap<uint64, uint64>::Type HashRangeMap; HashRangeMap tmp; while (rit != ress.end()) { GeoHashBits& hash = *rit; GeoHashBits next = hash; next.bits++; tmp[GeoHashHelper::Allign60Bits(hash)] = GeoHashHelper::Allign60Bits(next); rit++; } HashRangeMap::iterator tit = tmp.begin(); HashRangeMap::iterator nit = tmp.begin(); nit++; while (tit != tmp.end()) { ZRangeSpec range; range.contain_min = true; range.contain_max = true; range.min.SetInt64(tit->first); range.max.SetInt64(tit->second); while (nit != tmp.end() && nit->first == range.max.value.iv) { range.max.SetInt64(nit->second); nit++; tit++; } range_array.push_back(range); nit++; tit++; } DEBUG_LOG("After areas merging, reduce searching area size from %u to %u", ress.size(), range_array.size()); std::vector<ZRangeSpec>::iterator hit = range_array.begin(); ZSetIterator* iter = NULL; while (hit != range_array.end()) { ZRangeSpec& range = *hit; uint64 t1 = get_current_epoch_millis(); ZSetRangeByScore(ctx, meta, range, fetch_options, iter); uint64 t2 = get_current_epoch_millis(); DEBUG_LOG("####Cost %llums to range fetch", t2 - t1); hit++; } DELETE(iter); } DEBUG_LOG("####Step2: Cost %lluus", get_current_epoch_micros() - start_time); uint32 outrange = 0; LocationDeque::iterator lit = fetch_options.locs.begin(); DataArray::iterator vit = fetch_options.results.begin(); while (vit != fetch_options.results.end()) { Location& loc = *lit; GeoPoint point; point.x = loc.x; point.y = loc.y; /* * distance accuracy is 0.2m */ if (GeoHashHelper::GetDistanceSquareIfInRadius(GEO_MERCATOR_TYPE, x, y, point.x, point.y, options.radius, point.distance, 0.2)) { vit->GetDecodeString(point.value); /* * filter by exclude/include */ if (!options.includes.empty() || !options.excludes.empty()) { Data subst; subst.SetString(point.value, false); bool matched = options.includes.empty() ? true : false; if (!options.includes.empty()) { StringStringMap::const_iterator sit = options.includes.begin(); while (sit != options.includes.end()) { Data mv; if (0 != MatchValueByPattern(ctx, sit->first, sit->second, subst, mv)) { matched = false; break; } else { matched = true; } sit++; } } if (matched && !options.excludes.empty()) { StringStringMap::const_iterator sit = options.excludes.begin(); while (sit != options.excludes.end()) { Data mv; if (0 == MatchValueByPattern(ctx, sit->first, sit->second, subst, mv)) { matched = false; break; } else { matched = true; } sit++; } } if (matched) { points.push_back(point); } } else { points.push_back(point); } } else { outrange++; } vit++; lit++; } DEBUG_LOG("###Result size:%d, outrange:%d", points.size(), outrange); DEBUG_LOG("####Step3: Cost %lluus", get_current_epoch_micros() - start_time); if (!options.nosort) { std::sort(points.begin(), points.end(), options.asc ? less_by_distance : great_by_distance); } DEBUG_LOG("####Step3.5: Cost %lluus", get_current_epoch_micros() - start_time); if (options.offset > 0) { if ((uint32) options.offset > points.size()) { points.clear(); } else { GeoPointArray::iterator start = points.begin() + options.offset; points.erase(points.begin(), start); } } if (options.limit > 0) { if ((uint32) options.limit < points.size()) { GeoPointArray::iterator end = points.begin() + options.limit; points.erase(end, points.end()); } } DEBUG_LOG("####Step4: Cost %lluus", get_current_epoch_micros() - start_time); ValueObjectMap meta_cache; GeoPointArray::iterator pit = points.begin(); while (pit != points.end()) { RedisReply& r = ctx.reply.AddMember(); fill_str_reply(r, pit->value); GeoGetOptionArray::const_iterator ait = options.get_patterns.begin(); while (ait != options.get_patterns.end()) { if (ait->get_distances) { RedisReply& rr = ctx.reply.AddMember(); rr.type = REDIS_REPLY_STRING; char dbuf[128]; int dlen = snprintf(dbuf, sizeof(dbuf), "%.2f", sqrt(pit->distance)); rr.str.assign(dbuf, dlen); } else if (ait->get_coodinates) { if (options.coord_type == GEO_WGS84_TYPE) { pit->x = GeoHashHelper::GetWGS84X(pit->x); pit->y = GeoHashHelper::GetWGS84Y(pit->y); } RedisReply& rr1 = ctx.reply.AddMember(); RedisReply& rr2 = ctx.reply.AddMember(); if (options.coord_type == GEO_WGS84_TYPE) { fill_double_reply(rr1, pit->x); fill_double_reply(rr2, pit->y); } else { char dbuf[128]; int dlen = snprintf(dbuf, sizeof(dbuf), "%.2f", pit->x); rr1.type = REDIS_REPLY_STRING; rr1.str.assign(dbuf, dlen); dlen = snprintf(dbuf, sizeof(dbuf), "%.2f", pit->y); rr2.type = REDIS_REPLY_STRING; rr2.str.assign(dbuf, dlen); } } else if (ait->hgetall) { std::string keystr(ait->get_pattern.data(), ait->get_pattern.size()); string_replace(keystr, "*", pit->value); RedisReply& rr = ctx.reply.AddMember(); rr.type = REDIS_REPLY_ARRAY; HashGetAll(ctx, keystr, rr); } else { Data v, attr; v.SetString(pit->value, false); GetValueByPattern(ctx, ait->get_pattern, v, attr, &meta_cache); RedisReply& rr = ctx.reply.AddMember(); fill_value_reply(rr, attr); } ait++; } pit++; } DEBUG_LOG("####Step5: Cost %lluus", get_current_epoch_micros() - start_time); uint64 end_time = get_current_epoch_micros(); DEBUG_LOG("Cost %llu microseconds to search.", end_time - start_time); return points.size(); }
void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) { ObjectGuid guid; uint32 spellId = 0; recv_data >> guid >> spellId; DEBUG_LOG("WORLD: Received CMSG_TRAINER_BUY_SPELL Trainer: %s, learn spell id is: %u", guid.GetString().c_str(), spellId); Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { DEBUG_LOG("WORLD: HandleTrainerBuySpellOpcode - %s not found or you can't interact with him.", guid.GetString().c_str()); return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if (!unit->IsTrainerOf(_player, true)) return; // check present spell in trainer spell list TrainerSpellData const* cSpells = unit->GetTrainerSpells(); TrainerSpellData const* tSpells = unit->GetTrainerTemplateSpells(); if (!cSpells && !tSpells) return; // Try find spell in npc_trainer TrainerSpell const* trainer_spell = cSpells ? cSpells->Find(spellId) : NULL; // Not found, try find in npc_trainer_template if (!trainer_spell && tSpells) trainer_spell = tSpells->Find(spellId); // Not found anywhere, cheating? if (!trainer_spell) return; // can't be learn, cheat? Or double learn with lags... uint32 reqLevel = 0; if(!_player->IsSpellFitByClassAndRace(trainer_spell->learnedSpell, &reqLevel)) return; reqLevel = trainer_spell->isProvidedReqLevel ? trainer_spell->reqLevel : std::max(reqLevel, trainer_spell->reqLevel); if (_player->GetTrainerSpellState(trainer_spell, reqLevel) != TRAINER_SPELL_GREEN) return; // apply reputation discount uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); // check money requirement if(_player->GetMoney() < nSpellCost ) return; _player->ModifyMoney( -int32(nSpellCost) ); WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer data << ObjectGuid(guid); data << uint32(0xB3); // index from SpellVisualKit.dbc SendPacket(&data); data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player data << _player->GetObjectGuid(); data << uint32(0x016A); // index from SpellVisualKit.dbc SendPacket(&data); // learn explicitly or cast explicitly if(trainer_spell->IsCastable()) _player->CastSpell(_player, trainer_spell->spell, true); else _player->learnSpell(spellId, false); data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); data << ObjectGuid(guid); data << uint32(spellId); // should be same as in packet from client SendPacket(&data); }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player* player = ObjectAccessor::FindPlayer(guid, false); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3 + 4 + 2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(data); return; } Pet* pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4 + 2 + 2 + 2 + 1 + 2 * 6 + 8 + 1 + 8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF if (pet) mask1 = 0x7FFFFFFF; // for hunters and other classes with pets Powers powerType = player->GetPowerType(); data << uint32(mask1); // group update mask data << uint16(GetGroupMemberStatus(player)); // member's online status data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL // verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); iCoordX = loc.coord_x; iCoordY = loc.coord_y; } else { // unknown player status. } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (uint32 aura = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(aura); data << uint8(1); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (pet) { Powers petpowertype = pet->GetPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (uint32 petaura = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(petaura); data << uint8(1); } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS } if (player->GetTransportInfo()) // GROUP_UPDATE_FLAG_VEHICLE_SEAT data << uint32(((Unit*)player->GetTransportInfo()->GetTransport())->GetVehicleInfo()->GetVehicleEntry()->m_seatID[player->GetTransportInfo()->GetTransportSeat()]); SendPacket(data); }
u32 sceDisplayIsVblank() { DEBUG_LOG(SCEDISPLAY,"%i=sceDisplayIsVblank()",isVblank); return isVblank; }
/// Logon Proof command handler bool AuthSocket::_HandleLogonProof() { DEBUG_LOG("Entering _HandleLogonProof"); ///- Read the packet if (ibuf.GetLength() < sizeof(sAuthLogonProof_C)) return false; sAuthLogonProof_C lp; ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C)); /// <ul><li> If the client has no valid version if (_expversion == NO_VALID_EXP_FLAG) { ///- Check if we have the appropriate patch on the disk // 24 = len("./patches/65535enGB.mpq")+1 char tmp[24]; // No buffer overflow (fixed length of arguments) sprintf(tmp, "./patches/%d%s.mpq", _build, _localizationName.c_str()); // This will be closed at the destruction of the AuthSocket (client disconnection) FILE *pFile = fopen(tmp, "rb"); if (!pFile) { ByteBuffer pkt; pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER; DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build); DEBUG_LOG("[AuthChallenge] Patch %s not found", tmp); SendBuf((char const*)pkt.contents(), pkt.size()); return true; } else // have patch { pPatch = pFile; XFER_INIT xferh; ///- Get the MD5 hash of the patch file (get it from preloaded Patcher cache or calculate it) if (PatchesCache.GetHash(tmp, (uint8*)&xferh.md5)) { DEBUG_LOG("\n[AuthChallenge] Found precached patch info for patch %s", tmp); } else { // calculate patch md5 printf("\n[AuthChallenge] Patch info for %s was not cached.", tmp); PatchesCache.LoadPatchMD5(tmp); PatchesCache.GetHash(tmp, (uint8*)&xferh.md5); } ///- Send a packet to the client with the file length and MD5 hash uint8 data[2] = { AUTH_LOGON_PROOF, REALM_AUTH_UPDATE_CLIENT }; SendBuf((const char*)data, sizeof(data)); memcpy(&xferh, "0\x05Patch", 7); xferh.cmd = XFER_INITIATE; fseek(pPatch, 0, SEEK_END); xferh.file_size = ftell(pPatch); SendBuf((const char*)&xferh, sizeof(xferh)); return true; } } /// </ul> ///- Continue the SRP6 calculation based on data received from the client BigNumber A; A.SetBinary(lp.A, 32); // SRP safeguard: abort if A==0 if (A.isZero()) return false; Sha1Hash sha; sha.UpdateBigNumbers(&A, &B, NULL); sha.Finalize(); BigNumber u; u.SetBinary(sha.GetDigest(), 20); BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); uint8 t[32]; uint8 t1[16]; uint8 vK[40]; memcpy(t, S.AsByteArray(32), 32); for (int i = 0; i < 16; ++i) { t1[i] = t[i * 2]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; ++i) { vK[i * 2] = sha.GetDigest()[i]; } for (int i = 0; i < 16; ++i) { t1[i] = t[i * 2 + 1]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; ++i) { vK[i * 2 + 1] = sha.GetDigest()[i]; } K.SetBinary(vK, 40); uint8 hash[20]; sha.Initialize(); sha.UpdateBigNumbers(&N, NULL); sha.Finalize(); memcpy(hash, sha.GetDigest(), 20); sha.Initialize(); sha.UpdateBigNumbers(&g, NULL); sha.Finalize(); for (int i = 0; i < 20; ++i) { hash[i] ^= sha.GetDigest()[i]; } BigNumber t3; t3.SetBinary(hash, 20); sha.Initialize(); sha.UpdateData(_login); sha.Finalize(); uint8 t4[SHA_DIGEST_LENGTH]; memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH); sha.Initialize(); sha.UpdateBigNumbers(&t3, NULL); sha.UpdateData(t4, SHA_DIGEST_LENGTH); sha.UpdateBigNumbers(&s, &A, &B, &K, NULL); sha.Finalize(); BigNumber M; M.SetBinary(sha.GetDigest(), 20); ///- Check if SRP6 results match (password is correct), else send an error if (!memcmp(M.AsByteArray(), lp.M1, 20)) { sLog.outBasic("User '%s' successfully authenticated", _login.c_str()); ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account // No SQL injection (escaped user name) and IP address as received by socket const char* K_hex = K.AsHexStr(); loginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '******'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str()); OPENSSL_free((void*)K_hex); ///- Finish SRP6 and send the final result to the client sha.Initialize(); sha.UpdateBigNumbers(&A, &M, &K, NULL); sha.Finalize(); if (_expversion & POST_BC_EXP_FLAG)//2.4.3 and 3.1.3 clients (10146 is Chinese build for 3.1.3) { sAuthLogonProof_S proof; memcpy(proof.M2, sha.GetDigest(), 20); proof.cmd = AUTH_LOGON_PROOF; proof.error = 0; proof.unk1 = 0x00800000; proof.unk2 = 0x00; proof.unk3 = 0x00; SendBuf((char *)&proof, sizeof(proof)); }else{ sAuthLogonProof_S_Old proof; memcpy(proof.M2, sha.GetDigest(), 20); proof.cmd = AUTH_LOGON_PROOF; proof.error = 0; //proof.unk1 = 0x00800000; proof.unk2 = 0x00; //proof.unk3 = 0x00; SendBuf((char *)&proof, sizeof(proof)); } ///- Set _authed to true! _authed = true; } else { char data[4]= { AUTH_LOGON_PROOF, REALM_AUTH_NO_MATCH, 3, 0}; SendBuf(data, sizeof(data)); sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ()); uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0); if (MaxWrongPassCount > 0) { //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP loginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '******'",_safelogin.c_str()); if (QueryResult *loginfail = loginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '******'", _safelogin.c_str())) { Field* fields = loginfail->Fetch(); uint32 failed_logins = fields[1].GetUInt32(); if (failed_logins >= MaxWrongPassCount) { uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600); bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false); if (WrongPassBanType) { uint32 acc_id = fields[0].GetUInt32(); loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)", acc_id, WrongPassBanTime); sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", _login.c_str(), WrongPassBanTime, failed_logins); } else { std::string current_ip = GetRemoteAddress(); loginDatabase.escape_string(current_ip); loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')", current_ip.c_str(), WrongPassBanTime); sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins); } } delete loginfail; } } } return true; }