Skip to content
This repository has been archived by the owner on Mar 9, 2021. It is now read-only.

Use highres_clock for packet sorting during claims #2476

Open
wants to merge 1 commit into
base: release
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/common/cbasetypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ using uint64 = std::uint64_t;
#include <chrono>

using namespace std::literals::chrono_literals;
using server_clock = std::chrono::system_clock;
using time_point = server_clock::time_point;
using duration = server_clock::duration;
using server_clock = std::chrono::system_clock;
using highres_clock = std::chrono::high_resolution_clock;
using time_point = server_clock::time_point;
using duration = server_clock::duration;
using hr_time_point = highres_clock::time_point;

#include "tracy.h"

Expand Down
26 changes: 26 additions & 0 deletions src/map/ai/controllers/mob_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ void CMobController::Tick(time_point tick)

if (PMob->isAlive())
{
ResolveClaim();

if (PMob->PAI->IsEngaged())
{
DoCombatTick(tick);
Expand All @@ -62,6 +64,30 @@ void CMobController::Tick(time_point tick)
}
}

void CMobController::ResolveClaim()
{
auto& list = PMob->m_EntitiesTryingToClaim;
if (list.empty())
{
return;
}

// Sort the list, earliest first
std::sort(list.begin(), list.end(), [](CBattleEntity* a, CBattleEntity* b)
{
return a->lastActionTime < b->lastActionTime;
});

// Try the claims in the order they arrived
for (auto* entity : list)
{
battleutils::ClaimMobFinal(PMob, entity);
}

// Empty the list
list.clear();
}

bool CMobController::TryDeaggro()
{
TracyZoneScoped;
Expand Down
1 change: 1 addition & 0 deletions src/map/ai/controllers/mob_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class CMobController : public CController
virtual bool Cast(uint16 targid, SpellID spellid) override;

protected:
void ResolveClaim();
virtual bool TryDeaggro();

virtual void TryLink();
Expand Down
3 changes: 3 additions & 0 deletions src/map/entities/battleentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,9 @@ class CBattleEntity : public CBaseEntity
virtual void Tick(time_point) override;
virtual void PostTick() override;

// High resolution timestamp of the last action time
hr_time_point lastActionTime{ hr_time_point::max() };

health_t health; // hp,mp,tp
stats_t stats; // атрибуты STR,DEX,VIT,AGI,INT,MND,CHR
skills_t WorkingSkills; // структура всех доступных сущности умений, ограниченных уровнем
Expand Down
2 changes: 2 additions & 0 deletions src/map/entities/mobentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ class CMobEntity : public CBattleEntity
static constexpr float sound_range{ 8.f };
static constexpr float sight_range{ 15.f };

std::vector<CBattleEntity*> m_EntitiesTryingToClaim;

protected:
void DistributeRewards();
void DropItems(CCharEntity* PChar);
Expand Down
11 changes: 7 additions & 4 deletions src/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ map_session_data_t* mapsession_createsession(uint32 ip, uint16 port)

map_session_data->server_packet_data = new int8[map_config.buffer_size + 20];

map_session_data->last_update = time(nullptr);
map_session_data->last_update = highres_clock::now();
map_session_data->client_addr = ip;
map_session_data->client_port = port;

Expand Down Expand Up @@ -405,7 +405,7 @@ int32 do_sockets(fd_set* rfd, duration next)
}
}

map_session_data->last_update = time(nullptr);
map_session_data->last_update = highres_clock::now();
size_t size = ret;

if (recv_parse(g_PBuff, &size, &from, map_session_data) != -1)
Expand Down Expand Up @@ -852,7 +852,9 @@ int32 map_cleanup(time_point tick, CTaskMgr::CTask* PTask)

CCharEntity* PChar = map_session_data->PChar;

if ((time(nullptr) - map_session_data->last_update) > 5)
auto last_update_time_sec = std::chrono::duration_cast<std::chrono::seconds>(highres_clock::now() - map_session_data->last_update).count();

if (last_update_time_sec > 5)
{
if (PChar != nullptr && !(PChar->nameflags.flags & FLAG_DC))
{
Expand All @@ -863,7 +865,8 @@ int32 map_cleanup(time_point tick, CTaskMgr::CTask* PTask)
PChar->loc.zone->SpawnPCs(PChar);
}
}
if ((time(nullptr) - map_session_data->last_update) > map_config.max_time_lastupdate)

