mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Tasks] Add task accept packet validation (#2354)
This makes it so clients can only accept tasks that have been offered
This commit is contained in:
parent
6068085de4
commit
7c27c4350d
@ -1835,7 +1835,13 @@ void Client::Handle_OP_AcceptNewTask(const EQApplicationPacket *app)
|
||||
AcceptNewTask_Struct *ant = (AcceptNewTask_Struct*)app->pBuffer;
|
||||
|
||||
if (ant->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && task_state)
|
||||
task_state->AcceptNewTask(this, ant->task_id, ant->task_master_id, std::time(nullptr));
|
||||
{
|
||||
if (task_state->CanAcceptNewTask(this, ant->task_id, ant->task_master_id))
|
||||
{
|
||||
task_state->AcceptNewTask(this, ant->task_id, ant->task_master_id, std::time(nullptr));
|
||||
}
|
||||
task_state->ClearLastOffers();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app)
|
||||
@ -15552,8 +15558,13 @@ void Client::Handle_OP_SharedTaskAccept(const EQApplicationPacket* app)
|
||||
buf->task_id
|
||||
);
|
||||
|
||||
if (buf->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && task_state) {
|
||||
task_state->AcceptNewTask(this, buf->task_id, buf->npc_entity_id, std::time(nullptr));
|
||||
if (buf->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && task_state)
|
||||
{
|
||||
if (task_state->CanAcceptNewTask(this, buf->task_id, buf->npc_entity_id))
|
||||
{
|
||||
task_state->AcceptNewTask(this, buf->task_id, buf->npc_entity_id, std::time(nullptr));
|
||||
}
|
||||
task_state->ClearLastOffers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2747,3 +2747,39 @@ void ClientTaskState::LockSharedTask(Client* client, bool lock)
|
||||
worldserver.SendPacket(&pack);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientTaskState::CanAcceptNewTask(Client* client, int task_id, int npc_entity_id) const
|
||||
{
|
||||
auto it = std::find_if(m_last_offers.begin(), m_last_offers.end(),
|
||||
[&](const TaskOffer& offer) { return offer.task_id == task_id; });
|
||||
|
||||
if (it == m_last_offers.end())
|
||||
{
|
||||
LogTasks("Client [{}] accepted unoffered task [{}]", client->GetName(), task_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (npc_entity_id != it->npc_entity_id)
|
||||
{
|
||||
LogTasks("Client [{}] accepted task [{}] with wrong npc entity id [{}] vs offered [{}]",
|
||||
client->GetName(), task_id, npc_entity_id, it->npc_entity_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
NPC* npc = entity_list.GetID(it->npc_entity_id)->CastToNPC();
|
||||
if (!npc) // client window disappears in this case
|
||||
{
|
||||
LogTasks("Client [{}] accepted task [{}] from missing npc", client->GetName(), task_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dist = npc->CalculateDistance(client->GetX(), client->GetY(), client->GetZ());
|
||||
if (dist > MAX_TASK_SELECT_DISTANCE)
|
||||
{
|
||||
LogTasks("Client [{}] accepted task [{}] from npc [{}] out of range [{}]",
|
||||
client->GetName(), task_id, npc->GetCleanName(), dist);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8,6 +8,14 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
constexpr float MAX_TASK_SELECT_DISTANCE = 60.0f; // client closes window at this distance
|
||||
|
||||
struct TaskOffer
|
||||
{
|
||||
int task_id;
|
||||
uint16_t npc_entity_id;
|
||||
};
|
||||
|
||||
class ClientTaskState {
|
||||
|
||||
public:
|
||||
@ -57,6 +65,8 @@ public:
|
||||
void ListTaskTimers(Client* client);
|
||||
void KickPlayersSharedTask(Client* client);
|
||||
void LockSharedTask(Client* client, bool lock);
|
||||
void ClearLastOffers() { m_last_offers.clear(); }
|
||||
bool CanAcceptNewTask(Client* client, int task_id, int npc_entity_id) const;
|
||||
|
||||
inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; }
|
||||
|
||||
@ -77,6 +87,7 @@ public:
|
||||
private:
|
||||
void AddReplayTimer(Client *client, ClientTaskInformation& client_task, TaskInformation& task);
|
||||
void DispatchEventTaskComplete(Client* client, ClientTaskInformation& client_task, int activity_id);
|
||||
void AddOffer(int task_id, uint16_t npc_entity_id) { m_last_offers.push_back({task_id, npc_entity_id}); };
|
||||
|
||||
void IncrementDoneCount(
|
||||
Client *client,
|
||||
@ -130,6 +141,7 @@ private:
|
||||
std::vector<int> m_enabled_tasks;
|
||||
std::vector<CompletedTaskInformation> m_completed_tasks;
|
||||
int m_last_completed_task_loaded;
|
||||
std::vector<TaskOffer> m_last_offers;
|
||||
|
||||
static void ShowClientTaskInfoMessage(ClientTaskInformation *task, Client *c);
|
||||
|
||||
|
||||
@ -761,6 +761,7 @@ void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int
|
||||
{
|
||||
LogTasks("TaskSelector for [{}] Tasks", task_count);
|
||||
int player_level = client->GetLevel();
|
||||
client->GetTaskState()->ClearLastOffers();
|
||||
|
||||
// Check if any of the tasks exist
|
||||
for (int i = 0; i < task_count; i++) {
|
||||
@ -809,6 +810,7 @@ void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int
|
||||
|
||||
buf.WriteUInt32(task_list[i]); // task_id
|
||||
m_task_data[task_list[i]]->SerializeSelector(buf, client->ClientVersion());
|
||||
client->GetTaskState()->AddOffer(task_list[i], mob->GetID());
|
||||
}
|
||||
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_TaskSelectWindow, buf);
|
||||
@ -821,6 +823,7 @@ void TaskManager::SendSharedTaskSelector(Client *client, Mob *mob, int task_coun
|
||||
|
||||
// request timer is only set when shared task selection shown (not for failed validations)
|
||||
client->StartTaskRequestCooldownTimer();
|
||||
client->GetTaskState()->ClearLastOffers();
|
||||
|
||||
SerializeBuffer buf;
|
||||
|
||||
@ -833,6 +836,7 @@ void TaskManager::SendSharedTaskSelector(Client *client, Mob *mob, int task_coun
|
||||
int task_id = task_list[i];
|
||||
buf.WriteUInt32(task_id);
|
||||
m_task_data[task_id]->SerializeSelector(buf, client->ClientVersion());
|
||||
client->GetTaskState()->AddOffer(task_id, mob->GetID());
|
||||
}
|
||||
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_SharedTaskSelectWindow, buf);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user