Massive overhaul on zone/nats_manager

This commit is contained in:
Xackery 2018-03-13 15:29:28 -07:00
parent b0f591540c
commit 6532a81b80
9 changed files with 753 additions and 451 deletions

View File

@ -19,22 +19,26 @@ message ChannelMessage {
bool is_emote = 12;
//0 not queued, 1 queued, 2 queue full, 3 offline
int32 queued = 13;
string result = 15;
string result = 15; //Result of channel request. 1 = Success, Non-numeric = error
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?
}
message CommandMessage {
string author = 1;
string command = 2;
repeated string params = 3;
string result = 4;
bytes payload = 5;
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
}
//Entity is full of entity data.
message Entity {
int32 id = 1;
string name = 2;
int32 type = 3;
string name = 2;
EntityType type = 3; //0 - NPC, 1 - Client
int32 hp = 4;
int32 level = 5;
Position position = 6;
@ -94,8 +98,9 @@ message Tint {
}
message Event {
OpCode op = 1;
bytes payload = 2;
OpCode op = 1; //opcode enum
bytes payload = 2; //unmarshal based on opcode
uint32 entity_id = 3; //target entity_id of event
}
//OP_Death
@ -294,6 +299,18 @@ message SpawnEvent {
bool show_name= 100;
}
//EntityType will attempt to identify an entity to it's upper-most type by default
enum EntityType {
NPC = 0; //Inherits mob
Client = 1; //Inherits mob
Mob = 2; //Inherits entity
Mercenary = 3; //Inherits NPC
Corpse = 4; //Inherits mob
Door = 5; //Inherits entity
Object = 6; //Inherits entity
}
enum OpCode {
//option allow_alias = true;
OP_Unknown = 0;

View File

@ -1,3 +1,4 @@
//Makes a player walk around in ecommons near Guard Reskin
package main
import (

View File

@ -0,0 +1,245 @@
//Makes a player say a message in local chat
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"
)
var (
nc *nats.Conn
err error
entities []*eqproto.Entity
)
func main() {
if nc, err = nats.Connect(nats.DefaultURL); err != nil {
log.Fatal(err)
}
defer nc.Close()
zone := "ecommons"
instance := int64(0)
entities = zoneEntityList(zone, 0)
fmt.Println(len(entities), "entities known")
var entityID int32
for _, entity := range entities {
if entity.Name == "Shin" {
fmt.Println("Found Shin as ID", entity.Id)
entityID = entity.Id
break
}
}
if entityID == 0 {
log.Fatal("Can't find entity!")
}
go entityEventSubscriber(zone, instance, entityID)
zoneChannel(zone, instance, entityID, eqproto.EntityType_Client, 256, "Hello, World!")
time.Sleep(1000 * time.Second)
}
func zoneChannel(zone string, instance int64, fromEntityID int32, fromEntityType eqproto.EntityType, chanNumber int32, message string) {
msg := &eqproto.ChannelMessage{
Message: message,
ChanNum: chanNumber,
FromEntityId: fromEntityID,
FromEntityType: fromEntityType,
Distance: 500,
SkipSender: true,
}
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)
reply, err := nc.Request(channel, d, 1*time.Second)
if err != nil {
log.Println("Failed to get request response on zone channel:", err.Error())
return
}
err = proto.Unmarshal(reply.Data, msg)
if err != nil {
fmt.Println("Failed to unmarshal", err.Error())
return
}
fmt.Println("Response:", msg)
return
}
func testAttack(zone string, entityID int64, targetID int64) {
time.Sleep(10 * time.Second)
fmt.Println("10 seconds, Having", entityID, "attack", targetID)
params := []string{
fmt.Sprintf("%d", entityID),
fmt.Sprintf("%d", targetID), //attack first element
"1", //amount of hate
}
command := "attack"
zoneCommand(zone, command, params)
}
func zoneEntityList(zone string, instanceID int) (entities []*eqproto.Entity) {
msg := &eqproto.CommandMessage{
Author: "xackery",
Command: "entitylist",
Params: []string{"client"},
}
d, err := proto.Marshal(msg)
if err != nil {
log.Fatal(err)
}
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())
return
}
err = proto.Unmarshal(reply.Data, msg)
if err != nil {
fmt.Println("Failed to unmarshal", err.Error())
return
}
rootEntities := &eqproto.Entities{}
err = proto.Unmarshal([]byte(msg.Payload), rootEntities)
if err != nil {
fmt.Println("failed to unmarshal entities", err.Error(), msg)
return
}
entities = rootEntities.Entities
return
}
func zoneCommandEntity(zone string, command string, params []string) (entityID int64) {
msg := &eqproto.CommandMessage{
Author: "xackery",
Command: command,
Params: params,
}
d, err := proto.Marshal(msg)
if err != nil {
log.Fatal(err)
}
reply, err := nc.Request(fmt.Sprintf("zone.%s.command_message.in", zone), d, 1*time.Second)
if err != nil {
log.Println("Failed to get request response:", err.Error())
return
}
err = proto.Unmarshal(reply.Data, msg)
if err != nil {
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)
return
}
return
}
func zoneCommand(zone string, command string, params []string) {
msg := &eqproto.CommandMessage{
Author: "xackery",
Command: command,
Params: params,
}
d, err := proto.Marshal(msg)
if err != nil {
log.Fatal(err)
}
reply, err := nc.Request(fmt.Sprintf("zone.%s.command_message.in", zone), d, 1*time.Second)
if err != nil {
log.Println("Failed to get request response:", err.Error())
return
}
err = proto.Unmarshal(reply.Data, msg)
if err != nil {
fmt.Println("Failed to unmarshal", err.Error())
return
}
fmt.Println("Response:", msg)
return
}
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 opCode int64
var index int
channel := fmt.Sprintf("zone.%s.%d.entity.%d.event.out", zone, instance, entityID)
nc.Subscribe(channel, func(m *nats.Msg) {
event := &eqproto.Event{}
err = proto.Unmarshal(m.Data, event)
if err != nil {
fmt.Println("invalid event data passed", m.Data)
}
var eventPayload proto.Message
switch event.Op {
case eqproto.OpCode_OP_ClientUpdate:
eventPayload = &eqproto.PlayerPositionUpdateEvent{}
case eqproto.OpCode_OP_Animation:
eventPayload = &eqproto.AnimationEvent{}
case eqproto.OpCode_OP_NewSpawn:
eventPayload = &eqproto.SpawnEvent{}
case eqproto.OpCode_OP_ZoneEntry:
eventPayload = &eqproto.SpawnEvent{}
case eqproto.OpCode_OP_HPUpdate:
eventPayload = &eqproto.HPEvent{}
case eqproto.OpCode_OP_MobHealth:
eventPayload = &eqproto.HPEvent{}
case eqproto.OpCode_OP_DeleteSpawn:
eventPayload = &eqproto.DeleteSpawnEvent{}
case eqproto.OpCode_OP_Damage:
eventPayload = &eqproto.DamageEvent{}
default:
return
}
err = proto.Unmarshal(event.Payload, eventPayload)
if err != nil {
fmt.Println("Invalid data passed for opcode", eqproto.OpCode(opCode), err.Error(), string(m.Data[index+1:]))
return
}
fmt.Println(m.Subject, event.Op, eventPayload)
//log.Printf("Received a message on %s: %s\n", m.Subject, string(m.Data))
//proto.Unmarshal(m.Data, event)
//log.Println(event.Op.String(), event.Entity, event.Target)
})
log.Println("Subscribed to", channel, ", waiting on messages...")
time.Sleep(500 * time.Second)
}