if (last_update_time_sec > map_config.max_time_lastupdate)
{
if (PChar != nullptr)
{
Expand Down
20 changes: 10 additions & 10 deletions src/map/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,16 @@ struct map_config_t

struct map_session_data_t
{
uint32 client_addr;
uint16 client_port;
uint16 client_packet_id; // id последнего пакета, пришедшего от клиента
uint16 server_packet_id; // id последнего пакета, отправленного сервером
int8* server_packet_data; // указатель на собранный пакет, который был ранее отправлен клиенту
size_t server_packet_size; // размер пакета, который был ранее отправлен клиенту
time_t last_update; // time of last packet recv
blowfish_t blowfish; // unique decypher keys
CCharEntity* PChar; // game char
uint8 shuttingDown; // prevents double session closing
uint32 client_addr;
uint16 client_port;
uint16 client_packet_id; // id последнего пакета, пришедшего от клиента
uint16 server_packet_id; // id последнего пакета, отправленного сервером
int8* server_packet_data; // указатель на собранный пакет, который был ранее отправлен клиенту
size_t server_packet_size; // размер пакета, который был ранее отправлен клиенту
hr_time_point last_update; // time of last packet recv
blowfish_t blowfish; // unique decypher keys
CCharEntity* PChar; // game char
uint8 shuttingDown; // prevents double session closing

map_session_data_t()
{
Expand Down
8 changes: 5 additions & 3 deletions src/map/packet_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,9 +646,11 @@ void SmallPacket0x01A(map_session_data_t* const PSession, CCharEntity* const PCh
TracyZoneScoped;
TracyZoneCString("Player Action");

// uint32 ID = data.ref<uint32>(0x04);
uint16 TargID = data.ref<uint16>(0x08);
uint8 action = data.ref<uint8>(0x0A);
uint16 TargID = data.ref<uint16>(0x08);
uint8 action = data.ref<uint8>(0x0A);

// Used later for claim resolution
PChar->lastActionTime = PSession->last_update;

switch (action)
{
Expand Down
134 changes: 77 additions & 57 deletions src/map/utils/battleutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4764,80 +4764,100 @@ namespace battleutils

void ClaimMob(CBattleEntity* PDefender, CBattleEntity* PAttacker, bool passing)
{
TracyZoneScoped;
if (PDefender->objtype == TYPE_MOB)
{
CBattleEntity* original = PAttacker;
if (PAttacker->objtype != TYPE_PC)
auto* PMob = static_cast<CMobEntity*>(PDefender);
PMob->m_EntitiesTryingToClaim.emplace_back(PAttacker);
}
}

void ClaimMobFinal(CBattleEntity* PDefender, CBattleEntity* PAttacker, bool passing)
{
TracyZoneScoped;

if (PDefender->objtype != TYPE_MOB)
{
return;
}

CBattleEntity* original = PAttacker;
if (PAttacker->objtype != TYPE_PC)
{
if (PAttacker->PMaster && PAttacker->PMaster->objtype == TYPE_PC)
{ // claim by master
PAttacker = PAttacker->PMaster;
}
else
{
if (PAttacker->PMaster && PAttacker->PMaster->objtype == TYPE_PC)
{ // claim by master
PAttacker = PAttacker->PMaster;
}
else
{
return;
}
return;
}
CBattleEntity* battleTarget = original->GetBattleTarget();
CMobEntity* mob = static_cast<CMobEntity*>(PDefender);
}

CBattleEntity* battleTarget = original->GetBattleTarget();
CMobEntity* mob = static_cast<CMobEntity*>(PDefender);

if (!passing)
{
mob->PEnmityContainer->UpdateEnmity(original, 0, 0, true, true);
}

if (PAttacker)
{
CCharEntity* attacker = static_cast<CCharEntity*>(PAttacker);
if (!passing)
{
mob->PEnmityContainer->UpdateEnmity(original, 0, 0, true, true);
battleutils::DirtyExp(PDefender, PAttacker);
}
if (PAttacker)

if (!battleTarget || battleTarget == PDefender || battleTarget != attacker->PClaimedMob || PDefender->isDead())
{
CCharEntity* attacker = static_cast<CCharEntity*>(PAttacker);
if (!passing)
{
battleutils::DirtyExp(PDefender, PAttacker);
if (PDefender->isAlive() && attacker->PClaimedMob && attacker->PClaimedMob != PDefender && attacker->PClaimedMob->isAlive() &&
attacker->PClaimedMob->m_OwnerID.id == attacker->id)
{ // unclaim any other living mobs owned by attacker
static_cast<CMobController*>(attacker->PClaimedMob->PAI->GetController())->TapDeclaimTime();
attacker->PClaimedMob = nullptr;
}
if (!battleTarget || battleTarget == PDefender || battleTarget != attacker->PClaimedMob || PDefender->isDead())

if (!mob->CalledForHelp())
{
if (PDefender->isAlive() && attacker->PClaimedMob && attacker->PClaimedMob != PDefender && attacker->PClaimedMob->isAlive() &&
attacker->PClaimedMob->m_OwnerID.id == attacker->id)
{ // unclaim any other living mobs owned by attacker
static_cast<CMobController*>(attacker->PClaimedMob->PAI->GetController())->TapDeclaimTime();
attacker->PClaimedMob = nullptr;
if (battleutils::HasClaim(PAttacker, PDefender))
{ // mob is currently claimed by your alliance, update ownership
mob->m_OwnerID.id = PAttacker->id;
mob->m_OwnerID.targid = PAttacker->targid;
if (PDefender->isAlive())
{ // ignore killing blow
mob->updatemask |= UPDATE_STATUS;
attacker->PClaimedMob = PDefender;
}
}
if (!mob->CalledForHelp())
{
if (battleutils::HasClaim(PAttacker, PDefender))
{ // mob is currently claimed by your alliance, update ownership
else
{ // mob is unclaimed
if (PDefender->isDead())
{ // always give rewards on the killing blow
mob->m_OwnerID.id = PAttacker->id;
mob->m_OwnerID.targid = PAttacker->targid;
if (PDefender->isAlive())
{ // ignore killing blow
mob->updatemask |= UPDATE_STATUS;
attacker->PClaimedMob = PDefender;
}
return;
}
else
{ // mob is unclaimed
if (PDefender->isDead())
{ // always give rewards on the killing blow

CBattleEntity* highestClaim = mob->PEnmityContainer->GetHighestEnmity();
if (highestClaim && highestClaim->objtype == TYPE_TRUST)
{
highestClaim = static_cast<CTrustEntity*>(highestClaim)->PMaster;
}

PAttacker->ForAlliance([&](CBattleEntity* PMember) {
if (!highestClaim || highestClaim == PMember || highestClaim == PMember->PPet)
{ // someone in your alliance is top of hate list, claim for your alliance
mob->m_OwnerID.id = PAttacker->id;
mob->m_OwnerID.targid = PAttacker->targid;
return;
}
CBattleEntity* highestClaim = mob->PEnmityContainer->GetHighestEnmity();
if (highestClaim && highestClaim->objtype == TYPE_TRUST)
{
highestClaim = static_cast<CTrustEntity*>(highestClaim)->PMaster;
}
PAttacker->ForAlliance([&](CBattleEntity* PMember) {
if (!highestClaim || highestClaim == PMember || highestClaim == PMember->PPet)
{ // someone in your alliance is top of hate list, claim for your alliance
mob->m_OwnerID.id = PAttacker->id;
mob->m_OwnerID.targid = PAttacker->targid;
if (PDefender->isAlive())
{ // ignore killing blow
mob->updatemask |= UPDATE_STATUS;
attacker->PClaimedMob = PDefender;
}

if (PDefender->isAlive())
{ // ignore killing blow
mob->updatemask |= UPDATE_STATUS;
attacker->PClaimedMob = PDefender;
}
});
}
}
});
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/map/utils/battleutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ namespace battleutils
uint8 getStoreTPbonusFromMerit(CBattleEntity* PEntity);

void ClaimMob(CBattleEntity* PDefender, CBattleEntity* PAttacker, bool passing = false);
void ClaimMobFinal(CBattleEntity* PDefender, CBattleEntity* PAttacker, bool passing = false);
void DirtyExp(CBattleEntity* PDefender, CBattleEntity* PAttacker);
void RelinquishClaim(CCharEntity* PDefender);

Expand Down