mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-28 08:51:39 +00:00
More work on shared tasks
This commit is contained in:
parent
39544b4723
commit
ea0a54ed60
@ -20,3 +20,30 @@ CREATE TABLE `task_replay_groups` (
|
||||
`name` VARCHAR(128) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY(`id`)
|
||||
);
|
||||
CREATE TABLE `character_task_lockouts` (
|
||||
`charid` INT NOT NULL,
|
||||
`replay_group` INT NOT NULL,
|
||||
`timestamp` INT NOT NULL,
|
||||
PRIMARY KEY(`charid`, `replay_group`)
|
||||
);
|
||||
CREATE TABLE `shared_task_state` (
|
||||
`id` INT NOT NULL,
|
||||
`taskid` INT NOT NULL,
|
||||
`acceptedtime` INT NOT NULL,
|
||||
`locked` TINYINT NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY(`id`)
|
||||
);
|
||||
CREATE TABLE `shared_task_activities` (
|
||||
`shared_id` INT NOT NULL,
|
||||
`activity_id` INT NOT NULL,
|
||||
`done_count` INT NOT NULL,
|
||||
`completed` TINYINT,
|
||||
PRIMARY KEY(`shared_id`, `activity_id`)
|
||||
);
|
||||
CREATE TABLE `shared_task_members` (
|
||||
`shared_id` INT NOT NULL,
|
||||
`charid` INT NOT NULL,
|
||||
`name` VARCHAR(64) NOT NULL,
|
||||
`leader` TINYINT,
|
||||
PRIMARY KEY(`charid`)
|
||||
);
|
||||
|
||||
@ -15,6 +15,7 @@ SET(world_sources
|
||||
login_server_list.cpp
|
||||
net.cpp
|
||||
queryserv.cpp
|
||||
shared_tasks.cpp
|
||||
ucs.cpp
|
||||
web_interface.cpp
|
||||
web_interface_eqw.cpp
|
||||
@ -42,6 +43,7 @@ SET(world_headers
|
||||
login_server_list.h
|
||||
net.h
|
||||
queryserv.h
|
||||
shared_tasks.h
|
||||
sof_char_create_data.h
|
||||
ucs.h
|
||||
web_interface.h
|
||||
|
||||
@ -83,6 +83,7 @@ union semun {
|
||||
#include "queryserv.h"
|
||||
#include "web_interface.h"
|
||||
#include "console.h"
|
||||
#include "shared_tasks.h"
|
||||
|
||||
#include "../common/net/servertalk_server.h"
|
||||
#include "../zone/data_bucket.h"
|
||||
@ -103,6 +104,7 @@ bool holdzones = false;
|
||||
const WorldConfig *Config;
|
||||
EQEmuLogSys LogSys;
|
||||
WebInterfaceList web_interface;
|
||||
SharedTaskManager shared_tasks;
|
||||
|
||||
void CatchSignal(int sig_num);
|
||||
void CheckForServerScript(bool force_download = false);
|
||||
@ -622,4 +624,4 @@ void CheckForServerScript(bool force_download) {
|
||||
system("wget -N --no-check-certificate --quiet -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
85
world/shared_tasks.cpp
Normal file
85
world/shared_tasks.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "shared_tasks.h"
|
||||
#include "clientlist.h"
|
||||
#include "cliententry.h"
|
||||
#include "zonelist.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern ZSList zoneserver_list;
|
||||
|
||||
void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
||||
{
|
||||
if (!pack)
|
||||
return;
|
||||
|
||||
char tmp_str[64] = { 0 };
|
||||
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) {
|
||||
pack->ReadString(tmp_str);
|
||||
missing_players.push_back(tmp_str);
|
||||
}
|
||||
|
||||
int id = GetNextID();
|
||||
auto ret = tasks.insert({id, {id, task_id}});
|
||||
if (!ret.second) {
|
||||
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
|
||||
}
|
||||
|
||||
auto &task = ret.first->second;
|
||||
task.AddMember(leader_name, true);
|
||||
|
||||
if (missing_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
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
task.SetMissingCount(missing_count);
|
||||
for (auto &&name : missing_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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
world/shared_tasks.h
Normal file
46
world/shared_tasks.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef SHARED_TASKS_H
|
||||
#define SHARED_TASKS_H
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "../common/servertalk.h"
|
||||
|
||||
struct SharedTaskMember {
|
||||
std::string name;
|
||||
bool leader;
|
||||
SharedTaskMember() : leader(false) {}
|
||||
SharedTaskMember(std::string name, bool leader) : name(name), 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() {}
|
||||
|
||||
void AddMember(std::string name, bool leader = false) { members.push_back({name, leader}); }
|
||||
inline void SetMissingCount(int in) { missing_count = in; }
|
||||
|
||||
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::vector<SharedTaskMember> members;
|
||||
};
|
||||
|
||||
class SharedTaskManager {
|
||||
public:
|
||||
SharedTaskManager() {}
|
||||
~SharedTaskManager() {}
|
||||
|
||||
// IPC packet processing
|
||||
void HandleTaskRequest(ServerPacket *pack);
|
||||
|
||||
private:
|
||||
inline int GetNextID() { return ++next_id; }
|
||||
int next_id;
|
||||
std::unordered_map<int, SharedTask> tasks;
|
||||
};
|
||||
|
||||
#endif /* !SHARED_TASKS_H */
|
||||
@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "adventure_manager.h"
|
||||
#include "ucs.h"
|
||||
#include "queryserv.h"
|
||||
#include "shared_tasks.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern GroupLFPList LFPGroupList;
|
||||
@ -45,6 +46,7 @@ extern volatile bool UCSServerAvailable_;
|
||||
extern AdventureManager adventure_manager;
|
||||
extern UCSConnection UCSLink;
|
||||
extern QueryServConnection QSLink;
|
||||
extern SharedTaskManager shared_tasks;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
ZoneServer::ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection, EQ::Net::ConsoleServer *console)
|
||||
@ -1344,6 +1346,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
cle->ProcessTellQueue();
|
||||
break;
|
||||
}
|
||||
case ServerOP_TaskRequest:
|
||||
{
|
||||
shared_tasks.HandleTaskRequest(pack);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Log(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size);
|
||||
|
||||
@ -234,6 +234,7 @@ struct PendingSharedTask {
|
||||
int id;
|
||||
int task_master_id;
|
||||
Timer timeout; // so if we take a very long time to get messages back from world, we time out and fail
|
||||
std::vector<std::string> members; // members ahh I guess if verification takes a long time raid could change?
|
||||
PendingSharedTask() : id(0), task_master_id(0) {}
|
||||
};
|
||||
|
||||
@ -1035,6 +1036,7 @@ public:
|
||||
inline bool IsTaskEnabled(int TaskID) { return (taskstate ? taskstate->IsTaskEnabled(TaskID) : false); }
|
||||
inline void ProcessTaskProximities(float X, float Y, float Z) { if(taskstate) taskstate->ProcessTaskProximities(this, X, Y, Z); }
|
||||
inline void AssignTask(int TaskID, int NPCID, bool enforce_level_requirement = false) { if (taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID, enforce_level_requirement); }
|
||||
inline void AssignSharedTask(int TaskID, int NPCID, int id) { if (taskstate) taskstate->AcceptNewSharedTask(this, TaskID, NPCID, id); }
|
||||
inline int ActiveSpeakTask(int NPCID) { if(taskstate) return taskstate->ActiveSpeakTask(NPCID); else return 0; }
|
||||
inline int ActiveSpeakActivity(int NPCID, int TaskID) { if(taskstate) return taskstate->ActiveSpeakActivity(NPCID, TaskID); else return 0; }
|
||||
inline void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); }
|
||||
@ -1054,10 +1056,12 @@ public:
|
||||
inline int GetTaskLockoutExpire(int id) { return 0; } // stub
|
||||
|
||||
inline void SetPendingTask(int id, int task_master_id) { pending_task.id = id; pending_task.task_master_id = task_master_id; }
|
||||
inline bool HasPendingTask() const { return pending_task.id == 0; }
|
||||
inline bool HasPendingTask() const { return pending_task.id != 0; }
|
||||
inline int GetPendingTaskID() const { return pending_task.id; }
|
||||
inline int GetPendingTaskMasterID() const { return pending_task.task_master_id; }
|
||||
inline void StartPendingTimer() { pending_task.timeout.Start(PENDING_TASK_TIMEOUT); }
|
||||
inline void ResetPendingTask() { pending_task.id = 0; pending_task.task_master_id = 0; pending_task.timeout.Disable(); pending_task.members.clear(); }
|
||||
inline void PendingTaskAddMember(const char *name) { pending_task.members.push_back(name); }
|
||||
|
||||
inline const EQEmu::versions::ClientVersion ClientVersion() const { return m_ClientVersion; }
|
||||
inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; }
|
||||
|
||||
@ -161,8 +161,7 @@ bool Client::Process() {
|
||||
|
||||
if (pending_task.timeout.Check(false)) {
|
||||
Message(13, "Shared task timed out.");
|
||||
pending_task.id = 0;
|
||||
pending_task.task_master_id = 0;
|
||||
ResetPendingTask();
|
||||
}
|
||||
|
||||
if (linkdead_timer.Check()) {
|
||||
|
||||
@ -3444,6 +3444,11 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
||||
bool task_failed = false;
|
||||
if (group) {
|
||||
for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) {
|
||||
if (group->members[i] == c)
|
||||
continue;
|
||||
|
||||
c->PendingTaskAddMember(group->membername[i]);
|
||||
|
||||
if (group->members[i] && group->members[i]->IsClient()) {
|
||||
auto *client = group->members[i]->CastToClient();
|
||||
auto *task_state = client->GetTaskState();
|
||||
@ -3476,6 +3481,11 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
||||
}
|
||||
} else if (raid) {
|
||||
for (int i = 0; i < MAX_RAID_MEMBERS; ++i) {
|
||||
if (raid->members[i].member == c)
|
||||
continue;
|
||||
|
||||
c->PendingTaskAddMember(raid->members[i].membername);
|
||||
|
||||
if (raid->members[i].member) {
|
||||
auto *client = raid->members[i].member;
|
||||
auto *task_state = client->GetTaskState();
|
||||
@ -3527,6 +3537,11 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
||||
delete pack;
|
||||
}
|
||||
|
||||
void ClientTaskState::AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float Z) {
|
||||
|
||||
float LastX = c->ProximityX();
|
||||
|
||||
@ -265,7 +265,7 @@ public:
|
||||
int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID);
|
||||
int GetTaskStartTime(TaskType type, int index);
|
||||
void AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||
// void AcceptNewSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||
void AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id);
|
||||
void PendSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||
void FailTask(Client *c, int TaskID);
|
||||
int TaskTimeLeft(int TaskID);
|
||||
|
||||
@ -1936,6 +1936,44 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_TaskGrant:
|
||||
{
|
||||
int id = pack->ReadUInt32();
|
||||
char name[64] = { 0 };
|
||||
pack->ReadString(name);
|
||||
auto client = entity_list.GetClientByName(name);
|
||||
if (client && client->HasPendingTask()) // if they don't have it, ignore it I guess :P
|
||||
client->AssignSharedTask(client->GetPendingTaskID(), client->GetPendingTaskMasterID(), id);
|
||||
break;
|
||||
}
|
||||
case ServerOP_TaskReject:
|
||||
{
|
||||
int message = pack->ReadUInt32();
|
||||
char name[64] = { 0 };
|
||||
pack->ReadString(name);
|
||||
auto client = entity_list.GetClientByName(name);
|
||||
if (client && client->HasPendingTask()) {
|
||||
client->ResetPendingTask();
|
||||
if (message == 0)
|
||||
client->Message(13, "Shared task assignment has failed.");
|
||||
else if (message > 0)
|
||||
client->Message_StringID(13, message);
|
||||
// negative nothing I guess
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_TaskRequest:
|
||||
{
|
||||
int id = pack->ReadUInt32(); // we need the ID when reply to world so we know which shared task we're going to
|
||||
int task_id = pack->ReadUInt32();
|
||||
char name[64] = { 0 };
|
||||
pack->ReadString(name);
|
||||
auto client = entity_list.GetClientByName(name);
|
||||
if (client) {
|
||||
// do check
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
std::cout << " Unknown ZSopcode:" << (int)pack->opcode;
|
||||
std::cout << " size:" << pack->size << std::endl;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user