View File

@ -73,13 +73,13 @@ bool NatsManager::connect() {
Log(Logs::General, Logs::NATS, "connected to %s", connection.c_str());
nats_timer.Disable();
s = natsConnection_SubscribeSync(&channelMessageSub, conn, "world.channel_message->in");
s = natsConnection_SubscribeSync(&channelMessageSub, conn, "world.channel_message.in");
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "world.channel_message->in: failed to subscribe: %s", nats_GetLastError(&s));
Log(Logs::General, Logs::NATS, "world.channel_message.in: failed to subscribe: %s", nats_GetLastError(&s));
s = natsConnection_SubscribeSync(&commandMessageSub, conn, "world.command_message->in");
s = natsConnection_SubscribeSync(&commandMessageSub, conn, "world.command_message.in");
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "world.command_message->in: failed to subscribe: %s", nats_GetLastError(&s));
Log(Logs::General, Logs::NATS, "world.command_message.in: failed to subscribe: %s", nats_GetLastError(&s));
return true;
}
@ -99,7 +99,7 @@ void NatsManager::Process()
eqproto::ChannelMessage* message = google::protobuf::Arena::CreateMessage<eqproto::ChannelMessage>(&the_arena);
if (!message->ParseFromString(natsMsg_GetData(msg))) {
Log(Logs::General, Logs::NATS, "world.channel_message->in: failed to parse");
Log(Logs::General, Logs::NATS, "world.channel_message.in: failed to parse");
natsMsg_Destroy(msg);
continue;
}
@ -116,7 +116,7 @@ void NatsManager::Process()
eqproto::CommandMessage* message = google::protobuf::Arena::CreateMessage<eqproto::CommandMessage>(&the_arena);
if (!message->ParseFromString(natsMsg_GetData(msg))) {
Log(Logs::General, Logs::NATS, "world.command_message->in: failed to parse");
Log(Logs::General, Logs::NATS, "world.command_message.in: failed to parse");
natsMsg_Destroy(msg);
continue;
}
@ -183,28 +183,6 @@ void NatsManager::SendAdminMessage(std::string adminMessage, const char* reply)
Log(Logs::General, Logs::NATS, "global.admin_message.out: %s", adminMessage.c_str());
}
// SendChannelMessage will send a channel message to NATS
void NatsManager::SendChannelMessage(eqproto::ChannelMessage* message, const char* reply) {
if (!connect())
return;
std::string pubMessage;
if (!message->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "world.channel_message.out: failed to serialize message to string");
return;
}
if (reply && strlen(reply) > 0)
s = natsConnection_Publish(conn, reply, (const void*)pubMessage.c_str(), pubMessage.length());
else
s = natsConnection_Publish(conn, "world.channel_message.out", (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK) {
Log(Logs::General, Logs::NATS, "world.channel_message.out failed: %s");
return;
}
Log(Logs::General, Logs::NATS, "world.channel_message.out: %s", message->message().c_str());
}
// SendCommandMessage will send a channel message to NATS
void NatsManager::SendCommandMessage(eqproto::CommandMessage* message, const char* reply) {
@ -307,8 +285,6 @@ void NatsManager::GetChannelMessage(eqproto::ChannelMessage* message, const char
if (!connect())
return;
Log(Logs::General, Logs::NATS, "world.channel_message->in: %s", message->message().c_str());
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");
@ -325,11 +301,41 @@ void NatsManager::GetChannelMessage(eqproto::ChannelMessage* message, const char
if (channel < 1)
channel = 5; //default to ooc
zoneserver_list.SendChannelMessage(tmpname, 0, channel, message->language(), message->message().c_str());
message->set_result("Sent message");
message->set_result("1");
SendChannelMessage(message, reply);
return;
}
// SendChannelMessage will send a channel message to NATS
void NatsManager::SendChannelMessage(eqproto::ChannelMessage* message, const char* reply) {
if (!connect())
return;
std::string pubMessage;
if (!message->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "world.channel_message.out: failed to serialize message to string");
return;
}
if (reply) {
s = natsConnection_Publish(conn, reply, (const void*)pubMessage.c_str(), pubMessage.length());
}
else {
s = natsConnection_Publish(conn, "world.channel_message.out", (const void*)pubMessage.c_str(), pubMessage.length());
}
if (s != NATS_OK) {
Log(Logs::General, Logs::NATS, "world.channel_message.out failed: %s", nats_GetLastError(&s));
return;
}
if (reply)
Log(Logs::General, Logs::NATS, "world.channel_message.in: %s (%s)", message->message().c_str(), message->result().c_str());
else
Log(Logs::General, Logs::NATS, "world.channel_message.out: %s", message->message().c_str());
}
void NatsManager::Load()
{
if (!connect())

View File

@ -4879,16 +4879,3 @@ void EntityList::ReloadMerchants() {
}
}
}
std::map<uint16, NPC *> EntityList::ListNPCs()
{
std::map<uint16, NPC*> npcs;
auto it = npc_list.begin();
while (it != npc_list.end()) {
NPC *n = it->second;
npcs[n->id] = n;
++it;
}
return npcs;
}

