mirror of
https://github.com/EQEmu/Server.git
synced 2026-02-16 08:42:25 +00:00
Massive overhaul on zone/nats_manager
This commit is contained in:
parent
b0f591540c
commit
6532a81b80
@ -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;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
//Makes a player walk around in ecommons near Guard Reskin
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
245
utils/nats/playersay/playersay.go
Normal file
245
utils/nats/playersay/playersay.go
Normal 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)
|
||||
}
|
||||
@ -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())
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user