mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
World should verify the full task to simplify things
This commit is contained in:
@@ -25,6 +25,9 @@
|
||||
#include "world_config.h"
|
||||
#include "../common/guilds.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "shared_tasks.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
extern uint32 numplayers;
|
||||
extern LoginServerList loginserverlist;
|
||||
@@ -50,6 +53,8 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char* iLoginN
|
||||
pLFGToLevel = 0;
|
||||
pLFGMatchFilter = false;
|
||||
memset(pLFGComments, 0, 64);
|
||||
shared_task_id = 0;
|
||||
m_shared_task = nullptr;
|
||||
}
|
||||
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin)
|
||||
@@ -71,6 +76,8 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccNa
|
||||
pLFGToLevel = 0;
|
||||
pLFGMatchFilter = false;
|
||||
memset(pLFGComments, 0, 64);
|
||||
shared_task_id = 0;
|
||||
m_shared_task = nullptr;
|
||||
}
|
||||
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
|
||||
@@ -93,6 +100,8 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
|
||||
pLFGToLevel = 0;
|
||||
pLFGMatchFilter = false;
|
||||
memset(pLFGComments, 0, 64);
|
||||
shared_task_id = 0;
|
||||
m_shared_task = nullptr;
|
||||
|
||||
if (iOnline >= CLE_Status_Zoning)
|
||||
Update(iZS, scl, iOnline);
|
||||
@@ -105,6 +114,8 @@ ClientListEntry::~ClientListEntry() {
|
||||
Camp(); // updates zoneserver's numplayers
|
||||
client_list.RemoveCLEReferances(this);
|
||||
}
|
||||
if (m_shared_task != nullptr)
|
||||
m_shared_task->MemberLeftGame(this);
|
||||
for (auto &elem : tell_queue)
|
||||
safe_delete_array(elem);
|
||||
tell_queue.clear();
|
||||
@@ -248,6 +259,10 @@ void ClientListEntry::ClearVars(bool iAll) {
|
||||
pLFG = 0;
|
||||
gm = 0;
|
||||
pClientVersion = 0;
|
||||
shared_task_id = 0;
|
||||
if (m_shared_task != nullptr)
|
||||
m_shared_task->MemberLeftGame(this);
|
||||
m_shared_task = nullptr;
|
||||
for (auto &elem : tell_queue)
|
||||
safe_delete_array(elem);
|
||||
tell_queue.clear();
|
||||
@@ -331,3 +346,34 @@ void ClientListEntry::ProcessTellQueue()
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns expire timestamp
|
||||
*/
|
||||
|
||||
int ClientListEntry::GetTaskLockoutExpire(int id) const
|
||||
{
|
||||
auto it = std::find_if(m_task_replay_timers.begin(), m_task_replay_timers.end(),
|
||||
[id](const TaskTimer &a) { return a.ID == id; });
|
||||
|
||||
if (it != m_task_replay_timers.end())
|
||||
return it->expires;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns seconds until expires
|
||||
* returns <= 0 if expired
|
||||
*/
|
||||
|
||||
int ClientListEntry::GetTaskLockoutTimeLeft(int id) const
|
||||
{
|
||||
auto it = std::find_if(m_task_replay_timers.begin(), m_task_replay_timers.end(),
|
||||
[id](const TaskTimer &a) { return a.ID == id; });
|
||||
|
||||
if (it != m_task_replay_timers.end())
|
||||
return it->expires - Timer::GetCurrentTime();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//#include "../common/eq_packet_structs.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/global_tasks.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -18,6 +19,7 @@
|
||||
|
||||
class ZoneServer;
|
||||
struct ServerClientList_Struct;
|
||||
class SharedTask;
|
||||
|
||||
class ClientListEntry {
|
||||
public:
|
||||
@@ -88,6 +90,12 @@ public:
|
||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||
void ProcessTellQueue();
|
||||
|
||||
// shared task stuff
|
||||
int GetTaskLockoutExpire(int id) const;
|
||||
int GetTaskLockoutTimeLeft(int id) const;
|
||||
inline int GetCurrentSharedTaskID() const { return shared_task_id; }
|
||||
inline void SetCurrentSharedTaskID(int in) { shared_task_id = in; }
|
||||
|
||||
private:
|
||||
void ClearVars(bool iAll = false);
|
||||
|
||||
@@ -129,6 +137,13 @@ private:
|
||||
bool pLFGMatchFilter;
|
||||
char pLFGComments[64];
|
||||
|
||||
// shared task stuff
|
||||
// stub for now
|
||||
int shared_task_id; // ID in the TaskManager
|
||||
SharedTask *m_shared_task; // just for quick reference so we can tell it to clean up our pointer
|
||||
|
||||
std::vector<TaskTimer> m_task_replay_timers;
|
||||
|
||||
// Tell Queue -- really a vector :D
|
||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||
};
|
||||
|
||||
+58
-85
@@ -3,6 +3,8 @@
|
||||
#include "cliententry.h"
|
||||
#include "zonelist.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
extern ClientList client_list;
|
||||
extern ZSList zoneserver_list;
|
||||
|
||||
@@ -15,11 +17,25 @@ void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
||||
int task_id = pack->ReadUInt32();
|
||||
pack->ReadString(tmp_str);
|
||||
std::string leader_name = tmp_str;
|
||||
int missing_count = pack->ReadUInt32();
|
||||
std::vector<std::string> missing_players;
|
||||
for (int i = 0; i < missing_count; ++i) {
|
||||
int player_count = pack->ReadUInt32();
|
||||
std::vector<std::string> players;
|
||||
for (int i = 0; i < player_count; ++i) {
|
||||
pack->ReadString(tmp_str);
|
||||
missing_players.push_back(tmp_str);
|
||||
players.push_back(tmp_str);
|
||||
}
|
||||
|
||||
// check if the task exist, we only load shared tasks in world, so we know the type is correct if found
|
||||
auto it = task_information.find(task_id);
|
||||
if (it == task_information.end()) { // not loaded! bad id or not shared task
|
||||
auto pc = client_list.FindCharacter(leader_name.c_str());
|
||||
if (pc) {
|
||||
auto pack = new ServerPacket(ServerOP_TaskReject, leader_name.size() + 1 + 4);
|
||||
pack->WriteUInt32(0); // string ID or just generic fail message
|
||||
pack->WriteString(leader_name.c_str());
|
||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||
safe_delete(pack);
|
||||
} // oh well
|
||||
return;
|
||||
}
|
||||
|
||||
int id = GetNextID();
|
||||
@@ -33,85 +49,46 @@ void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||
safe_delete(pack);
|
||||
} // oh well
|
||||
return;
|
||||
}
|
||||
|
||||
auto cle = client_list.FindCharacter(leader_name.c_str());
|
||||
if (cle == nullptr) {// something went wrong
|
||||
tasks.erase(ret.first);
|
||||
return;
|
||||
}
|
||||
|
||||
auto &task = ret.first->second;
|
||||
task.AddMember(leader_name, true);
|
||||
task.AddMember(leader_name, cle, true);
|
||||
|
||||
if (missing_players.empty()) {
|
||||
if (players.empty()) {
|
||||
// send instant success to leader
|
||||
auto pc = client_list.FindCharacter(leader_name.c_str());
|
||||
if (pc) {
|
||||
SerializeBuffer buf(10);
|
||||
buf.WriteInt32(id); // task's ID
|
||||
buf.WriteString(leader_name); // leader's name
|
||||
SerializeBuffer buf(10);
|
||||
buf.WriteInt32(id); // task's ID
|
||||
buf.WriteString(leader_name); // leader's name
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_TaskGrant, buf);
|
||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||
safe_delete(pack);
|
||||
} else { // well fuck
|
||||
tasks.erase(ret.first);
|
||||
}
|
||||
auto pack = new ServerPacket(ServerOP_TaskGrant, buf);
|
||||
zoneserver_list.SendPacket(cle->zone(), cle->instance(), pack);
|
||||
safe_delete(pack);
|
||||
return;
|
||||
}
|
||||
|
||||
task.SetMissingCount(missing_count);
|
||||
for (auto &&name : missing_players) {
|
||||
for (auto &&name : players) {
|
||||
// look up CLEs by name, tell them we need to know if they can be added
|
||||
auto pc = client_list.FindCharacter(name.c_str());
|
||||
if (pc) {
|
||||
SerializeBuffer buf(10);
|
||||
buf.WriteInt32(id);
|
||||
buf.WriteInt32(task_id);
|
||||
buf.WriteString(name);
|
||||
cle = client_list.FindCharacter(name.c_str());
|
||||
if (cle) {
|
||||
// make sure we don't have a shared task already
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_TaskRequest, buf);
|
||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||
safe_delete(pack);
|
||||
} else { // asked for a toon we couldn't find ABORT!
|
||||
auto pc = client_list.FindCharacter(leader_name.c_str());
|
||||
if (pc) {
|
||||
auto pack = new ServerPacket(ServerOP_TaskReject, leader_name.size() + 1 + 4);
|
||||
pack->WriteUInt32(0); // string ID or just generic fail message
|
||||
pack->WriteString(leader_name.c_str());
|
||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||
safe_delete(pack);
|
||||
} // oh well
|
||||
tasks.erase(ret.first);
|
||||
break;
|
||||
// make sure our level is right
|
||||
|
||||
// check our lock out timer
|
||||
|
||||
// we're good, add to task
|
||||
task.AddMember(name, cle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SharedTaskManager::HandleTaskRequestReply(ServerPacket *pack)
|
||||
{
|
||||
if (!pack)
|
||||
return;
|
||||
|
||||
int id = pack->ReadUInt32();
|
||||
|
||||
char name[64] = { 0 };
|
||||
pack->ReadString(name);
|
||||
|
||||
int status = pack->ReadUInt32();
|
||||
|
||||
auto it = tasks.find(id);
|
||||
if (it == tasks.end()) {
|
||||
// task already errored and no longer existed, we can ignore
|
||||
return;
|
||||
}
|
||||
|
||||
auto &task = it->second;
|
||||
|
||||
if (status != TASKJOINOOZ_CAN) {
|
||||
// TODO: forward to leader
|
||||
return;
|
||||
}
|
||||
|
||||
if (!task.DecrementMissingCount())
|
||||
tasks.erase(it);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called once during boot of world
|
||||
* We need to load next_id, clean up expired tasks (?), and populate the map
|
||||
@@ -138,23 +115,19 @@ int SharedTaskManager::GetNextID()
|
||||
return next_id;
|
||||
}
|
||||
|
||||
bool SharedTask::DecrementMissingCount()
|
||||
{
|
||||
--missing_count;
|
||||
if (missing_count == 0) {
|
||||
auto pc = client_list.FindCharacter(leader_name.c_str());
|
||||
if (pc) {
|
||||
SerializeBuffer buf(10);
|
||||
buf.WriteInt32(id); // task's ID
|
||||
buf.WriteString(leader_name); // leader's name
|
||||
/*
|
||||
* When a player leaves world they will tell us to clean up their pointer
|
||||
* This is NOT leaving the shared task, just crashed or something
|
||||
*/
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_TaskGrant, buf);
|
||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||
safe_delete(pack);
|
||||
} else {
|
||||
return false; // error, please clean us up
|
||||
}
|
||||
}
|
||||
return true;
|
||||
void SharedTask::MemberLeftGame(ClientListEntry *cle)
|
||||
{
|
||||
auto it = std::find_if(members.begin(), members.end(), [cle](SharedTaskMember &m) { return m.cle == cle; });
|
||||
|
||||
// ahh okay ...
|
||||
if (it == members.end())
|
||||
return;
|
||||
|
||||
it->cle = nullptr;
|
||||
}
|
||||
|
||||
|
||||
+18
-10
@@ -5,29 +5,36 @@
|
||||
#include <string>
|
||||
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/global_tasks.h"
|
||||
|
||||
class ClientListEntry;
|
||||
|
||||
struct SharedTaskMember {
|
||||
std::string name;
|
||||
ClientListEntry *cle;
|
||||
bool leader;
|
||||
SharedTaskMember() : leader(false) {}
|
||||
SharedTaskMember(std::string name, bool leader) : name(name), leader(leader) {}
|
||||
SharedTaskMember() : leader(false), cle(nullptr) {}
|
||||
SharedTaskMember(std::string name, ClientListEntry *cle, bool leader) : name(name), cle(cle), leader(leader) {}
|
||||
};
|
||||
|
||||
class SharedTask {
|
||||
public:
|
||||
SharedTask() : id(0), task_id(0), missing_count(0) {}
|
||||
SharedTask(int id, int task_id) : id(id), task_id(task_id), missing_count(0) {}
|
||||
SharedTask() : id(0), task_id(0) {}
|
||||
SharedTask(int id, int task_id) : id(id), task_id(task_id) {}
|
||||
~SharedTask() {}
|
||||
|
||||
void AddMember(std::string name, bool leader = false) { members.push_back({name, leader}); if (leader) leader_name = name; }
|
||||
inline void SetMissingCount(int in) { missing_count = in; }
|
||||
bool DecrementMissingCount(); // if we failed, tell who called us to clean us up basically
|
||||
void AddMember(std::string name, ClientListEntry *cle = nullptr, bool leader = false)
|
||||
{
|
||||
members.push_back({name, cle, leader});
|
||||
if (leader)
|
||||
leader_name = name;
|
||||
}
|
||||
void MemberLeftGame(ClientListEntry *cle);
|
||||
const std::string &GetLeaderName() const { return leader_name; }
|
||||
|
||||
private:
|
||||
int id; // id we have in our map
|
||||
int task_id; // ID of the task we're on
|
||||
int missing_count; // other toons waiting to verify (out of zone, etc)
|
||||
std::string leader_name;
|
||||
std::vector<SharedTaskMember> members;
|
||||
};
|
||||
@@ -38,15 +45,16 @@ public:
|
||||
~SharedTaskManager() {}
|
||||
|
||||
bool LoadSharedTaskState();
|
||||
bool LoadSharedTasks();
|
||||
|
||||
// IPC packet processing
|
||||
void HandleTaskRequest(ServerPacket *pack);
|
||||
void HandleTaskRequestReply(ServerPacket *pack);
|
||||
|
||||
private:
|
||||
int GetNextID();
|
||||
int next_id;
|
||||
std::unordered_map<int, SharedTask> tasks;
|
||||
std::unordered_map<int, SharedTask> tasks; // current active shared task states
|
||||
std::unordered_map<int, TaskInformation> task_information; // task info shit
|
||||
};
|
||||
|
||||
#endif /* !SHARED_TASKS_H */
|
||||
|
||||
@@ -1356,11 +1356,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
shared_tasks.HandleTaskRequest(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_TaskRequestReply:
|
||||
{
|
||||
shared_tasks.HandleTaskRequestReply(pack);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Log(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size);
|
||||
|
||||
Reference in New Issue
Block a user