View File

@ -216,7 +216,7 @@ public:
return it->second;
return nullptr;
}
std::map<uint16, NPC*> ListNPCs();
Doors *GetDoorsByDoorID(uint32 id);
Doors *GetDoorsByDBID(uint32 id);
void RemoveAllCorpsesByCharID(uint32 charid);

View File

@ -1,6 +1,6 @@
#include "entity.h"
#include "mob.h"
//#include "client.h" //map error
#include "client.h"
#include "event_codes.h"
#include "nats.h"
#include "zone_config.h"
@ -13,6 +13,7 @@
#include "../common/string_util.h"
#ifndef PROTO_H
#define PROTO_H
#undef new //needed for linux compile
#include "../common/message.pb.h"
#endif
#include <google/protobuf/arena.h>
@ -51,196 +52,388 @@ void NatsManager::Process()
for (int count = 0; (s == NATS_OK) && count < 5; count++)
{
s = natsSubscription_NextMsg(&msg, zoneCommandMessageSub, 1);
if (s != NATS_OK) {
s = natsSubscription_NextMsg(&msg, zoneInstanceCommandMessageSub, 1);
if (s != NATS_OK) {
break;
}
}
if (s != NATS_OK)
break;
eqproto::CommandMessage* message = google::protobuf::Arena::CreateMessage<eqproto::CommandMessage>(&the_arena);
if (!message->ParseFromString(natsMsg_GetData(msg))) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: failed to parse", subscribedZoneName.c_str(), subscribedZoneInstance);
Log(Logs::General, Logs::NATS, "zone.%s.command_message.in: failed to parse", subscribedZoneName.c_str());
natsMsg_Destroy(msg);
continue;
}
if (message->command().compare("npctypespawn") == 0) {
if (message->params_size() < 2) {
message->set_result("Usage: !npctypespawn <npctypeid> <factionid> <x> <y> <z> <h>.");
} else {
uint32 npctypeid = atoi(message->params(0).c_str());
uint32 factionid = atoi(message->params(1).c_str());
float x = atof(message->params(2).c_str());
float y = atof(message->params(3).c_str());
float z = atof(message->params(4).c_str());
float h = atof(message->params(5).c_str());
auto position = glm::vec4(x, y, z, h);
const NPCType* tmp = 0;
/*if (!(tmp = database.LoadNPCTypesData(npctypeid))) {
message->set_result(StringFormat("NPC Type %i not found", npctypeid));
} else {
//tmp->fixedZ = 1;
auto npc = new NPC(tmp, 0, position, FlyMode3);
if (npc && factionid >0)
npc->SetNPCFactionID(factionid);
npc->AddLootTable();
entity_list.AddNPC(npc);
message->set_result("Created NPC successfully.");
}
*/
}
}
if (message->command().compare("npctypespawn") == 0) {
if (message->params_size() < 5) {
message->set_result("Usage: npctypespawn <x> <y> <z> <h> name race level material hp gender class priweapon secweapon merchantid bodytype.");
}
else {
float x = atof(message->params(0).c_str());
float y = atof(message->params(1).c_str());
float z = atof(message->params(2).c_str());
float h = atof(message->params(3).c_str());
auto position = glm::vec4(x, y, z, h);
std::string argumentString;
for (int i = 4; i < message->params_size(); i++) {
argumentString.append(StringFormat(" %s", message->params(i).c_str()));
}
NPC* npc = NPC::SpawnNPC(argumentString.c_str(), position, NULL);
if (!npc) {
message->set_result("Format: #spawn name race level material hp gender class priweapon secweapon merchantid bodytype - spawns a npc those parameters.");
}
else {
message->set_result(StringFormat("%u", npc->GetID()));
}
}
}
if (message->command().compare("moveto") == 0) {
if (message->params_size() < 5) {
message->set_result("Usage: moveto <entityid> <x> <y> <z> <h>.");
}
else {
uint16 entityid = atoi(message->params(0).c_str());
float x = atof(message->params(1).c_str());
float y = atof(message->params(2).c_str());
float z = atof(message->params(3).c_str());
float h = atof(message->params(4).c_str());
auto position = glm::vec4(x, y, z, h);
auto npc = entity_list.GetNPCByID(entityid);
if (!npc) {
message->set_result("Invalid entity ID passed, or not an npc, etc");
}
else {
npc->MoveTo(position, true);
message->set_result("OK");
}
}
}
if (message->command().compare("attack") == 0) {
if (message->params_size() < 3) {
message->set_result("Usage: attack <entityid> <targetentityid> <hateamount>.");
}
else {
uint16 entityID = atoi(message->params(0).c_str());
uint16 targetEntityID = atoi(message->params(1).c_str());
uint32 hateAmount = atoi(message->params(2).c_str());
auto npc = entity_list.GetNPCByID(entityID);
if (!npc) {
message->set_result("Invalid entity ID passed, or not an npc, etc");
}
else {
auto mob = entity_list.GetMobID(targetEntityID);
if (!mob) {
message->set_result("Invalid target entitiy ID passed, or not a mob, etc");
}
else {
npc->AddToHateList(mob, hateAmount);
message->set_result("OK");
}
}
}
}
if (message->command().compare("entitylist") == 0) {
std::string entityPayload;
if (message->params_size() < 1) {
message->set_result("Usage: entitylist <typeid>.");
}
else {
eqproto::Entities* entities = google::protobuf::Arena::CreateMessage<eqproto::Entities>(&the_arena);
if (message->params(0).compare("npc") == 0) {
auto npcs = entity_list.ListNPCs();
auto it = npcs.begin();
for (const auto &entry : npcs) {
auto entity = entities->add_entities();
entity->set_id(entry.second->GetID());
entity->set_type(1);
entity->set_name(entry.second->GetName());
}
if (!entities->SerializeToString(&entityPayload)) {
message->set_result("Failed to serialized entitiy result");
}
else {
message->set_result("OK");
message->set_payload(entityPayload.c_str());
}
}
/*else if (message->params(0).compare("client") == 0) {
auto clients = entity_list.ListClients();
auto it = clients.begin();
for (const auto &entry : clients) {
auto entity = entities->add_entities();
entity->set_id(entry.second->GetID());
entity->set_type(0);
entity->set_name(entry.second->GetName());
}
if (!entities->SerializeToString(&entityMessage)) {
message->set_result("Failed to serialized entitiy result");
}
else {
message->set_result(entityMessage.c_str());
}
}*/
else {
message->set_result("Usage: entitylist <typeid>.");
}
}
}
if (message->result().length() < 1) {
message->set_result("Failed to parse command.");
Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: failed to parse command", subscribedZoneName.c_str(), subscribedZoneInstance);
natsMsg_Destroy(msg);
continue;
}
if (!message->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: failed to serialize to string", subscribedZoneName.c_str(), subscribedZoneInstance);
natsMsg_Destroy(msg);
continue;
}
s = natsConnection_Publish(conn, natsMsg_GetReply(msg), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: failed to publish: %s", subscribedZoneName.c_str(), subscribedZoneInstance, nats_GetLastError(&s));
natsMsg_Destroy(msg);
continue;
}
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());
GetCommandMessage(message, natsMsg_GetReply(msg));
natsMsg_Destroy(msg);
}
s = NATS_OK;
for (int count = 0; (s == NATS_OK) && count < 5; count++)
{
s = natsSubscription_NextMsg(&msg, zoneInstanceCommandMessageSub, 1);
if (s != NATS_OK)
break;
eqproto::CommandMessage* message = google::protobuf::Arena::CreateMessage<eqproto::CommandMessage>(&the_arena);
if (!message->ParseFromString(natsMsg_GetData(msg))) {
Log(Logs::General, Logs::NATS, "zone.%s.%dcommand_message.in: failed to parse", subscribedZoneName.c_str(), subscribedZoneInstance);
natsMsg_Destroy(msg);
continue;
}
GetCommandMessage(message, natsMsg_GetReply(msg));
natsMsg_Destroy(msg);
}
s = NATS_OK;
for (int count = 0; (s == NATS_OK) && count < 5; count++)
{
s = natsSubscription_NextMsg(&msg, zoneChannelMessageSub, 1);
if (s != NATS_OK)
break;
eqproto::ChannelMessage* message = google::protobuf::Arena::CreateMessage<eqproto::ChannelMessage>(&the_arena);
if (!message->ParseFromString(natsMsg_GetData(msg))) {
Log(Logs::General, Logs::NATS, "zone.%s.channel_message.in: failed to parse", subscribedZoneName.c_str());
natsMsg_Destroy(msg);
continue;
}
GetChannelMessage(message, natsMsg_GetReply(msg));
natsMsg_Destroy(msg);
}
s = NATS_OK;
for (int count = 0; (s == NATS_OK) && count < 5; count++)
{
s = natsSubscription_NextMsg(&msg, zoneInstanceChannelMessageSub, 1);
if (s != NATS_OK)
break;
eqproto::ChannelMessage* message = google::protobuf::Arena::CreateMessage<eqproto::ChannelMessage>(&the_arena);
if (!message->ParseFromString(natsMsg_GetData(msg))) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.channel_message.in: failed to parse", subscribedZoneName.c_str(), subscribedZoneInstance);
natsMsg_Destroy(msg);
continue;
}
GetChannelMessage(message, natsMsg_GetReply(msg));
natsMsg_Destroy(msg);
}
}
// GetChannelMessage is when a 3rd party app sends a channel message via NATS.
void NatsManager::GetChannelMessage(eqproto::ChannelMessage* message, const char* reply) {
if (!connect())
return;
if (message->from_entity_id() < 1) {
message->set_result("from_entity_id must be set to send zone channel messages.");
SendChannelMessage(message, reply);
return;
}
auto mob = entity_list.GetMobID(message->from_entity_id());
if (!mob) {
message->set_result("from_entity_id not found");
SendChannelMessage(message, reply);
return;
}
if (message->distance() > 0)
entity_list.MessageClose(mob, message->skip_sender(), message->distance(), message->chan_num(), message->message().c_str());
else
mob->Message(message->chan_num(), message->message().c_str());
message->set_result("1");
SendChannelMessage(message, reply);
return;
}
// SendChannelMessage will send a channel message to NATS
void NatsManager::SendChannelMessage(eqproto::ChannelMessage* message, const char* reply) {
if (!connect())
return;
std::string pubMessage;
if (!message->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "world.channel_message.out: failed to serialize message to string");
return;
}
if (reply)
s = natsConnection_Publish(conn, reply, (const void*)pubMessage.c_str(), pubMessage.length());
else
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.channel_message.out", subscribedZoneName.c_str(), subscribedZoneInstance).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK) {
Log(Logs::General, Logs::NATS, "world.channel_message.out failed: %s", nats_GetLastError(&s));
return;
}
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());
else
Log(Logs::General, Logs::NATS, "zone.%s.%d.channel_message.out: %s", subscribedZoneName.c_str(), subscribedZoneInstance, message->message().c_str());
}
// GetCommandMessage is used to process a command message
void NatsManager::GetCommandMessage(eqproto::CommandMessage* message, const char* reply) {
if (!connect())
return;
if (message->command().compare("npctypespawn") == 0) {
if (message->params_size() < 2) {
message->set_result("Format: npctypespawn <x> <y> <z> <h> <npctypeid> <factionid>");
SendCommandMessage(message, reply);
return;
}
float x = atof(message->params(0).c_str());
float y = atof(message->params(1).c_str());
float z = atof(message->params(2).c_str());
float h = atof(message->params(3).c_str());
auto position = glm::vec4(x, y, z, h);
uint32 npctypeid = atoi(message->params(4).c_str());
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));
SendCommandMessage(message, reply);
return;
}
//tmp->fixedZ = 1;
auto npc = new NPC(tmp, 0, position, FlyMode3);
if (!npc) {
message->set_result("failed to instantiate npc");
SendCommandMessage(message, reply);
return;
}
if (factionid > 0)
npc->SetNPCFactionID(factionid);
npc->AddLootTable();
entity_list.AddNPC(npc);
message->set_result(StringFormat("%u", npc->GetID()));
SendCommandMessage(message, reply);
return;
}
if (message->command().compare("spawn") == 0) {
if (message->params_size() < 5) {
message->set_result("Format: spawn <x> <y> <z> <h> <name> <race> <level> <material> <hp> <gender> <class> <priweapon> <secweapon> <merchantid> <bodytype> - spawns a npc those parameters.");
SendCommandMessage(message, reply);
return;
}
float x = atof(message->params(0).c_str());
float y = atof(message->params(1).c_str());
float z = atof(message->params(2).c_str());
float h = atof(message->params(3).c_str());
auto position = glm::vec4(x, y, z, h);
std::string argumentString;
for (int i = 4; i < message->params_size(); i++) {
argumentString.append(StringFormat(" %s", message->params(i).c_str()));
}
NPC* npc = NPC::SpawnNPC(argumentString.c_str(), position, NULL);
if (!npc) {
message->set_result("Format: spawn <x> <y> <z> <h> <name> <race> <level> <material> <hp> <gender> <class> <priweapon> <secweapon> <merchantid> <bodytype> - spawns a npc those parameters.");
SendCommandMessage(message, reply);
return;
}
message->set_result(StringFormat("%u", npc->GetID()));
SendCommandMessage(message, reply);
return;
}
if (message->command().compare("moveto") == 0) {
if (message->params_size() < 5) {
message->set_result("Usage: moveto <entityid> <x> <y> <z> <h>.");
SendCommandMessage(message, reply);
return;
}
uint16 entityid = atoi(message->params(0).c_str());
float x = atof(message->params(1).c_str());
float y = atof(message->params(2).c_str());
float z = atof(message->params(3).c_str());
float h = atof(message->params(4).c_str());
auto position = glm::vec4(x, y, z, h);
auto npc = entity_list.GetNPCByID(entityid);
if (!npc) {
message->set_result("Invalid entity ID passed, or not an npc, etc");
SendCommandMessage(message, reply);
return;
}
npc->MoveTo(position, true);
message->set_result("1");
SendCommandMessage(message, reply);
return;
}
if (message->command().compare("attack") == 0) {
if (message->params_size() < 3) {
message->set_result("Usage: attack <entityid> <targetentityid> <hateamount>.");
SendCommandMessage(message, reply);
return;
}
uint16 entityID = atoi(message->params(0).c_str());
uint16 targetEntityID = atoi(message->params(1).c_str());
uint32 hateAmount = atoi(message->params(2).c_str());
auto npc = entity_list.GetNPCByID(entityID);
if (!npc) {
message->set_result("Invalid entity ID passed, or not an npc, etc");
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");
SendCommandMessage(message, reply);
return;
}
npc->AddToHateList(mob, hateAmount);
message->set_result("1");
SendCommandMessage(message, reply);
return;
}
if (message->command().compare("entitylist") == 0) {
std::string entityPayload;
if (message->params_size() < 1) {
message->set_result("Usage: entitylist <type>. Types: npc, client, mob, mercenary, corpse, door, object");
SendCommandMessage(message, reply);
return;
}
eqproto::Entities* entities = google::protobuf::Arena::CreateMessage<eqproto::Entities>(&the_arena);
if (message->params(0).compare("npc") == 0) {
auto npcs = entity_list.GetNPCList();
auto it = npcs.begin();
for (const auto &entry : npcs) {
if (entry.second == nullptr)
continue;
auto npc = entry.second;
auto entity = entities->add_entities();
entity->set_id(npc->GetID());
entity->set_type(eqproto::EntityType::NPC);
entity->set_name(npc->GetName());
}
if (!entities->SerializeToString(&entityPayload)) {
message->set_result("Failed to serialize entitiy result");
SendCommandMessage(message, reply);
return;
}
message->set_result("1");
message->set_payload(entityPayload.c_str());
SendCommandMessage(message, reply);
return;
}
else if (message->params(0).compare("client") == 0) {
auto clients = entity_list.GetClientList();
auto it = clients.begin();
for (const auto &entry : clients) {
if (entry.second == nullptr)
continue;
auto client = entry.second;
auto entity = entities->add_entities();
entity->set_type(eqproto::EntityType::Client);
entity->set_name(client->GetName());
entity->set_id(client->GetID());
}
if (!entities->SerializeToString(&entityPayload)) {
message->set_result("Failed to serialize entitiy result");
SendCommandMessage(message, reply);
return;
}
message->set_result("1");
message->set_payload(entityPayload.c_str());
SendCommandMessage(message, reply);
return;
}
else if (message->params(0).compare("mob") == 0) {
auto mobs = entity_list.GetMobList();
auto it = mobs.begin();
for (const auto &entry : mobs) {
if (entry.second == nullptr)
continue;
auto mob = entry.second;
auto entity = entities->add_entities();
entity->set_type(eqproto::EntityType::Mob);
if (mob->IsClient())
entity->set_type(eqproto::EntityType::Client);
if (mob->IsNPC())
entity->set_type(eqproto::EntityType::NPC);
if (mob->IsMerc())
entity->set_type(eqproto::EntityType::Mercenary);
entity->set_id(mob->GetID());
entity->set_name(mob->GetName());
}
if (!entities->SerializeToString(&entityPayload)) {
message->set_result("Failed to serialize entitiy result");
SendCommandMessage(message, reply);
return;
}
message->set_result("1");
message->set_payload(entityPayload.c_str());
SendCommandMessage(message, reply);
return;
}
message->set_result("Usage: entitylist <type>. Types: npc, client, mob, mercenary, corpse, door, object");
SendCommandMessage(message, reply);
return;
}
message->set_result("Failed to parse command.");
SendCommandMessage(message, reply);
return;
}
// SendCommandMessage will send a channel message to NATS
void NatsManager::SendCommandMessage(eqproto::CommandMessage* message, const char* reply) {
if (!connect())
return;
if (message->result().length() == 0)
message->set_result("Failed to parse command.");
std::string pubMessage;
if (!message->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: failed to serialize to string", subscribedZoneName.c_str(), subscribedZoneInstance);
return;
}
if (reply)
s = natsConnection_Publish(conn, reply, (const void*)pubMessage.c_str(), pubMessage.length());
else
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.command_message.out", subscribedZoneName.c_str(), subscribedZoneInstance).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.command_message.in: failed: %s", subscribedZoneName.c_str(), subscribedZoneInstance, nats_GetLastError(&s));
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());
}
//Unregister is called when a zone is being put to sleep or being swapped
@ -286,6 +479,24 @@ void NatsManager::Unregister()
return;
}
void NatsManager::SendEvent(eqproto::OpCode op, uint32 entity_id, std::string pubMessage) {
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(op);
finalEvent->set_entity_id(entity_id);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
}
void NatsManager::ZoneSubscribe(const char* zonename, uint32 instance) {
if (strcmp(subscribedZoneName.c_str(), zonename) == 0)
return;
@ -404,89 +615,6 @@ void NatsManager::Load()
return;
}
/*
void NatsManager::OnEntityEvent(const EmuOpcode op, Entity *ent, Entity *target) {
if (ent == NULL) return;
if (!isEntityEventAllEnabled && !isEntitySubscribed(ent->GetID())) {
return;
}
if (!conn) {
Log(Logs::General, Logs::NATS, "OnChannelMessage failed, no connection to NATS");
return;
}
eqproto::EntityEvent event;
event->set_op(eqproto::OpCode(op));
eqproto::Entity entity;
entity.set_id(ent->GetID());
entity.set_name(ent->GetName());
if (ent->IsClient()) {
entity.set_type(1);
}
else if (ent->IsNPC()) {
entity.set_type(2);
}
auto position = eqproto::Position();
if (ent->IsMob()) {
auto mob = ent->CastToMob();
entity.set_hp(mob->GetHP());
entity.set_level(mob->GetLevel());
entity.set_name(mob->GetName());
position.set_x(mob->GetX());
position.set_y(mob->GetY());
position.set_z(mob->GetZ());
position.set_h(mob->GetHeading());
entity.set_race(mob->GetRace());
entity.set_class_(mob->GetClass());
}
auto targetEntity = eqproto::Entity();
auto targetPosition = eqproto::Position();
if (target != NULL && target->IsMob()) {
if (target->IsClient()) {
targetEntity.set_type(1);
}
else if (target->IsNPC()) {
targetEntity.set_type(2);
}
auto mob = target->CastToMob();
targetEntity.set_hp(mob->GetHP());
targetEntity.set_level(mob->GetLevel());
targetEntity.set_name(mob->GetName());
targetPosition.set_x(mob->GetX());
targetPosition.set_y(mob->GetY());
targetPosition.set_z(mob->GetZ());
targetPosition.set_h(mob->GetHeading());
targetEntity.set_race(mob->GetRace());
targetEntity.set_class_(mob->GetClass());
}
entity.set_allocated_position(&position);
targetEntity.set_allocated_position(&targetPosition);
event->set_allocated_entity(&entity);
event->set_allocated_target(&targetEntity);
std::string pubMessage;
bool isSerialized = event->SerializeToString(&pubMessage);
if (!isSerialized) Log(Logs::General, Logs::NATS, "Failed to serialize message to string");
Log(Logs::General, Logs::NATS, "Event: %d", op);
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event->%d", subscribedZonename.c_str(), ent->GetID()).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
entity.release_name();
targetEntity.release_name();
entity.release_position();
targetEntity.release_position();
event->release_entity();
event->release_target();
return;
}*/
bool NatsManager::isEntitySubscribed(const uint16 ID) {
if (!connect())
return false;
@ -505,7 +633,6 @@ void NatsManager::OnDeathEvent(Death_Struct* d) {
return;
auto op = eqproto::OP_Death;
std::string pubMessage;
eqproto::DeathEvent* event = google::protobuf::Arena::CreateMessage<eqproto::DeathEvent>(&the_arena);
@ -521,17 +648,8 @@ void NatsManager::OnDeathEvent(Death_Struct* d) {
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(op);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, d->spawn_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, d->spawn_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, d->spawn_id, op, nats_GetLastError(&s));
SendEvent(op, d->spawn_id, pubMessage);
SendEvent(op, d->killer_id, pubMessage);
}
@ -561,17 +679,6 @@ void NatsManager::OnChannelMessageEvent(uint32 entity_id, ChannelMessage_Struct*
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(eqproto::OP_ChannelMessage);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.channel_message.out: failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.channel_message.out", subscribedZoneName.c_str(), subscribedZoneInstance).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
}
void NatsManager::OnEntityEvent(const EmuOpcode op, uint32 entity_id, uint32 target_id) {
@ -598,24 +705,20 @@ void NatsManager::OnEntityEvent(const EmuOpcode op, uint32 entity_id, uint32 tar
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
auto eqop = eqproto::OP_Camp;
if (op == OP_Camp) {
finalEvent->set_op(eqproto::OP_Camp);
eqop = eqproto::OP_Camp;
}
else if (op == OP_Assist) {
finalEvent->set_op(eqproto::OP_Assist);
eqop = eqproto::OP_Assist;
}
else {
Log(Logs::General, Logs::NATS, "unhandled op type passed: %i", op);
return;
}
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(eqop, entity_id, pubMessage);
SendEvent(eqop, target_id, pubMessage);
}
@ -744,25 +847,16 @@ void NatsManager::OnSpawnEvent(const EmuOpcode op, uint32 entity_id, Spawn_Struc
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
if (op == OP_ZoneEntry)
finalEvent->set_op(eqproto::OP_ZoneEntry);
else if (op == OP_NewSpawn)
finalEvent->set_op(eqproto::OP_NewSpawn);
auto eqop = eqproto::OP_ZoneEntry;
if (op == OP_ZoneEntry)
eqop = eqproto::OP_ZoneEntry;
else if (op == OP_NewSpawn)
eqop = eqproto::OP_NewSpawn;
else {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) unhandled opcode passed", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(eqop, entity_id, pubMessage);
}
@ -790,18 +884,8 @@ void NatsManager::OnWearChangeEvent(uint32 entity_id, WearChange_Struct *wc) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(op);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(op, entity_id, pubMessage);
}
void NatsManager::OnDeleteSpawnEvent(uint32 entity_id, DeleteSpawn_Struct *ds) {
@ -823,18 +907,7 @@ void NatsManager::OnDeleteSpawnEvent(uint32 entity_id, DeleteSpawn_Struct *ds) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(op);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(op, entity_id, pubMessage);
}
void NatsManager::OnHPEvent(const EmuOpcode op, uint32 entity_id, uint32 cur_hp, uint32 max_hp) {
@ -858,25 +931,16 @@ void NatsManager::OnHPEvent(const EmuOpcode op, uint32 entity_id, uint32 cur_hp,
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
if (op == OP_MobHealth)
finalEvent->set_op(eqproto::OP_MobHealth);
else if (op == OP_HPUpdate)
finalEvent->set_op(eqproto::OP_HPUpdate);
auto eqop = eqproto::OP_MobHealth;
if (op == OP_MobHealth)
eqop = eqproto::OP_MobHealth;
else if (op == OP_HPUpdate)
eqop = eqproto::OP_HPUpdate;
else {
Log(Logs::General, Logs::NATS, "unhandled op type passed: %i", op);
return;
}
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(eqop, entity_id, pubMessage);
}
void NatsManager::OnDamageEvent(uint32 entity_id, CombatDamage_Struct *cd) {
@ -905,17 +969,8 @@ void NatsManager::OnDamageEvent(uint32 entity_id, CombatDamage_Struct *cd) {
Log(Logs::General, Logs::NATS, "Failed to serialize message to string");
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(op);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(op, entity_id, pubMessage);
}
void NatsManager::OnClientUpdateEvent(uint32 entity_id, PlayerPositionUpdateServer_Struct * spu) {
@ -949,18 +1004,8 @@ void NatsManager::OnClientUpdateEvent(uint32 entity_id, PlayerPositionUpdateServ
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(op);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(op, entity_id, pubMessage);
}
@ -985,17 +1030,5 @@ void NatsManager::OnAnimationEvent(uint32 entity_id, Animation_Struct *anim) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
eqproto::Event* finalEvent = google::protobuf::Arena::CreateMessage<eqproto::Event>(&the_arena);
finalEvent->set_payload(pubMessage.c_str());
finalEvent->set_op(op);
if (!finalEvent->SerializeToString(&pubMessage)) {
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to serialize message to string", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op);
return;
}
s = natsConnection_Publish(conn, StringFormat("zone.%s.%d.entity.%d.event.out", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
if (s != NATS_OK)
Log(Logs::General, Logs::NATS, "zone.%s.%d.entity.%d.event.out: (OP: %d) failed to send: %s", subscribedZoneName.c_str(), subscribedZoneInstance, entity_id, op, nats_GetLastError(&s));
SendEvent(op, entity_id, pubMessage);
}

View File

@ -1,13 +1,19 @@
#ifndef _NATS_H
#define _NATS_H
#include "nats.h"
#include "event_codes.h"
#include "entity.h"
#include "mob.h"
#include "nats.h"
//#include "event_codes.h"
//#include "entity.h"
//#include "mob.h"
#include "../common/opcodemgr.h"
#include "../common/global_define.h"
#include "../common/types.h"
//#include "../common/global_define.h"
//#include "../common/types.h"
#undef New //Needed for MSVC compile
#undef Move //Needed for linux compile
#ifndef PROTO_H
#define PROTO_H
#include "../common/message.pb.h"
#endif
class NatsManager
{
@ -18,6 +24,13 @@ public:
void Unregister();
void ZoneSubscribe(const char * zonename, uint32 instance);
void Load();
void GetChannelMessage(eqproto::ChannelMessage* message, const char* reply = nullptr);
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 SendEvent(eqproto::OpCode op, uint32 entity_id, std::string pubMessage);
void OnChannelMessageEvent(uint32 entity_id, ChannelMessage_Struct * cm);
void OnEntityEvent(const EmuOpcode op, uint32 entity_id, uint32 target_id);
void OnSpawnEvent(const EmuOpcode op, uint32 entity_id, Spawn_Struct * spawn);
@ -27,8 +40,8 @@ public:
void OnDamageEvent(uint32 entity_id, CombatDamage_Struct * cd);
void OnClientUpdateEvent(uint32 entity_id, PlayerPositionUpdateServer_Struct * spu);
void OnAnimationEvent(uint32 entity_id, Animation_Struct * anim);
void OnDeathEvent(Death_Struct * d);
void SendAdminMessage(std::string adminMessage);
void OnDeathEvent(Death_Struct * d);
protected:
bool connect();
Timer nats_timer;

View File

@ -72,7 +72,7 @@ struct item_tick_struct {
};
class Client;
class Map;
//class Map; //Unused? Needed to uncomment for NATS
class Mob;
class PathManager;
class WaterMap;