From 6a25f3044147135cd33cf8a2ebc167d3ff81080f Mon Sep 17 00:00:00 2001 From: Xackery Date: Sat, 17 Mar 2018 18:45:31 -0700 Subject: [PATCH] Added lua/perl support for nats AdminMessage, added more response fields --- common/message.proto | 31 +++++-- utils/nats/playersay/playersay.go | 112 +++++++++++++++--------- world/nats_manager.cpp | 90 ++++++++++++++------ zone/embparser_api.cpp | 18 ++++ zone/lua_general.cpp | 11 ++- zone/nats_manager.cpp | 137 ++++++++++++++++++------------ zone/nats_manager.h | 2 +- 7 files changed, 273 insertions(+), 128 deletions(-) diff --git a/common/message.proto b/common/message.proto index ae67ed11a..36b04f088 100644 --- a/common/message.proto +++ b/common/message.proto @@ -16,22 +16,28 @@ message ChannelMessage { int32 minstatus = 9; int32 fromadmin = 10; bool noreply = 11; - bool is_emote = 12; - //0 not queued, 1 queued, 2 queue full, 3 offline - int32 queued = 13; - string result = 15; //Result of channel request. 1 = Success, Non-numeric = error + bool is_emote = 12; //Is message considered an emote? + int32 queued = 13; //only used on channel_message.out events. (*.in uses response_message): 0 not queued, 1 queued, 2 queue full, 3 offline int32 from_entity_id = 16; //(Only in zone requests) Entity to send message from EntityType from_entity_type = 17; //(Only in zone requests) Entity type the message is from float distance = 18; //(optional, only in zone requests) how far should the message travel? (e.g. say) bool skip_sender = 19; //(optional, only in zone requests) should we skip sender? + string response_message = 20; //Human-readable response message of request. + int32 response_value = 21; //Response value. In cases where a single value is returned, this is utilized (like an entity id) + ErrorType response_error = 22; //error (if any), ERR_OK (0) is default + string response_type = 23; //defines what message type the response_payload is + bytes response_payload = 24; //binary payload to be parsed using response_type } message CommandMessage { string author = 1; //Author of command. This can typically be ignored string command = 2; //command to request - repeated string params = 3; //Parameters are an array of strings. - string result = 4; //Result of command request. If non-numeric, it is an error message. If it's an integer, and greater than 0, it is a success (1 is default. Some commands return entity id) - bytes payload = 5; //Raw Payload to be parsed + repeated string params = 3; //Parameters are an array of strings. + string response_message = 4; //Human-readable response message of request. + int32 response_value = 5; //Response value. In cases where a single value is returned, this is utilized (like an entity id) + ErrorType response_error = 6; //error (if any), ERR_OK (0) is default + string response_type = 7; //defines what message type the response_payload is + bytes response_payload = 8; //binary payload to be parsed using response_type } //Entity is full of entity data. @@ -447,6 +453,14 @@ message UseAAEvent { uint32 exp_value = 6; } + +enum ErrorType { + ERR_OK = 0; //OK, No error provided + ERR_Request = 1; //Request data has something wrong. See response_message for more details. + ERR_Internal = 2; //Internal server error. See response message for mode details + ERR_Failed = 3; //Failed request. This is when the request succeeds, there are no internal server errors, but the response is a failure. +} + //EntityType will attempt to identify an entity to it's upper-most type by default enum EntityType { NPC = 0; //Inherits mob @@ -514,7 +528,8 @@ enum MessageType { BrightBlue = 3; // FF|0040FF Magenta = 5; // FF|F000F0 Gray = 6; // FF|808080 - LightGray = 7; // FF|E0E0E0 + LightGray = 7; // FF|E0E0E0 , also tell? + SayLocal = 8; //Say when you say it? WhiteSmoke2 = 10; // FF|F0F0F0 DarkGray = 12; // FF|A0A0A0 Red= 13; // FF|F00000 diff --git a/utils/nats/playersay/playersay.go b/utils/nats/playersay/playersay.go index c03890fa6..a231eec8a 100644 --- a/utils/nats/playersay/playersay.go +++ b/utils/nats/playersay/playersay.go @@ -4,12 +4,12 @@ package main import ( "fmt" "log" - "strconv" "time" "github.com/eqemu/server/protobuf/go/eqproto" "github.com/golang/protobuf/proto" "github.com/nats-io/go-nats" + "github.com/pkg/errors" ) var ( @@ -28,7 +28,9 @@ func main() { zone := "ecommons" instance := int64(0) entities = zoneEntityList(zone, 0) - + if len(entities) == 0 { + return + } fmt.Println(len(entities), "entities known") //fmt.Println(entities) @@ -45,35 +47,82 @@ func main() { } go asyncChannelMessageSubscriber(nc) //async is recommended go entityEventSubscriber(zone, instance, entityID) - zoneChannel(zone, instance, entityID, eqproto.EntityType_Client, eqproto.MessageType_Say, "Hello, World!") + err := zoneChannelMessage(zone, instance, entityID, eqproto.EntityType_Client, eqproto.MessageType_Say, "Hello, World!") + //err := tell("shin", "Testing tell") + if err != nil { + fmt.Println("Failed to send channel message:", err.Error()) + return + } time.Sleep(1000 * time.Second) } -func zoneChannel(zone string, instance int64, fromEntityID int32, fromEntityType eqproto.EntityType, chanNumber eqproto.MessageType, message string) { +func tell(to string, message string) (err error) { msg := &eqproto.ChannelMessage{ - Message: message, - Number: chanNumber, - FromEntityId: fromEntityID, - FromEntityType: fromEntityType, - Distance: 500, - SkipSender: true, + Message: message, + From: "go", + To: to, } + d, err := proto.Marshal(msg) if err != nil { log.Fatal(err) } - channel := fmt.Sprintf("zone.%s.channel_message.in", zone) - log.Println(channel, "sending channel request", msg) + + channel := fmt.Sprintf("world.channel_message.in") reply, err := nc.Request(channel, d, 1*time.Second) if err != nil { - log.Println("Failed to get request response on zone channel:", err.Error()) + err = errors.Wrap(err, "Failed to get request response on zone channel") return } err = proto.Unmarshal(reply.Data, msg) if err != nil { - fmt.Println("Failed to unmarshal", err.Error()) + err = errors.Wrap(err, "failed to unmarshal") + return + } + + if msg.ResponseError > 0 { + err = errors.New(msg.ResponseMessage) + return + } + fmt.Println("Response:", msg) + return +} + +func zoneChannelMessage(zone string, instance int64, fromEntityID int32, fromEntityType eqproto.EntityType, chanNumber eqproto.MessageType, message string) (err error) { + + msg := &eqproto.ChannelMessage{ + Message: message, + Number: eqproto.MessageType_SayLocal, //chanNumber, + FromEntityId: fromEntityID, + FromEntityType: fromEntityType, + From: "go", + Distance: 500, + SkipSender: false, + //To: "shin", + } + + d, err := proto.Marshal(msg) + if err != nil { + log.Fatal(err) + } + + channel := fmt.Sprintf("zone.%s.%d.channel_message.in", zone, instance) + reply, err := nc.Request(channel, d, 1*time.Second) + if err != nil { + err = errors.Wrap(err, "Failed to get request response on zone channel") + return + } + + err = proto.Unmarshal(reply.Data, msg) + if err != nil { + err = errors.Wrap(err, "failed to unmarshal") + return + } + + if msg.ResponseError > 0 { + err = errors.New(msg.ResponseMessage) return } fmt.Println("Response:", msg) @@ -107,7 +156,7 @@ func zoneEntityList(zone string, instanceID int) (entities []*eqproto.Entity) { channel := fmt.Sprintf("zone.%s.command_message.in", zone) reply, err := nc.Request(channel, d, 1*time.Second) if err != nil { - log.Println("Failed to get response on", channel, "", err.Error()) + log.Println("Failed to get response on", channel, err.Error()) return } @@ -116,15 +165,14 @@ func zoneEntityList(zone string, instanceID int) (entities []*eqproto.Entity) { fmt.Println("Failed to unmarshal", err.Error()) return } - - if msg.Result != "1" { - fmt.Println("Failed response: ", msg.Result) + if msg.ResponseError > 0 { + fmt.Println("Failed to get entity list:", msg.ResponseError, msg.ResponseMessage) return } //fmt.Println("reply", len(msg.Payload), string(msg.Payload)) rootEntities := &eqproto.Entities{} - err = proto.Unmarshal([]byte(msg.Payload), rootEntities) + err = proto.Unmarshal([]byte(msg.ResponsePayload), rootEntities) if err != nil { fmt.Println("failed to unmarshal entities", err.Error(), msg) return @@ -133,7 +181,7 @@ func zoneEntityList(zone string, instanceID int) (entities []*eqproto.Entity) { return } -func zoneCommandEntity(zone string, command string, params []string) (entityID int64) { +func zoneCommandEntity(zone string, command string, params []string) (entityID int32) { msg := &eqproto.CommandMessage{ Author: "xackery", Command: command, @@ -154,12 +202,13 @@ func zoneCommandEntity(zone string, command string, params []string) (entityID i fmt.Println("Failed to unmarshal", err.Error()) return } - fmt.Println("Response:", msg) - entityID, err = strconv.ParseInt(msg.Result, 10, 64) - if err != nil { - fmt.Println("Failed to parse response", err.Error(), msg.Result) + //fmt.Println("Response:", msg) + if msg.ResponseError > 0 { + fmt.Println("Failed to get response:", msg.ResponseError, msg.ResponseMessage) return } + + entityID = msg.ResponseValue return } @@ -190,20 +239,6 @@ func zoneCommand(zone string, command string, params []string) { func entityEventSubscriber(zone string, instance int64, entityID int32) { - /*event := &eqproto.EntityEvent{ - Entity: &eqproto.Entity{ - Id: 1, - }, - } - d, err := proto.Marshal(event) - if err != nil { - log.Fatal(err) - } - if err = nc.Publish(fmt.Sprintf("zone.%s.entity.event_subscribe.all", zone), d); err != nil { - log.Println("Failed to publish event subscribe:", err.Error()) - return - }*/ - var index int channel := fmt.Sprintf("zone.%s.%d.entity.%d.event.out", zone, instance, entityID) @@ -212,6 +247,7 @@ func entityEventSubscriber(zone string, instance int64, entityID int32) { err = proto.Unmarshal(m.Data, event) if err != nil { fmt.Println("invalid event data passed", m.Data) + return } var eventPayload proto.Message diff --git a/world/nats_manager.cpp b/world/nats_manager.cpp index 2e1a7dfbf..8d877682e 100644 --- a/world/nats_manager.cpp +++ b/world/nats_manager.cpp @@ -3,6 +3,7 @@ #include "zonelist.h" #include "login_server_list.h" #include "clientlist.h" +#include "cliententry.h" #include "worlddb.h" #include @@ -98,7 +99,7 @@ void NatsManager::Process() break; eqproto::ChannelMessage* message = google::protobuf::Arena::CreateMessage(&the_arena); - if (!message->ParseFromString(natsMsg_GetData(msg))) { + if (!message->ParseFromArray(natsMsg_GetData(msg), natsMsg_GetDataLength(msg))) { Log(Logs::General, Logs::NATS, "world.channel_message.in: failed to parse"); natsMsg_Destroy(msg); continue; @@ -115,11 +116,11 @@ void NatsManager::Process() break; eqproto::CommandMessage* message = google::protobuf::Arena::CreateMessage(&the_arena); - if (!message->ParseFromString(natsMsg_GetData(msg))) { + if (!message->ParseFromArray(natsMsg_GetData(msg), natsMsg_GetDataLength(msg))) { Log(Logs::General, Logs::NATS, "world.command_message.in: failed to parse"); natsMsg_Destroy(msg); continue; - } + } GetCommandMessage(message, natsMsg_GetReply(msg)); } } @@ -191,10 +192,6 @@ void NatsManager::SendCommandMessage(eqproto::CommandMessage* message, const cha if (!connect()) return; - if (message->result().length() <= 1) - message->set_result("Failed to parse command."); - - size_t event_size = message->ByteSizeLong(); void *event_buffer = malloc(event_size); if (!message->SerializeToArray(event_buffer, event_size)) { @@ -209,11 +206,11 @@ void NatsManager::SendCommandMessage(eqproto::CommandMessage* message, const cha s = natsConnection_Publish(conn, "world.command_message.out", event_buffer, event_size); if (s != NATS_OK) { - Log(Logs::General, Logs::NATS, "world.command_message.out failed: %s"); + Log(Logs::General, Logs::NATS, "world.command_message.out failed: %s", nats_GetLastError(&s)); return; } - Log(Logs::General, Logs::NATS, "world.command_message.in: %s (%s)", message->command().c_str(), message->result().c_str()); + Log(Logs::General, Logs::NATS, "world.command_message.in: %s (%d: %s)", message->command().c_str(), message->response_error(), message->response_message().c_str()); } // GetCommandMessage is used to process a command message @@ -222,7 +219,7 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char return; if (message->command().compare("who") == 0) { - message->set_result(client_list.GetWhoAll()); + message->set_response_message(client_list.GetWhoAll()); SendCommandMessage(message, reply); return; } @@ -231,7 +228,7 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char WorldConfig::UnlockWorld(); if (loginserverlist.Connected()) loginserverlist.SendStatus(); - message->set_result("Server is now unlocked."); + message->set_response_message("Server is now unlocked."); SendCommandMessage(message, reply); return; } @@ -240,7 +237,7 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char WorldConfig::LockWorld(); if (loginserverlist.Connected()) loginserverlist.SendStatus(); - message->set_result("Server is now locked."); + message->set_response_message("Server is now locked."); SendCommandMessage(message, reply); return; } @@ -250,26 +247,27 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char uint32 interval=0; if(message->params_size() == 2 && ((time=atoi(message->params(0).c_str()))>0) && ((interval=atoi(message->params(1).c_str()))>0)) { - message->set_result(StringFormat("Sending shutdown packet now, World will shutdown in: %i minutes with an interval of: %i seconds", (time / 60), interval)); + message->set_response_message(StringFormat("Sending shutdown packet now, World will shutdown in: %i minutes with an interval of: %i seconds", (time / 60), interval)); zoneserver_list.WorldShutDown(time, interval); SendCommandMessage(message, reply); return; } else if(strcasecmp(message->params(0).c_str(), "now") == 0){ - message->set_result("Sending shutdown packet now"); + message->set_response_message("Sending shutdown packet now"); zoneserver_list.WorldShutDown(0, 0); SendCommandMessage(message, reply); return; } else if(strcasecmp(message->params(0).c_str(), "disable") == 0){ - message->set_result("Shutdown prevented, next time I may not be so forgiving..."); + message->set_response_message("Shutdown prevented, next time I may not be so forgiving..."); zoneserver_list.SendEmoteMessage(0, 0, 0, 15, ":SYSTEM MSG:World shutdown aborted."); zoneserver_list.shutdowntimer->Disable(); zoneserver_list.reminder->Disable(); SendCommandMessage(message, reply); return; } - message->set_result("worldshutdown - Shuts down the server and all zones.\n \ + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("worldshutdown - Shuts down the server and all zones.\n \ Usage: worldshutdown now - Shuts down the server and all zones immediately.\n \ Usage: worldshutdown disable - Stops the server from a previously scheduled shut down.\n \ Usage: worldshutdown [timer] [interval] - Shuts down the server and all zones after [timer] seconds and sends warning every [interval] seconds\n"); @@ -277,7 +275,8 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char return; } - message->set_result("unknown command sent"); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Unknown command"); SendCommandMessage(message, reply); return; } @@ -289,21 +288,60 @@ void NatsManager::GetChannelMessage(eqproto::ChannelMessage* message, const char if (message->is_emote()) { //emote message zoneserver_list.SendEmoteMessage(message->to().c_str(), message->guilddbid(), message->minstatus(), message->type(), message->message().c_str()); - message->set_result("Sent message"); + message->set_response_message("Success"); SendChannelMessage(message, reply); return; } //normal broadcast - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], message->from().c_str()); - //TODO: add To support on tells + char from[64]; + from[0] = '*'; + strcpy(&from[1], message->from().c_str()); + + int channel = message->number(); - if (channel < 1) + if (channel < 1) { channel = MT_OOC; //default to ooc - zoneserver_list.SendChannelMessage(tmpname, 0, channel, message->language(), message->message().c_str()); - message->set_result("1"); + message->set_number(eqproto::OOC); + } + + if (message->to().length() == 0) { //Send a world message + zoneserver_list.SendChannelMessage(from, 0, channel, message->language(), message->message().c_str()); + message->set_response_message("Success"); + SendChannelMessage(message, reply); + return; + } + + + //Send a tell + + channel = 7; //tells are always echo + message->set_number(static_cast(7)); + ClientListEntry* cle = client_list.FindCharacter(message->to().c_str()); + if (cle == 0 || cle->Online() < CLE_Status_Zoning || + (cle->TellsOff() && ((cle->Anon() == 1 && message->fromadmin() < cle->Admin()) || message->fromadmin() < 80))) { + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message("Player is offline"); + SendChannelMessage(message, reply); + return; + } + + if (cle->Online() == CLE_Status_Zoning) { + if (cle->TellQueueFull()) { + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message("Queue is full"); + SendChannelMessage(message, reply); + return; + } + + //This should succeed in going into a tell queue, since it doesn't return we have to detect above + zoneserver_list.SendChannelMessage(from, message->to().c_str(), channel, message->language(), message->message().c_str()); + message->set_response_message("Player is zoning, tell is queued"); + SendChannelMessage(message, reply); + return; + } + zoneserver_list.SendChannelMessage(from, message->to().c_str(), channel, message->language(), message->message().c_str()); + message->set_response_message("Success"); SendChannelMessage(message, reply); return; } @@ -334,7 +372,7 @@ void NatsManager::SendChannelMessage(eqproto::ChannelMessage* message, const cha } if (reply) - Log(Logs::General, Logs::NATS, "world.channel_message.in: %s (%s)", message->message().c_str(), message->result().c_str()); + Log(Logs::General, Logs::NATS, "world.channel_message.in: %s (%d: %s)", message->message().c_str(), message->response_error(), message->response_message().c_str()); else Log(Logs::General, Logs::NATS, "world.channel_message.out: %s", message->message().c_str()); } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 0c8ef58b9..88c822cc2 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -31,9 +31,11 @@ #include "queryserv.h" #include "questmgr.h" #include "zone.h" +#include "nats_manager.h" extern Zone* zone; extern QueryServ* QServ; +extern NatsManager nats; /* @@ -2882,6 +2884,21 @@ XS(XS__varlink) { XSRETURN(1); } +XS(XS__adminmessage); // prototype to pass -Wmissing-prototypes +XS(XS__adminmessage) { + dXSARGS; + + if (items == 1) + nats.SendAdminMessage(SvPV_nolen(ST(0))); + else if (items == 2) + nats.SendAdminMessage(SvPV_nolen(ST(0)), (int)SvIV(ST(1))); + else + Perl_croak(aTHX_ "Usage: adminmessage(message [, min_status])"); + + XSRETURN_EMPTY; +} + + XS(XS__CreateInstance); XS(XS__CreateInstance) { dXSARGS; @@ -3766,6 +3783,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "addldonwin"), XS__addldonpoints, file); newXS(strcpy(buf, "addloot"), XS__addloot, file); newXS(strcpy(buf, "addskill"), XS__addskill, file); + newXS(strcpy(buf, "adminmessage"), XS__adminmessage, file); newXS(strcpy(buf, "assigntask"), XS__assigntask, file); newXS(strcpy(buf, "attack"), XS__attack, file); newXS(strcpy(buf, "attacknpc"), XS__attacknpc, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index ec22fec1b..c34b50ffb 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -22,6 +22,7 @@ #include "qglobals.h" #include "encounter.h" #include "lua_encounter.h" +#include "nats_manager.h" struct Events { }; struct Factions { }; @@ -45,6 +46,7 @@ struct lua_registered_event { extern std::map> lua_encounter_events_registered; extern std::map lua_encounters_loaded; extern std::map lua_encounters; +extern NatsManager nats; extern void MapOpcodes(); extern void ClearMappedOpcode(EmuOpcode op); @@ -1320,6 +1322,10 @@ void lua_debug(std::string message, int level) { Log(static_cast(level), Logs::QuestDebug, message); } +void lua_adminmessage(std::string message) { + nats.SendAdminMessage(message); +} + void lua_update_zone_header(std::string type, std::string value) { quest_manager.UpdateZoneHeader(type, value); } @@ -1698,8 +1704,9 @@ luabind::scope lua_register_general() { luabind::def("reloadzonestaticdata", &lua_reloadzonestaticdata), luabind::def("clock", &lua_clock), luabind::def("create_npc", &lua_create_npc), - luabind::def("debug", (void(*)(std::string))&lua_debug), - luabind::def("debug", (void(*)(std::string, int))&lua_debug) + luabind::def("debug", (void(*)(std::string))&lua_debug), + luabind::def("debug", (void(*)(std::string, int))&lua_debug), + luabind::def("adminmessage", &lua_adminmessage) ]; } diff --git a/zone/nats_manager.cpp b/zone/nats_manager.cpp index da84cd49d..306979c64 100644 --- a/zone/nats_manager.cpp +++ b/zone/nats_manager.cpp @@ -58,7 +58,7 @@ void NatsManager::Process() break; eqproto::CommandMessage* message = google::protobuf::Arena::CreateMessage(&the_arena); - if (!message->ParseFromString(natsMsg_GetData(msg))) { + if (!message->ParseFromArray(natsMsg_GetData(msg), natsMsg_GetDataLength(msg))) { Log(Logs::General, Logs::NATS, "zone.%s.command_message.in: failed to parse", subscribedZoneName.c_str()); natsMsg_Destroy(msg); continue; @@ -75,7 +75,7 @@ void NatsManager::Process() break; eqproto::CommandMessage* message = google::protobuf::Arena::CreateMessage(&the_arena); - if (!message->ParseFromString(natsMsg_GetData(msg))) { + if (!message->ParseFromArray(natsMsg_GetData(msg), natsMsg_GetDataLength(msg))) { Log(Logs::General, Logs::NATS, "zone.%s.%dcommand_message.in: failed to parse", subscribedZoneName.c_str(), subscribedZoneInstance); natsMsg_Destroy(msg); continue; @@ -92,7 +92,7 @@ void NatsManager::Process() break; eqproto::ChannelMessage* message = google::protobuf::Arena::CreateMessage(&the_arena); - if (!message->ParseFromString(natsMsg_GetData(msg))) { + if (!message->ParseFromArray(natsMsg_GetData(msg), natsMsg_GetDataLength(msg))) { Log(Logs::General, Logs::NATS, "zone.%s.channel_message.in: failed to parse", subscribedZoneName.c_str()); natsMsg_Destroy(msg); continue; @@ -109,7 +109,7 @@ void NatsManager::Process() break; eqproto::ChannelMessage* message = google::protobuf::Arena::CreateMessage(&the_arena); - if (!message->ParseFromString(natsMsg_GetData(msg))) { + if (!message->ParseFromArray(natsMsg_GetData(msg), natsMsg_GetDataLength(msg))) { Log(Logs::General, Logs::NATS, "zone.%s.%d.channel_message.in: failed to parse", subscribedZoneName.c_str(), subscribedZoneInstance); natsMsg_Destroy(msg); continue; @@ -125,7 +125,8 @@ void NatsManager::GetChannelMessage(eqproto::ChannelMessage* message, const char return; if (message->from_entity_id() < 1) { - message->set_result("from_entity_id must be set to send zone channel messages."); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("from_entity_id must be set to send zone channel messages."); SendChannelMessage(message, reply); return; } @@ -133,7 +134,8 @@ void NatsManager::GetChannelMessage(eqproto::ChannelMessage* message, const char auto mob = entity_list.GetMobID(message->from_entity_id()); if (!mob) { - message->set_result("from_entity_id not found"); + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message("mob from_entity_id not found"); SendChannelMessage(message, reply); return; } @@ -143,7 +145,8 @@ void NatsManager::GetChannelMessage(eqproto::ChannelMessage* message, const char else mob->Message(message->number(), message->message().c_str()); - message->set_result("1"); + + message->set_response_message("Success"); SendChannelMessage(message, reply); return; } @@ -173,7 +176,7 @@ void NatsManager::SendChannelMessage(eqproto::ChannelMessage* message, const cha } if (reply) - Log(Logs::General, Logs::NATS, "zone.%s.%d.channel_message.in: %s (%s)", subscribedZoneName.c_str(), subscribedZoneInstance, message->message().c_str(), message->result().c_str()); + Log(Logs::General, Logs::NATS, "zone.%s.%d.channel_message.in: %s (%d: %s)", subscribedZoneName.c_str(), subscribedZoneInstance, message->message().c_str(), message->response_error(), message->response_message().c_str()); else Log(Logs::General, Logs::NATS, "zone.%s.%d.channel_message.out: %s", subscribedZoneName.c_str(), subscribedZoneInstance, message->message().c_str()); } @@ -186,7 +189,8 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char if (message->command().compare("npctypespawn") == 0) { if (message->params_size() < 2) { - message->set_result("Format: npctypespawn "); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Format: npctypespawn "); SendCommandMessage(message, reply); return; } @@ -201,7 +205,8 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char uint32 factionid = atoi(message->params(5).c_str()); const NPCType* tmp = 0; if (!(tmp = database.LoadNPCTypesData(npctypeid))) { - message->set_result(StringFormat("NPC Type %i not found", npctypeid)); + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message(StringFormat("NPC of typied %i not found", npctypeid)); SendCommandMessage(message, reply); return; } @@ -210,7 +215,8 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char auto npc = new NPC(tmp, 0, position, FlyMode3); if (!npc) { - message->set_result("failed to instantiate npc"); + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message("Failed to create npc"); SendCommandMessage(message, reply); return; } @@ -219,14 +225,16 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char npc->SetNPCFactionID(factionid); npc->AddLootTable(); entity_list.AddNPC(npc); - message->set_result(StringFormat("%u", npc->GetID())); + message->set_response_message("Success"); + message->set_response_value(npc->GetID()); SendCommandMessage(message, reply); return; } if (message->command().compare("spawn") == 0) { if (message->params_size() < 5) { - message->set_result("Format: spawn - spawns a npc those parameters."); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Requires minimum 5 arguments. Format: spawn - spawns a npc those parameters."); SendCommandMessage(message, reply); return; } @@ -244,19 +252,22 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char NPC* npc = NPC::SpawnNPC(argumentString.c_str(), position, NULL); if (!npc) { - message->set_result("Format: spawn - spawns a npc those parameters."); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Failed to spawn npc with provided arguments."); SendCommandMessage(message, reply); return; } - message->set_result(StringFormat("%u", npc->GetID())); + message->set_response_message("Success"); + message->set_response_value(npc->GetID()); SendCommandMessage(message, reply); return; } if (message->command().compare("moveto") == 0) { if (message->params_size() < 5) { - message->set_result("Usage: moveto ."); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Usage: moveto ."); SendCommandMessage(message, reply); return; } @@ -270,20 +281,22 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char auto npc = entity_list.GetNPCByID(entityid); if (!npc) { - message->set_result("Invalid entity ID passed, or not an npc, etc"); + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message("Could not find npcid"); SendCommandMessage(message, reply); return; } - npc->MoveTo(position, true); - message->set_result("1"); + npc->MoveTo(position, true); + message->set_response_message("Success"); SendCommandMessage(message, reply); return; } if (message->command().compare("attack") == 0) { if (message->params_size() < 3) { - message->set_result("Usage: attack ."); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Usage: attack ."); SendCommandMessage(message, reply); return; } @@ -293,19 +306,22 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char auto npc = entity_list.GetNPCByID(entityID); if (!npc) { - message->set_result("Invalid entity ID passed, or not an npc, etc"); + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message("npc ID not found"); SendCommandMessage(message, reply); return; } auto mob = entity_list.GetMobID(targetEntityID); if (!mob) { - message->set_result("Invalid target entitiy ID passed, or not a mob, etc"); + message->set_response_error(eqproto::ERR_Failed); + message->set_response_message("target mob ID not found"); SendCommandMessage(message, reply); return; } npc->AddToHateList(mob, hateAmount); - message->set_result("1"); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); SendCommandMessage(message, reply); return; } @@ -313,7 +329,8 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char if (message->command().compare("entitylist") == 0) { std::string entityPayload; if (message->params_size() < 1) { - message->set_result("Usage: entitylist . Types: npc, client, mob, mercenary, corpse, door, object"); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Usage: entitylist . Types: npc, client, mob, mercenary, corpse, door, object"); SendCommandMessage(message, reply); return; } @@ -334,12 +351,14 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char size_t size = entities->ByteSizeLong(); void *buffer = malloc(size); if (!entities->SerializeToArray(buffer, size)) { - message->set_result("Failed to serialize entitiy result"); + message->set_response_message("Failed to serialize entity result"); + message->set_response_error(eqproto::ERR_Internal); SendCommandMessage(message, reply); return; } - message->set_result("1"); - message->set_payload(buffer, size); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); + message->set_response_payload(buffer, size); SendCommandMessage(message, reply); return; } @@ -357,12 +376,14 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char size_t size = entities->ByteSizeLong(); void *buffer = malloc(size); if (!entities->SerializeToArray(buffer, size)) { - message->set_result("Failed to serialize entitiy result"); + message->set_response_message("Failed to serialize entity result"); + message->set_response_error(eqproto::ERR_Internal); SendCommandMessage(message, reply); return; } - message->set_result("1"); - message->set_payload(buffer, size); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); + message->set_response_payload(buffer, size); SendCommandMessage(message, reply); return; } @@ -380,12 +401,14 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char size_t size = entities->ByteSizeLong(); void *buffer = malloc(size); if (!entities->SerializeToArray(buffer, size)) { - message->set_result("Failed to serialize entitiy result"); + message->set_response_message("Failed to serialize entity result"); + message->set_response_error(eqproto::ERR_Internal); SendCommandMessage(message, reply); return; } - message->set_result("1"); - message->set_payload(buffer, size); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); + message->set_response_payload(buffer, size); SendCommandMessage(message, reply); return; } @@ -403,12 +426,14 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char size_t size = entities->ByteSizeLong(); void *buffer = malloc(size); if (!entities->SerializeToArray(buffer, size)) { - message->set_result("Failed to serialize entitiy result"); + message->set_response_message("Failed to serialize entity result"); + message->set_response_error(eqproto::ERR_Internal); SendCommandMessage(message, reply); return; } - message->set_result("1"); - message->set_payload(buffer, size); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); + message->set_response_payload(buffer, size); SendCommandMessage(message, reply); return; } @@ -426,12 +451,14 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char size_t size = entities->ByteSizeLong(); void *buffer = malloc(size); if (!entities->SerializeToArray(buffer, size)) { - message->set_result("Failed to serialize entitiy result"); + message->set_response_message("Failed to serialize entity result"); + message->set_response_error(eqproto::ERR_Internal); SendCommandMessage(message, reply); return; } - message->set_result("1"); - message->set_payload(buffer, size); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); + message->set_response_payload(buffer, size); SendCommandMessage(message, reply); return; } @@ -450,12 +477,14 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char size_t size = entities->ByteSizeLong(); void *buffer = malloc(size); if (!entities->SerializeToArray(buffer, size)) { - message->set_result("Failed to serialize entitiy result"); + message->set_response_message("Failed to serialize entity result"); + message->set_response_error(eqproto::ERR_Internal); SendCommandMessage(message, reply); return; } - message->set_result("1"); - message->set_payload(buffer, size); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); + message->set_response_payload(buffer, size); SendCommandMessage(message, reply); return; } @@ -473,21 +502,25 @@ void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char size_t size = entities->ByteSizeLong(); void *buffer = malloc(size); if (!entities->SerializeToArray(buffer, size)) { - message->set_result("Failed to serialize entitiy result"); + message->set_response_message("Failed to serialize entity result"); + message->set_response_error(eqproto::ERR_Internal); SendCommandMessage(message, reply); return; } - message->set_result("1"); - message->set_payload(buffer, size); + message->set_response_message("Success"); + message->set_response_type("CommandMessage"); + message->set_response_payload(buffer, size); SendCommandMessage(message, reply); return; } - message->set_result("Usage: entitylist . Types: npc, client, mob, mercenary, corpse, door, object"); + message->set_response_error(eqproto::ERR_Request); + message->set_response_message("Usage: entitylist . Types: npc, client, mob, mercenary, corpse, door, object"); SendCommandMessage(message, reply); return; } - message->set_result("Failed to parse command."); + message->set_response_message("Failed to parse command."); + message->set_response_error(eqproto::ERR_Request); SendCommandMessage(message, reply); return; } @@ -498,9 +531,6 @@ void NatsManager::SendCommandMessage(eqproto::CommandMessage* message, const cha if (!connect()) return; - if (message->result().length() == 0) - message->set_result("Failed to parse command."); - size_t size = message->ByteSizeLong(); void *buffer = malloc(size); @@ -521,7 +551,7 @@ void NatsManager::SendCommandMessage(eqproto::CommandMessage* message, const cha return; } - Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: %s (%s)", subscribedZoneName.c_str(), subscribedZoneInstance, message->command().c_str(), message->result().c_str()); + Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: %s (%d: %s)", subscribedZoneName.c_str(), subscribedZoneInstance, message->command().c_str(), message->response_error(), message->response_message().c_str()); } //Unregister is called when a zone is being put to sleep or being swapped @@ -570,6 +600,7 @@ void NatsManager::Unregister() void NatsManager::SendEvent(eqproto::OpCode op, uint32 entity_id, void * buffer, size_t size) { eqproto::Event* event = google::protobuf::Arena::CreateMessage(&the_arena); + event->set_payload(buffer, size); event->set_op(op); event->set_entity_id(entity_id); @@ -638,13 +669,13 @@ void NatsManager::ZoneSubscribe(const char* zonename, uint32 instance) { } -void NatsManager::SendAdminMessage(std::string adminMessage) { +void NatsManager::SendAdminMessage(std::string adminMessage, int min_status) { if (!connect()) return; eqproto::ChannelMessage* message = google::protobuf::Arena::CreateMessage(&the_arena); message->set_message(adminMessage.c_str()); - + message->set_minstatus(min_status); size_t size = message->ByteSizeLong(); void *buffer = malloc(size); diff --git a/zone/nats_manager.h b/zone/nats_manager.h index f67e9827f..01185141e 100644 --- a/zone/nats_manager.h +++ b/zone/nats_manager.h @@ -28,7 +28,7 @@ public: void SendChannelMessage(eqproto::ChannelMessage* message, const char* reply = nullptr); void GetCommandMessage(eqproto::CommandMessage* message, const char* reply = nullptr); void SendCommandMessage(eqproto::CommandMessage* message, const char* reply = nullptr); - void SendAdminMessage(std::string adminMessage); + void SendAdminMessage(std::string adminMessage, int min_status = 200); void SendEvent(eqproto::OpCode op, uint32 entity_id, void * buffer, size_t size); void OnAlternateAdvancementStats(uint32 entity_id, AltAdvStats_Struct * aas);