mirror of
https://github.com/EQEmu/Server.git
synced 2026-02-21 22:02:24 +00:00
Nats initial commit
This commit is contained in:
parent
0b97db9fd2
commit
c69b9a95b7
22
.gitignore
vendored
22
.gitignore
vendored
@ -23,17 +23,19 @@ CMakeFiles
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
Build/
|
||||
build/
|
||||
Build32/
|
||||
build32/
|
||||
Build64/
|
||||
build64/
|
||||
Build_32/
|
||||
build_32/
|
||||
Build_64/
|
||||
build_64/
|
||||
[Bb]uild/
|
||||
[Bb]uild32/
|
||||
[Bb]uild64/
|
||||
[Bb]uild_32/
|
||||
[Bb]uild_64/
|
||||
deploy/server/
|
||||
x64/
|
||||
x86/
|
||||
log/
|
||||
logs/
|
||||
|
||||
# Proto
|
||||
protobuf/csharp/*
|
||||
protobuf/go/*
|
||||
protobuf/java/*
|
||||
protobuf/python/*
|
||||
@ -52,7 +52,25 @@ IF(MSVC OR MINGW)
|
||||
ENDIF(CMAKE_CL_64)
|
||||
ENDIF(MSVC OR MINGW)
|
||||
|
||||
IF(MSVC)
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deploy/server")
|
||||
|
||||
# include dirs are universal
|
||||
SET(NATS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/nats")
|
||||
SET(PROTOBUF_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/protobuf")
|
||||
|
||||
SET(NATS_INCLUDE_DIR "${NATS_ROOT}/include")
|
||||
SET(PROTOBUF_INCLUDE_DIR "${PROTOBUF_ROOT}/include")
|
||||
|
||||
IF(MSVC)
|
||||
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
|
||||
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_CURRENT_SOURCE_DIR}/deploy/server" )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_CURRENT_SOURCE_DIR}/deploy/server" )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_CURRENT_SOURCE_DIR}/deploy/server" )
|
||||
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
|
||||
|
||||
|
||||
|
||||
#Set our default locations for zlib/mysql based on x86/x64
|
||||
IF(CMAKE_CL_64)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64")
|
||||
@ -67,12 +85,16 @@ IF(MSVC)
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
SET(NATS_LIBRARY "${NATS_ROOT}/lib_x64/nats.lib")
|
||||
SET(PROTOBUF_LIBRARY "${PROTOBUF_ROOT}/lib_x64/libprotobufd.lib")
|
||||
ELSE(CMAKE_CL_64)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86")
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
|
||||
SET(NATS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/nats_x86")
|
||||
SET(PROTOBUF_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/protobuf_x86")
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
@ -80,6 +102,8 @@ IF(MSVC)
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
SET(NATS_LIBRARY "${NATS_ROOT}/lib_x86/nats.lib")
|
||||
SET(PROTOBUF_LIBRARY "${PROTOBUF_ROOT}/lib_x86/libprotobufd.lib")
|
||||
ENDIF(CMAKE_CL_64)
|
||||
|
||||
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
|
||||
@ -131,6 +155,10 @@ IF(MSVC)
|
||||
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
ELSE(MSVC)
|
||||
|
||||
SET(NATS_LIBRARY "${NATS_ROOT}/lib_x64/libnats.so")
|
||||
SET(PROTOBUF_LIBRARY "${PROTOBUF_ROOT}/lib_x64/libprotobuf.so")
|
||||
|
||||
#Normally set by perl but we don't use the perl flags anymore so we set it.
|
||||
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
|
||||
ENDIF(MSVC)
|
||||
@ -309,7 +337,7 @@ IF(EQEMU_BUILD_PERL)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
||||
ENDIF(EQEMU_BUILD_PERL)
|
||||
|
||||
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt)
|
||||
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt ${NATS_LIBRARY} ${PROTOBUF_LIBRARY})
|
||||
|
||||
FIND_PACKAGE(Sodium REQUIRED)
|
||||
IF(SODIUM_FOUND)
|
||||
@ -352,6 +380,8 @@ ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${NATS_INCLUDE_DIR}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${PROTOBUF_INCLUDE_DIR}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/common/glm")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/include" )
|
||||
|
||||
@ -98,6 +98,7 @@ SET(common_sources
|
||||
patches/titanium_limits.cpp
|
||||
patches/uf.cpp
|
||||
patches/uf_limits.cpp
|
||||
proto/message.pb.cc
|
||||
StackWalker/StackWalker.cpp
|
||||
tinyxml/tinystr.cpp
|
||||
tinyxml/tinyxml.cpp
|
||||
@ -254,6 +255,7 @@ SET(common_headers
|
||||
patches/uf_limits.h
|
||||
patches/uf_ops.h
|
||||
patches/uf_structs.h
|
||||
proto/message.pb.h
|
||||
StackWalker/StackWalker.h
|
||||
tinyxml/tinystr.h
|
||||
tinyxml/tinyxml.h
|
||||
|
||||
@ -81,6 +81,10 @@ class EQEmuConfig
|
||||
std::string QSDatabaseDB;
|
||||
uint16 QSDatabasePort;
|
||||
|
||||
// From <nats/>
|
||||
std::string NATSHost;
|
||||
uint16 NATSPort;
|
||||
|
||||
// From <files/>
|
||||
std::string SpellsFile;
|
||||
std::string OpCodesFile;
|
||||
|
||||
@ -104,6 +104,7 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::MySQLError].log_to_console = Logs::General;
|
||||
log_settings[Logs::Login_Server].log_to_console = Logs::General;
|
||||
log_settings[Logs::Headless_Client].log_to_console = Logs::General;
|
||||
log_settings[Logs::NATS].log_to_console = Logs::General;
|
||||
|
||||
/* Set Category enabled status on defaults */
|
||||
log_settings[Logs::World_Server].is_category_enabled = 1;
|
||||
@ -113,6 +114,7 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::Crash].is_category_enabled = 1;
|
||||
log_settings[Logs::MySQLError].is_category_enabled = 1;
|
||||
log_settings[Logs::Login_Server].is_category_enabled = 1;
|
||||
log_settings[Logs::NATS].is_category_enabled = 1;
|
||||
|
||||
/* Declare process file names for log writing
|
||||
If there is no process_file_name declared, no log file will be written, simply
|
||||
|
||||
@ -90,6 +90,7 @@ enum LogCategory {
|
||||
FixZ,
|
||||
Food,
|
||||
Traps,
|
||||
NATS,
|
||||
MaxCategoryID /* Don't Remove this*/
|
||||
};
|
||||
|
||||
@ -144,7 +145,8 @@ static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
|
||||
"HP Update",
|
||||
"FixZ",
|
||||
"Food",
|
||||
"Traps"
|
||||
"Traps",
|
||||
"NATS"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
15056
common/proto/message.pb.cc
Normal file
15056
common/proto/message.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
9458
common/proto/message.pb.h
Normal file
9458
common/proto/message.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
8
protobuf/README.md
Normal file
8
protobuf/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Protobuf
|
||||
|
||||
* [https://developers.google.com/protocol-buffers/](Learn more about protobuf)
|
||||
* Version is 3.5.1 (latest). In order to modify *.pb.cpp files, you need to have the [https://github.com/google/protobuf/releases](protoc binary).
|
||||
* If you add any new .proto files, you need to include them into the CMakeList.txt entry of the respective dir, likely common/CMakeList.txt.
|
||||
* By default, the generated cpp files are placed in the common/proto/* directory, while this is not best practice to have them versioned as they are auto generated files, it simplifies compiling source by not requiring protoc. (Perhaps later, we can look into adding this flow into cmake)
|
||||
* Run build.bat or build.sh to build protobuf for different platforms.
|
||||
* Look at each language subdirectory to learn more about building them
|
||||
7
protobuf/build.bat
Normal file
7
protobuf/build.bat
Normal file
@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
del /q ..\common\proto\*
|
||||
del /q go\eqproto\*
|
||||
del /q python\proto\*pb2*
|
||||
del /q java\eqproto\*.java
|
||||
del /q csharp\proto\*.cs
|
||||
protoc --cpp_out=../common/proto --go_out=go/eqproto --python_out=python/proto --csharp_out=csharp/proto --java_out=java message.proto
|
||||
5
protobuf/build.sh
Normal file
5
protobuf/build.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Cleaning up existing .pb* files"
|
||||
rm -rf ../common/proto/* go/eqproto/* csharp/proto/*.cs java/eqproto/*.java python/proto/*pb2*
|
||||
protoc --cpp_out=../common/proto --go_out=go/eqproto --python_out=python/proto --csharp_out=csharp/proto --java_out=java message.proto
|
||||
883
protobuf/message.proto
Normal file
883
protobuf/message.proto
Normal file
@ -0,0 +1,883 @@
|
||||
syntax = "proto3";
|
||||
package eqproto;
|
||||
|
||||
message ChannelMessage {
|
||||
int32 chan_num = 1;
|
||||
int32 language = 2;
|
||||
string from = 3;
|
||||
string to = 4;
|
||||
string message = 5;
|
||||
int32 guilddbid = 6;
|
||||
string deliverto = 7;
|
||||
int32 type = 8;
|
||||
int32 minstatus = 9;
|
||||
int32 fromadmin = 10;
|
||||
bool noreply = 11;
|
||||
bool is_emote = 12;
|
||||
//0 not queued, 1 queued, 2 queue full, 3 offline
|
||||
int32 queued = 13;
|
||||
//You can specify a zone id if you want a message exclusively to one zone
|
||||
int32 zone_id = 14;
|
||||
}
|
||||
|
||||
message CommandMessage {
|
||||
string author = 1;
|
||||
string command = 2;
|
||||
repeated string params = 3;
|
||||
string result = 4;
|
||||
bytes payload = 5;
|
||||
}
|
||||
|
||||
//Daily Gain is a special system for tracking players progression in a daily snapshot.
|
||||
message DailyGain {
|
||||
int32 account_id = 1;
|
||||
int32 character_id = 2;
|
||||
int32 levels_gained = 3;
|
||||
int32 experience_gained = 4;
|
||||
int32 money_earned = 5;
|
||||
string identity = 6;
|
||||
}
|
||||
|
||||
//Entity is full of entity data.
|
||||
message Entity {
|
||||
int32 id = 1;
|
||||
string name = 2;
|
||||
int32 type = 3;
|
||||
int32 hp = 4;
|
||||
int32 level = 5;
|
||||
Position position = 6;
|
||||
int32 race = 7;
|
||||
int32 class = 8;
|
||||
}
|
||||
|
||||
message Entities {
|
||||
repeated Entity entities = 1;
|
||||
}
|
||||
|
||||
message Position {
|
||||
float x = 1;
|
||||
float y = 2;
|
||||
float z = 3;
|
||||
float h = 4;
|
||||
}
|
||||
|
||||
message TextureProfile {
|
||||
Texture Head = 1;
|
||||
Texture Chest = 2;
|
||||
Texture Arms = 3;
|
||||
Texture Wrist = 4;
|
||||
Texture Hands = 5;
|
||||
Texture Legs = 6;
|
||||
Texture Feet = 7;
|
||||
Texture Primary = 8;
|
||||
Texture Secondary = 9;
|
||||
}
|
||||
|
||||
message Texture {
|
||||
uint32 material = 1;
|
||||
uint32 unknown1 = 2;
|
||||
uint32 EliteModel = 3;
|
||||
uint32 HerosForgeModel = 4;
|
||||
uint32 Unknown2 = 5;
|
||||
}
|
||||
|
||||
message TintProfile {
|
||||
Tint Head = 1;
|
||||
Tint Chest = 2;
|
||||
Tint Arms = 3;
|
||||
Tint Wrist = 4;
|
||||
Tint Hands = 5;
|
||||
Tint Legs = 6;
|
||||
Tint Feet = 7;
|
||||
Tint Primary = 8;
|
||||
Tint Secondary = 9;
|
||||
}
|
||||
|
||||
message Tint {
|
||||
uint32 Blue = 1;
|
||||
uint32 Green = 2;
|
||||
uint32 Red = 3;
|
||||
uint32 UseTint = 4; // if there's a tint, this is FF
|
||||
uint32 Color = 5;
|
||||
}
|
||||
|
||||
message Event {
|
||||
OpCode op = 1;
|
||||
bytes payload = 2;
|
||||
}
|
||||
|
||||
//OP_Death
|
||||
message DeathEvent {
|
||||
uint32 spawn_id = 1;
|
||||
uint32 killer_id = 2;
|
||||
uint32 corpse_id = 3;
|
||||
uint32 bind_zone_id = 4;
|
||||
uint32 spell_id = 5;
|
||||
uint32 attack_skill_id = 6;
|
||||
uint32 damage = 7;
|
||||
uint32 unknown028 = 8;
|
||||
}
|
||||
|
||||
//OP_Damage
|
||||
message DamageEvent {
|
||||
uint32 target = 1;
|
||||
uint32 source = 2;
|
||||
uint32 type = 3; //slashing, etc. 231 (0xE7) for spells
|
||||
uint32 spellid = 4;
|
||||
uint32 damage = 5;
|
||||
float force = 6;
|
||||
float meleepush_xy = 7; // see above notes in Action_Struct
|
||||
float meleepush_z = 8;
|
||||
}
|
||||
|
||||
//OP_Assist OP_Camp
|
||||
message EntityEvent {
|
||||
uint32 entity_id = 1; //source of event trigger.
|
||||
uint32 target_id = 2; //target or other/source/target entity
|
||||
}
|
||||
|
||||
//OP_ChannelMessage
|
||||
message ChannelMessageEvent {
|
||||
string target_name = 1; // Tell recipient
|
||||
string sender = 2; // The senders name (len might be wrong)
|
||||
uint32 language = 3; // Language
|
||||
uint32 chan_num = 4; // Channel
|
||||
uint32 cm_unknown4 = 5; // ***Placeholder
|
||||
uint32 skill_in_language = 6; // The players skill in this language? might be wrong
|
||||
string message = 7; // Variable length message
|
||||
}
|
||||
|
||||
//OP_WearChange
|
||||
message WearChangeEvent {
|
||||
uint32 spawn_id = 1;
|
||||
uint32 material = 2;
|
||||
uint32 unknown06 = 3;
|
||||
uint32 elite_material = 4; // 1 for Drakkin Elite Material
|
||||
uint32 hero_forge_model = 5; // New to VoA
|
||||
uint32 unknown18 = 6; // New to RoF
|
||||
Tint color = 7;
|
||||
uint32 wear_slot_id = 8;
|
||||
}
|
||||
|
||||
//OP_DeleteSpawn
|
||||
message DeleteSpawnEvent {
|
||||
uint32 spawn_id = 1; // Spawn ID to delete
|
||||
uint32 decay = 2; // 0 = vanish immediately, 1 = 'Decay' sparklies for corpses.
|
||||
}
|
||||
|
||||
//OP_MobHealth, OP_HPUpdate
|
||||
message HPEvent {
|
||||
uint32 spawn_id = 1;
|
||||
uint32 cur_hp = 2;
|
||||
uint32 max_hp = 3;
|
||||
}
|
||||
|
||||
//OP_ClientUpdate
|
||||
message PlayerPositionUpdateEvent {
|
||||
uint32 spawn_id = 1;
|
||||
int32 delta_heading = 2; // change in heading
|
||||
int32 x_pos = 3; // x coord
|
||||
int32 padding0002 = 4; // ***Placeholder
|
||||
int32 y_pos = 5; // y coord
|
||||
int32 animation = 6; // animation
|
||||
int32 padding0006 = 7; // ***Placeholder
|
||||
int32 z_pos = 8; // z coord
|
||||
int32 delta_y = 9; // change in y
|
||||
int32 delta_x = 10; // change in x
|
||||
int32 heading = 11; // heading
|
||||
int32 padding0014 = 12; // ***Placeholder
|
||||
int32 delta_z = 13; // change in z
|
||||
int32 padding0018 = 14; // ***Placeholder
|
||||
}
|
||||
|
||||
//OP_Animation
|
||||
message AnimationEvent {
|
||||
uint32 spawnid = 1;
|
||||
uint32 speed = 2;
|
||||
uint32 action = 3;
|
||||
}
|
||||
|
||||
//OP_ZoneEntry OP_NewSpawn
|
||||
message SpawnEvent {
|
||||
uint32 unknown0000= 1;
|
||||
uint32 gm = 2; // 0=no, 1=gm
|
||||
uint32 unknown0003 = 3;
|
||||
uint32 aaitle = 4; // 0=none, 1=general, 2=archtype, 3=class
|
||||
uint32 unknown0004 = 5;
|
||||
uint32 anon = 6; // 0=normal, 1=anon, 2=roleplay
|
||||
uint32 face = 7; // Face id for players
|
||||
string name = 8; // Player's Name
|
||||
uint32 deity = 9; // Player's Deity
|
||||
uint32 unknown0073 = 10;
|
||||
float size = 11; // Model size
|
||||
uint32 unknown0079 = 12;
|
||||
uint32 NPC = 13; // 0=player,1=npc,2=pc corpse,3=npc corpse,a
|
||||
uint32 invis = 14; // Invis (0=not, 1=invis)
|
||||
uint32 haircolor = 15; // Hair color
|
||||
uint32 curHp = 16; // Current hp %%% wrong
|
||||
uint32 max_hp = 17; // (name prolly wrong)takes on the value 100 for players, 100 or 110 for NPCs and 120 for PC corpses...
|
||||
uint32 findable = 18; // 0=can't be found, 1=can be found
|
||||
uint32 unknown0089 = 19;
|
||||
int32 deltaHeading = 20; // change in heading
|
||||
int32 x = 21; // x coord
|
||||
int32 padding0054 = 22; // ***Placeholder
|
||||
int32 y = 23; // y coord
|
||||
int32 animation = 24; // animation
|
||||
int32 padding0058 = 25; // ***Placeholder
|
||||
int32 z = 26; // z coord
|
||||
int32 deltaY = 27; // change in y
|
||||
int32 deltaX = 28; // change in x
|
||||
uint32 heading = 29; // heading
|
||||
int32 padding0066 = 30; // ***Placeholder
|
||||
int32 deltaZ = 31; // change in z
|
||||
int32 padding0070 = 32; // ***Placeholder
|
||||
uint32 eyecolor1 = 33; // Player's left eye color
|
||||
uint32 unknown0115 = 34; // Was [24]
|
||||
uint32 StandState = 35; // stand state for SoF+ 0x64 for normal animation
|
||||
uint32 drakkin_heritage = 36; // Added for SoF
|
||||
uint32 drakkin_tattoo = 37; // Added for SoF
|
||||
uint32 drakkin_details = 38; // Added for SoF
|
||||
uint32 showhelm = 39; // 0=no, 1=yes
|
||||
uint32 unknown0140 = 40;
|
||||
uint32 is_npc = 41; // 0=no, 1=yes
|
||||
uint32 hairstyle = 42; // Hair style
|
||||
uint32 beard = 43; // Beard style (not totally, sure but maybe!)
|
||||
uint32 unknown0147 = 44;
|
||||
uint32 level = 45; // Spawn Level
|
||||
uint32 PlayerState = 46; // Controls animation stuff // None = 0, Open = 1, WeaponSheathed = 2, Aggressive = 4, ForcedAggressive = 8, InstrumentEquipped = 16, Stunned = 32, PrimaryWeaponEquipped = 64, SecondaryWeaponEquipped = 128
|
||||
uint32 beardcolor = 47; // Beard color
|
||||
string suffix = 48; // Player's suffix (of Veeshan, etc.)
|
||||
uint32 petOwnerId = 49; // If this is a pet, the spawn id of owner
|
||||
uint32 guildrank = 50; // 0=normal, 1=officer, 2=leader
|
||||
uint32 unknown0194 = 51;
|
||||
TextureProfile equipment = 52;
|
||||
float runspeed = 53; // Speed when running
|
||||
uint32 afk = 54; // 0=no, 1=afk
|
||||
uint32 guildID = 55; // Current guild
|
||||
string title = 56; // Title
|
||||
uint32 unknown0274 = 57; // non-zero prefixes name with '!'
|
||||
uint32 set_to_0xFF = 58; // ***Placeholder (all ff)
|
||||
uint32 helm = 59; // Helm texture
|
||||
uint32 race = 60; // Spawn race
|
||||
uint32 unknown0288 = 61;
|
||||
string lastName = 62; // Player's Lastname
|
||||
float walkspeed = 63; // Speed when walking
|
||||
uint32 unknown0328 = 64;
|
||||
uint32 is_pet = 65; // 0=no, 1=yes
|
||||
uint32 light = 66; // Spawn's lightsource %%% wrong
|
||||
uint32 class_ = 67; // Player's class
|
||||
uint32 eyecolor2 = 68; // Left eye color
|
||||
uint32 flymode = 69;
|
||||
uint32 gender = 70; // Gender (0=male, 1=female)
|
||||
uint32 bodytype = 71; // Bodytype
|
||||
uint32 unknown0336 = 72;
|
||||
//union
|
||||
uint32 equip_chest2 = 73; // Second place in packet for chest texture (usually 0xFF in live packets) // Not sure why there are 2 of them, but it effects chest texture!
|
||||
uint32 mount_color = 74; // drogmor: 0=white, 1=black, 2=green, 3=red horse: 0=brown, 1=white, 2=black, 3=tan
|
||||
//endunion
|
||||
uint32 spawnId = 75; // Spawn Id
|
||||
uint32 unknown0344 = 76;
|
||||
uint32 IsMercenary = 77;
|
||||
TintProfile equipment_tint = 78;
|
||||
uint32 lfg = 79; // 0=off, 1=lfg on
|
||||
bool DestructibleObject = 80; // Only used to flag as a destrible object
|
||||
string DestructibleModel = 82; // Model of the Destructible Object - Required - Seen "DEST_TNT_G"
|
||||
string DestructibleName2 = 83; // Secondary name - Not Required - Seen "a_tent"
|
||||
string DestructibleString = 84; // Unknown - Not Required - Seen "ZoneActor_01186"
|
||||
uint32 DestructibleAppearance = 85; // Damage Appearance
|
||||
uint32 DestructibleUnk1 = 86;
|
||||
uint32 DestructibleID1 = 87;
|
||||
uint32 DestructibleID2 = 88;
|
||||
uint32 DestructibleID3 = 89;
|
||||
uint32 DestructibleID4 = 90;
|
||||
uint32 DestructibleUnk2 = 91;
|
||||
uint32 DestructibleUnk3 = 92;
|
||||
uint32 DestructibleUnk4 = 93;
|
||||
uint32 DestructibleUnk5 = 94;
|
||||
uint32 DestructibleUnk6 = 95;
|
||||
uint32 DestructibleUnk7 = 96;
|
||||
uint32 DestructibleUnk8 = 97;
|
||||
uint32 DestructibleUnk9 = 98;
|
||||
bool targetable_with_hotkey = 99;
|
||||
bool show_name= 100;
|
||||
}
|
||||
|
||||
enum OpCode {
|
||||
//option allow_alias = true;
|
||||
OP_Unknown = 0;
|
||||
OP_ExploreUnknown = 1;
|
||||
OP_0x0193 = 2;
|
||||
OP_0x0347 = 3;
|
||||
OP_AAAction = 4;
|
||||
OP_AAExpUpdate = 5;
|
||||
OP_AcceptNewTask = 6;
|
||||
OP_AckPacket = 7;
|
||||
OP_Action = 8;
|
||||
OP_Action2 = 9;
|
||||
OP_AddNimbusEffect = 10;
|
||||
OP_AdventureData = 11;
|
||||
OP_AdventureDetails = 12;
|
||||
OP_AdventureFinish = 13;
|
||||
OP_AdventureInfo = 14;
|
||||
OP_AdventureInfoRequest = 15;
|
||||
OP_AdventureLeaderboardReply = 16;
|
||||
OP_AdventureLeaderboardRequest = 17;
|
||||
OP_AdventureMerchantPurchase = 18;
|
||||
OP_AdventureMerchantRequest = 19;
|
||||
OP_AdventureMerchantResponse = 20;
|
||||
OP_AdventureMerchantSell = 21;
|
||||
OP_AdventurePointsUpdate = 22;
|
||||
OP_AdventureRequest = 23;
|
||||
OP_AdventureStatsReply = 24;
|
||||
OP_AdventureStatsRequest = 25;
|
||||
OP_AdventureUpdate = 26;
|
||||
OP_AggroMeterLockTarget = 27;
|
||||
OP_AggroMeterTargetInfo = 28;
|
||||
OP_AggroMeterUpdate = 29;
|
||||
OP_AltCurrency = 30;
|
||||
OP_AltCurrencyMerchantReply = 31;
|
||||
OP_AltCurrencyMerchantRequest = 32;
|
||||
OP_AltCurrencyPurchase = 33;
|
||||
OP_AltCurrencyReclaim = 34;
|
||||
OP_AltCurrencySell = 35;
|
||||
OP_AltCurrencySellSelection = 36;
|
||||
OP_Animation = 37; //supported
|
||||
OP_AnnoyingZoneUnknown = 38;
|
||||
OP_ApplyPoison = 39;
|
||||
OP_ApproveName = 40;
|
||||
OP_ApproveWorld = 41;
|
||||
OP_ApproveZone = 42;
|
||||
OP_Assist = 43; //supported
|
||||
OP_AssistGroup = 44;
|
||||
OP_AugmentInfo = 45;
|
||||
OP_AugmentItem = 46;
|
||||
OP_AutoAttack = 47;
|
||||
OP_AutoAttack2 = 48;
|
||||
OP_AutoFire = 49;
|
||||
OP_Bandolier = 50;
|
||||
OP_BankerChange = 51;
|
||||
OP_Barter = 52;
|
||||
OP_Bazaar = 53;
|
||||
OP_BazaarInspect = 54;
|
||||
OP_BazaarSearch = 55;
|
||||
OP_BecomeCorpse = 56;
|
||||
OP_BecomeTrader = 57;
|
||||
OP_Begging = 58;
|
||||
OP_BeginCast = 59;
|
||||
OP_Bind_Wound = 60;
|
||||
OP_BlockedBuffs = 61;
|
||||
OP_BoardBoat = 62;
|
||||
OP_Buff = 63;
|
||||
OP_BuffCreate = 64;
|
||||
OP_BuffRemoveRequest = 65;
|
||||
OP_Bug = 66;
|
||||
OP_CameraEffect = 67;
|
||||
OP_Camp = 68; //supported
|
||||
OP_CancelSneakHide = 69;
|
||||
OP_CancelTask = 70;
|
||||
OP_CancelTrade = 71;
|
||||
OP_CastSpell = 72;
|
||||
OP_ChangeSize = 73;
|
||||
OP_ChannelMessage = 74;
|
||||
OP_CharacterCreate = 75;
|
||||
OP_CharacterCreateRequest = 76;
|
||||
OP_CharInventory = 77;
|
||||
OP_Charm = 78;
|
||||
OP_ChatMessage = 79; //used by lua
|
||||
OP_ClearAA = 80;
|
||||
OP_ClearBlockedBuffs = 81;
|
||||
OP_ClearLeadershipAbilities = 82;
|
||||
OP_ClearNPCMarks = 83;
|
||||
OP_ClearObject = 84;
|
||||
OP_ClearSurname = 85;
|
||||
OP_ClickDoor = 86;
|
||||
OP_ClickObject = 87;
|
||||
OP_ClickObjectAction = 88;
|
||||
OP_ClientError = 89;
|
||||
OP_ClientReady = 90;
|
||||
OP_ClientTimeStamp = 91;
|
||||
OP_ClientUpdate = 92; //supported
|
||||
OP_CloseContainer = 93;
|
||||
OP_CloseTributeMaster = 94;
|
||||
OP_ColoredText = 95;
|
||||
OP_CombatAbility = 96;
|
||||
OP_Command = 97;
|
||||
OP_CompletedTasks = 98;
|
||||
OP_ConfirmDelete = 99;
|
||||
OP_Consent = 100;
|
||||
OP_ConsentDeny = 101;
|
||||
OP_ConsentResponse = 102;
|
||||
OP_Consider = 103;
|
||||
OP_ConsiderCorpse = 104;
|
||||
OP_Consume = 105;
|
||||
OP_ControlBoat = 106;
|
||||
OP_CorpseDrag = 107;
|
||||
OP_CorpseDrop = 108;
|
||||
OP_CrashDump = 109;
|
||||
OP_CrystalCountUpdate = 110;
|
||||
OP_CrystalCreate = 111;
|
||||
OP_CrystalReclaim = 112;
|
||||
OP_CustomTitles = 113;
|
||||
OP_Damage = 114;
|
||||
OP_Death = 115;
|
||||
OP_DelegateAbility = 116;
|
||||
OP_DeleteCharacter = 117;
|
||||
OP_DeleteCharge = 118;
|
||||
OP_DeleteItem = 119;
|
||||
OP_DeletePetition = 120;
|
||||
OP_DeleteSpawn = 121; //supported
|
||||
OP_DeleteSpell = 122;
|
||||
OP_DenyResponse = 123;
|
||||
OP_Disarm = 124;
|
||||
OP_DisarmTraps = 125;
|
||||
OP_DisciplineTimer = 126;
|
||||
OP_DisciplineUpdate = 127;
|
||||
OP_DiscordMerchantInventory = 128;
|
||||
OP_DoGroupLeadershipAbility = 129;
|
||||
OP_DuelResponse = 130;
|
||||
OP_DuelResponse2 = 131;
|
||||
OP_DumpName = 132;
|
||||
OP_Dye = 133;
|
||||
OP_DynamicWall = 134;
|
||||
OP_DzAddPlayer = 135;
|
||||
OP_DzChooseZone = 136;
|
||||
OP_DzCompass = 137;
|
||||
OP_DzExpeditionEndsWarning = 138;
|
||||
OP_DzExpeditionInfo = 139;
|
||||
OP_DzExpeditionList = 140;
|
||||
OP_DzJoinExpeditionConfirm = 141;
|
||||
OP_DzJoinExpeditionReply = 142;
|
||||
OP_DzLeaderStatus = 143;
|
||||
OP_DzListTimers = 144;
|
||||
OP_DzMakeLeader = 145;
|
||||
OP_DzMemberList = 146;
|
||||
OP_DzMemberStatus = 147;
|
||||
OP_DzPlayerList = 148;
|
||||
OP_DzQuit = 149;
|
||||
OP_DzRemovePlayer = 150;
|
||||
OP_DzSwapPlayer = 151;
|
||||
OP_Emote = 152;
|
||||
OP_EndLootRequest = 153;
|
||||
OP_EnduranceUpdate = 154;
|
||||
OP_EnterChat = 155;
|
||||
OP_EnterWorld = 156;
|
||||
OP_EnvDamage = 157;
|
||||
OP_ExpansionInfo = 158;
|
||||
OP_ExpUpdate = 159;
|
||||
OP_FaceChange = 160;
|
||||
OP_Feedback = 161;
|
||||
OP_FeignDeath = 162;
|
||||
OP_FellowshipUpdate = 163;
|
||||
OP_FindPersonReply = 164;
|
||||
OP_FindPersonRequest = 165;
|
||||
OP_FinishTrade = 166;
|
||||
OP_FinishWindow = 167;
|
||||
OP_FinishWindow2 = 168;
|
||||
OP_Fishing = 169;
|
||||
OP_Fling = 170;
|
||||
OP_FloatListThing = 171;
|
||||
OP_Forage = 172;
|
||||
OP_ForceFindPerson = 173;
|
||||
OP_FormattedMessage = 174;
|
||||
OP_FriendsWho = 175;
|
||||
OP_GetGuildMOTD = 176;
|
||||
OP_GetGuildMOTDReply = 177;
|
||||
OP_GetGuildsList = 178;
|
||||
OP_GiveMoney = 179;
|
||||
OP_GMApproval = 180;
|
||||
OP_GMBecomeNPC = 181;
|
||||
OP_GMDelCorpse = 182;
|
||||
OP_GMEmoteZone = 183;
|
||||
OP_GMEndTraining = 184;
|
||||
OP_GMEndTrainingResponse = 185;
|
||||
OP_GMFind = 186;
|
||||
OP_GMGoto = 187;
|
||||
OP_GMHideMe = 188;
|
||||
OP_GMKick = 189;
|
||||
OP_GMKill = 190;
|
||||
OP_GMLastName = 191;
|
||||
OP_GMNameChange = 192;
|
||||
OP_GMSearchCorpse = 193;
|
||||
OP_GMServers = 194;
|
||||
OP_GMSummon = 195;
|
||||
OP_GMToggle = 196;
|
||||
OP_GMTraining = 197;
|
||||
OP_GMTrainSkill = 198;
|
||||
OP_GMTrainSkillConfirm = 199;
|
||||
OP_GMZoneRequest = 200;
|
||||
OP_GMZoneRequest2 = 201;
|
||||
OP_GroundSpawn = 202;
|
||||
OP_GroupAcknowledge = 203;
|
||||
OP_GroupCancelInvite = 204;
|
||||
OP_GroupDelete = 205;
|
||||
OP_GroupDisband = 206;
|
||||
OP_GroupDisbandOther = 207;
|
||||
OP_GroupDisbandYou = 208;
|
||||
OP_GroupFollow = 209;
|
||||
OP_GroupFollow2 = 210;
|
||||
OP_GroupInvite = 211;
|
||||
OP_GroupInvite2 = 212;
|
||||
OP_GroupLeaderChange = 213;
|
||||
OP_GroupLeadershipAAUpdate = 214;
|
||||
OP_GroupMakeLeader = 215;
|
||||
OP_GroupMentor = 216;
|
||||
OP_GroupRoles = 217;
|
||||
OP_GroupUpdate = 218;
|
||||
OP_GroupUpdateB = 219;
|
||||
OP_GroupUpdateLeaderAA = 220;
|
||||
OP_GuildBank = 221;
|
||||
OP_GuildBankItemList = 222;
|
||||
OP_GuildCreate = 223;
|
||||
OP_GuildDelete = 224;
|
||||
OP_GuildDemote = 225;
|
||||
OP_GuildInvite = 226;
|
||||
OP_GuildInviteAccept = 227;
|
||||
OP_GuildLeader = 228;
|
||||
OP_GuildManageAdd = 229;
|
||||
OP_GuildManageBanker = 230;
|
||||
OP_GuildManageRemove = 231;
|
||||
OP_GuildManageStatus = 232;
|
||||
OP_GuildMemberLevelUpdate = 233;
|
||||
OP_GuildMemberList = 234;
|
||||
OP_GuildMemberUpdate = 235;
|
||||
OP_GuildMOTD = 236;
|
||||
OP_GuildPeace = 237;
|
||||
OP_GuildPromote = 238;
|
||||
OP_GuildPublicNote = 239;
|
||||
OP_GuildRemove = 240;
|
||||
OP_GuildsList = 241;
|
||||
OP_GuildStatus = 242;
|
||||
OP_GuildTributeInfo = 243;
|
||||
OP_GuildUpdateURLAndChannel = 244;
|
||||
OP_GuildWar = 245;
|
||||
OP_Heartbeat = 246;
|
||||
OP_Hide = 247;
|
||||
OP_HideCorpse = 248;
|
||||
OP_HPUpdate = 249; //supported
|
||||
OP_Illusion = 250;
|
||||
OP_IncreaseStats = 251;
|
||||
OP_InitialHPUpdate = 252;
|
||||
OP_InitialMobHealth = 253;
|
||||
OP_InspectAnswer = 254;
|
||||
OP_InspectBuffs = 255;
|
||||
OP_InspectMessageUpdate = 256;
|
||||
OP_InspectRequest = 257;
|
||||
OP_InstillDoubt = 258;
|
||||
OP_InterruptCast = 259;
|
||||
OP_ItemLinkClick = 260;
|
||||
OP_ItemLinkResponse = 261;
|
||||
OP_ItemLinkText = 262;
|
||||
OP_ItemName = 263;
|
||||
OP_ItemPacket = 264;
|
||||
OP_ItemPreview = 265;
|
||||
OP_ItemRecastDelay = 266;
|
||||
OP_ItemVerifyReply = 267;
|
||||
OP_ItemVerifyRequest = 268;
|
||||
OP_ItemViewUnknown = 269;
|
||||
OP_Jump = 270;
|
||||
OP_KeyRing = 271;
|
||||
OP_KnowledgeBase = 272;
|
||||
OP_LDoNButton = 273;
|
||||
OP_LDoNDisarmTraps = 274;
|
||||
OP_LDoNInspect = 275;
|
||||
OP_LDoNOpen = 276;
|
||||
OP_LDoNPickLock = 277;
|
||||
OP_LDoNSenseTraps = 278;
|
||||
OP_LeadershipExpToggle = 279;
|
||||
OP_LeadershipExpUpdate = 280;
|
||||
OP_LeaveAdventure = 281;
|
||||
OP_LeaveBoat = 282;
|
||||
OP_LevelAppearance = 283;
|
||||
OP_LevelUpdate = 284;
|
||||
OP_LFGAppearance = 285;
|
||||
OP_LFGCommand = 286;
|
||||
OP_LFGGetMatchesRequest = 287;
|
||||
OP_LFGGetMatchesResponse = 288;
|
||||
OP_LFGResponse = 289;
|
||||
OP_LFGuild = 290;
|
||||
OP_LFPCommand = 291;
|
||||
OP_LFPGetMatchesRequest = 292;
|
||||
OP_LFPGetMatchesResponse = 293;
|
||||
OP_LinkedReuse = 294;
|
||||
OP_LoadSpellSet = 295;
|
||||
OP_LocInfo = 296;
|
||||
OP_LockoutTimerInfo = 297;
|
||||
OP_Login = 298;
|
||||
OP_LoginAccepted = 299;
|
||||
OP_LoginComplete = 300;
|
||||
OP_LoginUnknown1 = 301;
|
||||
OP_LoginUnknown2 = 302;
|
||||
OP_Logout = 303;
|
||||
OP_LogoutReply = 304;
|
||||
OP_LogServer = 305;
|
||||
OP_LootComplete = 306;
|
||||
OP_LootItem = 307;
|
||||
OP_LootRequest = 308;
|
||||
OP_ManaChange = 309;
|
||||
OP_ManaUpdate = 310;
|
||||
OP_MarkNPC = 311;
|
||||
OP_Marquee = 312;
|
||||
OP_MemorizeSpell = 313;
|
||||
OP_Mend = 314;
|
||||
OP_MendHPUpdate = 315;
|
||||
OP_MercenaryAssign = 316;
|
||||
OP_MercenaryCommand = 317;
|
||||
OP_MercenaryDataRequest = 318;
|
||||
OP_MercenaryDataResponse = 319;
|
||||
OP_MercenaryDataUpdate = 320;
|
||||
OP_MercenaryDataUpdateRequest = 321;
|
||||
OP_MercenaryDismiss = 322;
|
||||
OP_MercenaryHire = 323;
|
||||
OP_MercenarySuspendRequest = 324;
|
||||
OP_MercenarySuspendResponse = 325;
|
||||
OP_MercenaryTimer = 326;
|
||||
OP_MercenaryTimerRequest = 327;
|
||||
OP_MercenaryUnknown1 = 328;
|
||||
OP_MercenaryUnsuspendResponse = 329;
|
||||
OP_MobEnduranceUpdate = 330;
|
||||
OP_MobHealth = 331; //supported
|
||||
OP_MobManaUpdate = 332;
|
||||
OP_MobRename = 333;
|
||||
OP_MobUpdate = 334; // not used anymore, here for lecacy reasons eqextractor
|
||||
OP_MoneyOnCorpse = 335;
|
||||
OP_MoneyUpdate = 336;
|
||||
OP_MOTD = 337;
|
||||
OP_MoveCoin = 338;
|
||||
OP_MoveDoor = 339;
|
||||
OP_MoveItem = 340;
|
||||
OP_MoveLogDisregard = 341;
|
||||
OP_MoveLogRequest = 342;
|
||||
OP_MultiLineMsg = 343;
|
||||
OP_NewSpawn = 344; //supported
|
||||
OP_NewTitlesAvailable = 345;
|
||||
OP_NewZone = 346;
|
||||
OP_OnLevelMessage = 347;
|
||||
OP_OpenContainer = 348;
|
||||
OP_OpenDiscordMerchant = 349;
|
||||
OP_OpenGuildTributeMaster = 350;
|
||||
OP_OpenInventory = 351;
|
||||
OP_OpenNewTasksWindow = 352;
|
||||
OP_OpenTributeMaster = 353;
|
||||
OP_PDeletePetition = 354;
|
||||
OP_PetBuffWindow = 355;
|
||||
OP_PetCommands = 356;
|
||||
OP_PetCommandState = 357;
|
||||
OP_PetHoTT = 358;
|
||||
OP_Petition = 359;
|
||||
OP_PetitionBug = 360;
|
||||
OP_PetitionCheckIn = 361;
|
||||
OP_PetitionCheckout = 362;
|
||||
OP_PetitionCheckout2 = 363;
|
||||
OP_PetitionDelete = 364;
|
||||
OP_PetitionQue = 365;
|
||||
OP_PetitionRefresh = 366;
|
||||
OP_PetitionResolve = 367;
|
||||
OP_PetitionSearch = 368;
|
||||
OP_PetitionSearchResults = 369;
|
||||
OP_PetitionSearchText = 370;
|
||||
OP_PetitionUnCheckout = 371;
|
||||
OP_PetitionUpdate = 372;
|
||||
OP_PickPocket = 373;
|
||||
OP_PlayerProfile = 374;
|
||||
OP_PlayerStateAdd = 375;
|
||||
OP_PlayerStateRemove = 376;
|
||||
OP_PlayEverquestRequest = 377;
|
||||
OP_PlayEverquestResponse = 378;
|
||||
OP_PlayMP3 = 379;
|
||||
OP_Poll = 380;
|
||||
OP_PollResponse = 381;
|
||||
OP_PopupResponse = 382;
|
||||
OP_PostEnterWorld = 383; //this is really OP_WorldAccessGrant
|
||||
OP_PotionBelt = 384;
|
||||
OP_PreLogoutReply = 385;
|
||||
OP_PurchaseLeadershipAA = 386;
|
||||
OP_PVPLeaderBoardDetailsReply = 387;
|
||||
OP_PVPLeaderBoardDetailsRequest = 388;
|
||||
OP_PVPLeaderBoardReply = 389;
|
||||
OP_PVPLeaderBoardRequest = 390;
|
||||
OP_PVPStats = 391;
|
||||
OP_QueryResponseThing = 392;
|
||||
OP_RaidInvite = 393;
|
||||
OP_RaidJoin = 394;
|
||||
OP_RaidUpdate = 395;
|
||||
OP_RandomNameGenerator = 396;
|
||||
OP_RandomReply = 397;
|
||||
OP_RandomReq = 398;
|
||||
OP_ReadBook = 399;
|
||||
OP_RecipeAutoCombine = 400;
|
||||
OP_RecipeDetails = 401;
|
||||
OP_RecipeReply = 402;
|
||||
OP_RecipesFavorite = 403;
|
||||
OP_RecipesSearch = 404;
|
||||
OP_ReclaimCrystals = 405;
|
||||
OP_ReloadUI = 406;
|
||||
OP_RemoveAllDoors = 407;
|
||||
OP_RemoveBlockedBuffs = 408;
|
||||
OP_RemoveNimbusEffect = 409;
|
||||
OP_RemoveTrap = 410;
|
||||
OP_Report = 411;
|
||||
OP_ReqClientSpawn = 412;
|
||||
OP_ReqNewZone = 413;
|
||||
OP_RequestClientZoneChange = 414;
|
||||
OP_RequestDuel = 415;
|
||||
OP_RequestKnowledgeBase = 416;
|
||||
OP_RequestTitles = 417;
|
||||
OP_RespawnWindow = 418;
|
||||
OP_RespondAA = 419;
|
||||
OP_RestState = 420;
|
||||
OP_Rewind = 421;
|
||||
OP_RezzAnswer = 422;
|
||||
OP_RezzComplete = 423;
|
||||
OP_RezzRequest = 424;
|
||||
OP_Sacrifice = 425;
|
||||
OP_SafeFallSuccess = 426;
|
||||
OP_SafePoint = 427;
|
||||
OP_Save = 428;
|
||||
OP_SaveOnZoneReq = 429;
|
||||
OP_SelectTribute = 430;
|
||||
OP_SendAAStats = 431;
|
||||
OP_SendAATable = 432;
|
||||
OP_SendCharInfo = 433;
|
||||
OP_SendExpZonein = 434;
|
||||
OP_SendFindableNPCs = 435;
|
||||
OP_SendGuildTributes = 436;
|
||||
OP_SendLoginInfo = 437;
|
||||
OP_SendMaxCharacters = 438;
|
||||
OP_SendMembership = 439;
|
||||
OP_SendMembershipDetails = 440;
|
||||
OP_SendSystemStats = 441;
|
||||
OP_SendTitleList = 442;
|
||||
OP_SendTributes = 443;
|
||||
OP_SendZonepoints = 444;
|
||||
OP_SenseHeading = 445;
|
||||
OP_SenseTraps = 446;
|
||||
OP_ServerListRequest = 447;
|
||||
OP_ServerListResponse = 448;
|
||||
OP_SessionReady = 449;
|
||||
OP_SetChatServer = 450;
|
||||
OP_SetChatServer2 = 451;
|
||||
OP_SetGroupTarget = 452;
|
||||
OP_SetGuildMOTD = 453;
|
||||
OP_SetGuildRank = 454;
|
||||
OP_SetRunMode = 455;
|
||||
OP_SetServerFilter = 456;
|
||||
OP_SetStartCity = 457;
|
||||
OP_SetTitle = 458;
|
||||
OP_SetTitleReply = 459;
|
||||
OP_Shielding = 460;
|
||||
OP_ShopDelItem = 461;
|
||||
OP_ShopEnd = 462;
|
||||
OP_ShopEndConfirm = 463;
|
||||
OP_ShopItem = 464;
|
||||
OP_ShopPlayerBuy = 465;
|
||||
OP_ShopPlayerSell = 466;
|
||||
OP_ShopRequest = 467;
|
||||
OP_SimpleMessage = 468;
|
||||
OP_SkillUpdate = 469;
|
||||
OP_Sneak = 470;
|
||||
OP_Some3ByteHPUpdate = 471;
|
||||
OP_Some6ByteHPUpdate = 472;
|
||||
OP_SomeItemPacketMaybe = 473;
|
||||
OP_Sound = 474;
|
||||
OP_SpawnAppearance = 475;
|
||||
OP_SpawnDoor = 476;
|
||||
OP_SpawnPositionUpdate = 477;
|
||||
OP_SpecialMesg = 478;
|
||||
OP_SpellEffect = 479;
|
||||
OP_Split = 480;
|
||||
OP_Stamina = 481;
|
||||
OP_Stun = 482;
|
||||
OP_Surname = 483;
|
||||
OP_SwapSpell = 484;
|
||||
OP_TargetBuffs = 485;
|
||||
OP_TargetCommand = 486;
|
||||
OP_TargetHoTT = 487;
|
||||
OP_TargetMouse = 488;
|
||||
OP_TargetReject = 489;
|
||||
OP_TaskActivity = 490;
|
||||
OP_TaskActivityComplete = 491;
|
||||
OP_TaskDescription = 492;
|
||||
OP_TaskHistoryReply = 493;
|
||||
OP_TaskHistoryRequest = 494;
|
||||
OP_TaskMemberList = 495;
|
||||
OP_Taunt = 496;
|
||||
OP_TestBuff = 497;
|
||||
OP_TGB = 498;
|
||||
OP_TimeOfDay = 499;
|
||||
OP_Track = 500;
|
||||
OP_TrackTarget = 501;
|
||||
OP_TrackUnknown = 502;
|
||||
OP_TradeAcceptClick = 503;
|
||||
OP_TradeBusy = 504;
|
||||
OP_TradeCoins = 505;
|
||||
OP_TradeMoneyUpdate = 506;
|
||||
OP_Trader = 507;
|
||||
OP_TraderBuy = 508;
|
||||
OP_TraderDelItem = 509;
|
||||
OP_TradeRequest = 510;
|
||||
OP_TradeRequestAck = 511;
|
||||
OP_TraderItemUpdate = 512;
|
||||
OP_TraderShop = 513;
|
||||
OP_TradeSkillCombine = 514;
|
||||
OP_Translocate = 515;
|
||||
OP_TributeInfo = 516;
|
||||
OP_TributeItem = 517;
|
||||
OP_TributeMoney = 518;
|
||||
OP_TributeNPC = 519;
|
||||
OP_TributePointUpdate = 520;
|
||||
OP_TributeTimer = 521;
|
||||
OP_TributeToggle = 522;
|
||||
OP_TributeUpdate = 523;
|
||||
OP_Untargetable = 524;
|
||||
OP_UpdateAA = 525;
|
||||
OP_UpdateAura = 526;
|
||||
OP_UpdateLeadershipAA = 527;
|
||||
OP_VetClaimReply = 528;
|
||||
OP_VetClaimRequest = 529;
|
||||
OP_VetRewardsAvaliable = 530;
|
||||
OP_VoiceMacroIn = 531;
|
||||
OP_VoiceMacroOut = 532;
|
||||
OP_WeaponEquip1 = 533;
|
||||
OP_WearChange = 534; //supported
|
||||
OP_Weather = 535;
|
||||
OP_Weblink = 536;
|
||||
OP_WhoAllRequest = 537;
|
||||
OP_WhoAllResponse = 538;
|
||||
OP_World_Client_CRC1 = 539;
|
||||
OP_World_Client_CRC2 = 540;
|
||||
OP_WorldClientReady = 541;
|
||||
OP_WorldComplete = 542;
|
||||
OP_WorldLogout = 543;
|
||||
OP_WorldObjectsSent = 544;
|
||||
OP_WorldUnknown001 = 545;
|
||||
OP_XTargetAutoAddHaters = 546;
|
||||
OP_XTargetOpen = 547;
|
||||
OP_XTargetOpenResponse = 548;
|
||||
OP_XTargetRequest = 549;
|
||||
OP_XTargetResponse = 550;
|
||||
OP_YellForHelp = 551;
|
||||
OP_ZoneChange = 552;
|
||||
OP_ZoneComplete = 553;
|
||||
OP_ZoneEntry = 554; //supported
|
||||
OP_ZoneGuildList = 555;
|
||||
OP_ZoneInUnknown = 556;
|
||||
OP_ZonePlayerToBind = 557;
|
||||
OP_ZoneServerInfo = 558;
|
||||
OP_ZoneServerReady = 559;
|
||||
OP_ZoneSpawns = 560;
|
||||
OP_ZoneUnavail = 561;
|
||||
OP_ResetAA = 562;
|
||||
OP_Buddy = 563;
|
||||
OP_ChannelAnnounceJoin = 564;
|
||||
OP_ChannelAnnounceLeave = 565;
|
||||
OP_Ignore = 566;
|
||||
OP_Mail = 567;
|
||||
OP_MailboxChange = 568;
|
||||
OP_MailDeliveryStatus = 569;
|
||||
OP_MailHeader = 570;
|
||||
OP_MailHeaderCount = 571;
|
||||
OP_MailLogin = 572;
|
||||
OP_MailNew = 573;
|
||||
OP_MailSendBody = 574;
|
||||
|
||||
}
|
||||
@ -13,6 +13,7 @@ SET(world_sources
|
||||
lfplist.cpp
|
||||
login_server.cpp
|
||||
login_server_list.cpp
|
||||
nats_manager.cpp
|
||||
net.cpp
|
||||
queryserv.cpp
|
||||
ucs.cpp
|
||||
@ -40,6 +41,7 @@ SET(world_headers
|
||||
lfplist.h
|
||||
login_server.h
|
||||
login_server_list.h
|
||||
nats_manager.h
|
||||
net.h
|
||||
queryserv.h
|
||||
sof_char_create_data.h
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
#include "clientlist.h"
|
||||
#include "wguild_mgr.h"
|
||||
#include "sof_char_create_data.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
@ -84,6 +85,7 @@ extern ClientList client_list;
|
||||
extern EQEmu::Random emu_random;
|
||||
extern uint32 numclients;
|
||||
extern volatile bool RunLoops;
|
||||
extern NatsManager nats;
|
||||
|
||||
Client::Client(EQStreamInterface* ieqs)
|
||||
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
|
||||
@ -799,6 +801,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
else {
|
||||
Log(Logs::Detail, Logs::World_Server, "'%s' is trying to go home before they're able...", char_name);
|
||||
nats.SendAdminMessage(StringFormat("Hacker: %s [%s]: MQGoHome: player tried to go home before they were able.", GetAccountName(), char_name));
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
@ -823,6 +826,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
else {
|
||||
Log(Logs::Detail, Logs::World_Server, "'%s' is trying to go to tutorial but are not allowed...", char_name);
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s [%s]: MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.", GetAccountName(), char_name));
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
|
||||
@ -1467,4 +1467,59 @@ void ClientList::OnTick(EQ::Timer *t)
|
||||
}
|
||||
|
||||
web_interface.SendEvent(out);
|
||||
}
|
||||
|
||||
std::string ClientList::GetWhoAll() {
|
||||
std::string reply = "";
|
||||
|
||||
LinkedListIterator<ClientListEntry*> iterator(clientlist);
|
||||
ClientListEntry* cle = 0;
|
||||
uint32 x = 0;
|
||||
|
||||
char* output = 0;
|
||||
uint32 outsize = 0, outlen = 0;
|
||||
reply.append("Players on server:\n");
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
cle = iterator.GetData();
|
||||
const char* tmpZone = database.GetZoneName(cle->zone());
|
||||
if (cle->Online() < CLE_Status_Zoning ||
|
||||
x > 20) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
if (cle->Admin() >= 250) reply.append("* GM-Impossible * ");
|
||||
else if (cle->Admin() >= 200) reply.append("* GM-Mgmt * ");
|
||||
else if (cle->Admin() >= 180) reply.append("* GM-Coder * ");
|
||||
else if (cle->Admin() >= 170) reply.append("* GM-Areas * ");
|
||||
else if (cle->Admin() >= 160) reply.append("* QuestMaster * ");
|
||||
else if (cle->Admin() >= 150) reply.append("* GM-Lead Admin * ");
|
||||
else if (cle->Admin() >= 100) reply.append("* GM-Admin * ");
|
||||
else if (cle->Admin() >= 95) reply.append("* GM-Staff * ");
|
||||
else if (cle->Admin() >= 90) reply.append("* EQ Support * ");
|
||||
else if (cle->Admin() >= 85) reply.append("* GM-Tester * ");
|
||||
else if (cle->Admin() >= 81) reply.append("* Senior Guide * ");
|
||||
else if (cle->Admin() >= 80) reply.append("* QuestTroupe * ");
|
||||
else if (cle->Admin() >= 50) reply.append("* Guide * ");
|
||||
//else if (cle->Admin() >= 20) reply.append("* Apprentice Guide * ");
|
||||
//else if (cle->Admin() >= 10) reply.append("* Steward * ");
|
||||
|
||||
|
||||
if (cle->Anon() == 2) reply.append("[RolePlay");
|
||||
else if (cle->Anon() == 1) reply.append("[ANON");
|
||||
else reply.append("[");
|
||||
|
||||
reply.append(StringFormat(" %i %s ] %s", cle->level(), GetClassIDName(cle->class_(), cle->level()), cle->name()));
|
||||
reply.append(StringFormat(" %s zone: %s", GetRaceIDName(cle->race()), database.GetZoneName(cle->zone())));
|
||||
|
||||
if (guild_mgr.GuildExists(cle->GuildID())) reply.append(StringFormat(" <%s>", guild_mgr.GetGuildName(cle->GuildID())));
|
||||
if (cle->LFG()) reply.append(" LFG");
|
||||
reply.append("\n");
|
||||
x++;
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if (x >= 20) reply.append("First 20 shown, ");
|
||||
reply.append(StringFormat("%u total players online.", x));
|
||||
return reply;
|
||||
}
|
||||
@ -69,6 +69,7 @@ public:
|
||||
int GetClientCount();
|
||||
void GetClients(const char *zone_name, std::vector<ClientListEntry *> &into);
|
||||
|
||||
std::string GetWhoAll();
|
||||
private:
|
||||
void OnTick(EQ::Timer *t);
|
||||
inline uint32 GetNextCLEID() { return NextCLEID++; }
|
||||
|
||||
268
world/nats_manager.cpp
Normal file
268
world/nats_manager.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
#include "nats_manager.h"
|
||||
#include "nats.h"
|
||||
#include "zonelist.h"
|
||||
#include "login_server_list.h"
|
||||
#include "clientlist.h"
|
||||
#include "worlddb.h"
|
||||
|
||||
#include "../common/seperator.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#ifndef PROTO_H
|
||||
#define PROTO_H
|
||||
#include "../common/proto/message.pb.h"
|
||||
#endif
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/string_util.h"
|
||||
|
||||
extern ZSList zoneserver_list;
|
||||
extern LoginServerList loginserverlist;
|
||||
extern ClientList client_list;
|
||||
const WorldConfig *worldConfig;
|
||||
|
||||
NatsManager::NatsManager()
|
||||
{
|
||||
//new timers, object initialization
|
||||
worldConfig = WorldConfig::get();
|
||||
}
|
||||
|
||||
NatsManager::~NatsManager()
|
||||
{
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsStatistics_Destroy(stats);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
}
|
||||
|
||||
bool NatsManager::connect() {
|
||||
auto ncs = natsConnection_Status(conn);
|
||||
if (ncs == CONNECTED) return true;
|
||||
if (nats_timer.Enabled() && !nats_timer.Check()) return false;
|
||||
natsOptions *opts = NULL;
|
||||
natsOptions_Create(&opts);
|
||||
natsOptions_SetMaxReconnect(opts, 0);
|
||||
natsOptions_SetReconnectWait(opts, 0);
|
||||
natsOptions_SetAllowReconnect(opts, false);
|
||||
//The timeout is going to cause a 100ms delay on all connected clients every X seconds (20s)
|
||||
//since this blocks the connection. It can be set lower or higher delay,
|
||||
//but since NATS is a second priority I wanted server impact minimum.
|
||||
natsOptions_SetTimeout(opts, 100);
|
||||
std::string connection = StringFormat("nats://%s:%d", worldConfig->NATSHost.c_str(), worldConfig->NATSPort);
|
||||
if (worldConfig->NATSHost.length() == 0) connection = "nats://localhost:4222";
|
||||
natsOptions_SetURL(opts, connection.c_str());
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
natsOptions_Destroy(opts);
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to connect to %s: %s, retrying in 20s", connection.c_str(), nats_GetLastError(&s));
|
||||
conn = NULL;
|
||||
nats_timer.Enable();
|
||||
nats_timer.SetTimer(20000);
|
||||
return false;
|
||||
}
|
||||
Log(Logs::General, Logs::NATS, "connected to %s", connection.c_str());
|
||||
nats_timer.Disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void NatsManager::Process()
|
||||
{
|
||||
natsMsg *msg = NULL;
|
||||
if (!connect()) return;
|
||||
s = NATS_OK;
|
||||
for (int count = 0; (s == NATS_OK) && count < 5; count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, channelMessageSub, 1);
|
||||
if (s != NATS_OK) break;
|
||||
Log(Logs::General, Logs::NATS, "Got Broadcast Message '%s'", natsMsg_GetData(msg));
|
||||
eqproto::ChannelMessage message;
|
||||
if (!message.ParseFromString(natsMsg_GetData(msg))) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to marshal");
|
||||
natsMsg_Destroy(msg);
|
||||
continue;
|
||||
}
|
||||
ChannelMessageEvent(&message);
|
||||
}
|
||||
|
||||
s = NATS_OK;
|
||||
for (int count = 0; (s == NATS_OK) && count < 5; count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, commandMessageSub, 1);
|
||||
if (s != NATS_OK) break;
|
||||
Log(Logs::General, Logs::NATS, "Got Command Message '%s'", natsMsg_GetData(msg));
|
||||
eqproto::CommandMessage message;
|
||||
|
||||
|
||||
if (!message.ParseFromString(natsMsg_GetData(msg))) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to marshal");
|
||||
natsMsg_Destroy(msg);
|
||||
continue;
|
||||
}
|
||||
CommandMessageEvent(&message, natsMsg_GetReply(msg));
|
||||
}
|
||||
}
|
||||
|
||||
void NatsManager::OnChannelMessage(ServerChannelMessage_Struct* msg) {
|
||||
if (!connect()) return;
|
||||
|
||||
eqproto::ChannelMessage message;
|
||||
|
||||
message.set_fromadmin(msg->fromadmin);
|
||||
message.set_deliverto(msg->deliverto);
|
||||
message.set_guilddbid(msg->guilddbid);
|
||||
message.set_noreply(msg->noreply);
|
||||
message.set_queued(msg->queued);
|
||||
message.set_chan_num(msg->chan_num);
|
||||
message.set_message(msg->message);
|
||||
message.set_to(msg->to);
|
||||
message.set_language(msg->language);
|
||||
message.set_from(msg->from);
|
||||
SendChannelMessage(&message);
|
||||
return;
|
||||
}
|
||||
|
||||
void NatsManager::OnEmoteMessage(ServerEmoteMessage_Struct* msg) {
|
||||
if (!connect()) return;
|
||||
|
||||
eqproto::ChannelMessage message;
|
||||
message.set_guilddbid(msg->guilddbid);
|
||||
message.set_minstatus(msg->minstatus);
|
||||
message.set_type(msg->type);
|
||||
message.set_message(msg->message);
|
||||
message.set_to(msg->to);
|
||||
message.set_is_emote(true);
|
||||
SendChannelMessage(&message);
|
||||
return;
|
||||
}
|
||||
|
||||
void NatsManager::SendAdminMessage(std::string adminMessage) {
|
||||
if (!connect()) return;
|
||||
|
||||
eqproto::ChannelMessage message;
|
||||
message.set_message(adminMessage.c_str());
|
||||
std::string pubMessage;
|
||||
if (!message.SerializeToString(&pubMessage)) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to serialize message to string");
|
||||
return;
|
||||
}
|
||||
s = natsConnection_PublishString(conn, "AdminMessage", pubMessage.c_str());
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to SendAdminMessage");
|
||||
}
|
||||
Log(Logs::General, Logs::NATS, "AdminMessage: %s", adminMessage.c_str());
|
||||
}
|
||||
|
||||
//Send (publish) message to NATS
|
||||
void NatsManager::SendChannelMessage(eqproto::ChannelMessage* message) {
|
||||
if (!connect()) return;
|
||||
|
||||
std::string pubMessage;
|
||||
if (!message->SerializeToString(&pubMessage)) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to serialize message to string");
|
||||
return;
|
||||
}
|
||||
s = natsConnection_PublishString(conn, "ChannelMessage", pubMessage.c_str());
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to send ChannelMessageEvent");
|
||||
}
|
||||
}
|
||||
|
||||
void NatsManager::CommandMessageEvent(eqproto::CommandMessage* message, const char* reply) {
|
||||
if (!connect()) return;
|
||||
std::string pubMessage;
|
||||
//Log(Logs::General, Logs::NATS, "Command: %s", message->command().c_str());
|
||||
// message->params()
|
||||
|
||||
|
||||
if (message->command().compare("who") == 0) {
|
||||
message->set_result(client_list.GetWhoAll());
|
||||
}
|
||||
|
||||
if (message->command().compare("unlock") == 0) {
|
||||
WorldConfig::UnlockWorld();
|
||||
if (loginserverlist.Connected()) loginserverlist.SendStatus();
|
||||
message->set_result("Server is now unlocked.");
|
||||
}
|
||||
|
||||
if (message->command().compare("lock") == 0) {
|
||||
WorldConfig::LockWorld();
|
||||
if (loginserverlist.Connected()) loginserverlist.SendStatus();
|
||||
message->set_result("Server is now locked.");
|
||||
}
|
||||
|
||||
if(message->command().compare("worldshutdown") == 0) {
|
||||
uint32 time=0;
|
||||
uint32 interval=0;
|
||||
|
||||
if(message->params_size() < 1) {
|
||||
message->set_result("worldshutdown - Shuts down the server and all zones.\n \
|
||||
Usage: worldshutdown now - Shuts down the server and all zones immediately.\n \
|
||||
Usage: worldshutdown disable - Stops the server from a previously scheduled shut down.\n \
|
||||
Usage: worldshutdown [timer] [interval] - Shuts down the server and all zones after [timer] seconds and sends warning every [interval] seconds\n");
|
||||
} else if(message->params_size() == 2 && ((time=atoi(message->params(0).c_str()))>0) && ((interval=atoi(message->params(1).c_str()))>0)) {
|
||||
message->set_result(StringFormat("Sending shutdown packet now, World will shutdown in: %i minutes with an interval of: %i seconds", (time / 60), interval));
|
||||
zoneserver_list.WorldShutDown(time, interval);
|
||||
}
|
||||
else if(strcasecmp(message->params(0).c_str(), "now") == 0){
|
||||
message->set_result("Sending shutdown packet now");
|
||||
zoneserver_list.WorldShutDown(0, 0);
|
||||
}
|
||||
else if(strcasecmp(message->params(0).c_str(), "disable") == 0){
|
||||
message->set_result("Shutdown prevented, next time I may not be so forgiving...");
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 0, 15, "<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World shutdown aborted.");
|
||||
zoneserver_list.shutdowntimer->Disable();
|
||||
zoneserver_list.reminder->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
if (message->result().length() <= 1) {
|
||||
message->set_result("Failed to parse command.");
|
||||
}
|
||||
|
||||
if (!message->SerializeToString(&pubMessage)) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to serialize command message to string");
|
||||
return;
|
||||
}
|
||||
|
||||
s = natsConnection_PublishString(conn, reply, pubMessage.c_str());
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to send CommandMessageEvent");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Send a message to all zone servers.
|
||||
void NatsManager::ChannelMessageEvent(eqproto::ChannelMessage* message) {
|
||||
if (!connect()) return;
|
||||
if (message->zone_id() > 0) return; //do'nt process non-zero messages
|
||||
Log(Logs::General, Logs::NATS, "Broadcasting Message");
|
||||
if (message->is_emote()) { //emote message
|
||||
zoneserver_list.SendEmoteMessage(message->to().c_str(), message->guilddbid(), message->minstatus(), message->type(), message->message().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
//normal broadcast
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], message->from().c_str());
|
||||
//TODO: add To support on tells
|
||||
int channel = message->chan_num();
|
||||
if (channel < 1) channel = 5; //default to ooc
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, channel, message->language(), message->message().c_str());
|
||||
}
|
||||
|
||||
void NatsManager::Save()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void NatsManager::Load()
|
||||
{
|
||||
if (!connect()) return;
|
||||
|
||||
s = natsConnection_SubscribeSync(&channelMessageSub, conn, "ChannelMessageWorld");
|
||||
s = natsConnection_SubscribeSync(&commandMessageSub, conn, "CommandMessageWorld");
|
||||
return;
|
||||
}
|
||||
43
world/nats_manager.h
Normal file
43
world/nats_manager.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef NATS_H
|
||||
#define NATS_H
|
||||
|
||||
#include "nats.h"
|
||||
|
||||
#include "world_config.h"
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/types.h"
|
||||
#include "../common/timer.h"
|
||||
#ifndef PROTO_H
|
||||
#define PROTO_H
|
||||
#include "../common/proto/message.pb.h"
|
||||
#endif
|
||||
#include "../common/servertalk.h"
|
||||
|
||||
class NatsManager
|
||||
{
|
||||
public:
|
||||
NatsManager();
|
||||
~NatsManager();
|
||||
|
||||
void Process();
|
||||
void OnChannelMessage(ServerChannelMessage_Struct * msg);
|
||||
void OnEmoteMessage(ServerEmoteMessage_Struct * msg);
|
||||
void SendAdminMessage(std::string adminMessage);
|
||||
void ChannelMessageEvent(eqproto::ChannelMessage* message);
|
||||
void CommandMessageEvent(eqproto::CommandMessage* message, const char* reply);
|
||||
void SendChannelMessage(eqproto::ChannelMessage* message);
|
||||
void Save();
|
||||
void Load();
|
||||
protected:
|
||||
bool connect();
|
||||
Timer nats_timer;
|
||||
natsConnection *conn = NULL;
|
||||
natsStatus s;
|
||||
natsStatistics *stats = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *channelMessageSub = NULL;
|
||||
natsSubscription *commandMessageSub = NULL;
|
||||
natsSubscription *adminMessageSub = NULL;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -83,6 +83,7 @@ union semun {
|
||||
#include "queryserv.h"
|
||||
#include "web_interface.h"
|
||||
#include "console.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include "../common/net/servertalk_server.h"
|
||||
|
||||
@ -102,6 +103,7 @@ bool holdzones = false;
|
||||
const WorldConfig *Config;
|
||||
EQEmuLogSys LogSys;
|
||||
WebInterfaceList web_interface;
|
||||
NatsManager nats;
|
||||
|
||||
void CatchSignal(int sig_num);
|
||||
void CheckForServerScript(bool force_download = false);
|
||||
@ -386,6 +388,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
adventure_manager.Load();
|
||||
adventure_manager.LoadLeaderboardInfo();
|
||||
nats.Load();
|
||||
|
||||
Log(Logs::General, Logs::World_Server, "Purging expired instances");
|
||||
database.PurgeExpiredInstances();
|
||||
@ -412,7 +415,7 @@ int main(int argc, char** argv) {
|
||||
server_opts.credentials = Config->SharedKey;
|
||||
server_connection->Listen(server_opts);
|
||||
Log(Logs::General, Logs::World_Server, "Server (TCP) listener started.");
|
||||
|
||||
nats.SendAdminMessage("World server booted up.");
|
||||
server_connection->OnConnectionIdentified("Zone", [&console](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||
LogF(Logs::General, Logs::World_Server, "New Zone Server connection from {2} at {0}:{1}",
|
||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
||||
@ -559,6 +562,7 @@ int main(int argc, char** argv) {
|
||||
launcher_list.Process();
|
||||
LFPGroupList.Process();
|
||||
adventure_manager.Process();
|
||||
nats.Process();
|
||||
|
||||
if (InterserverTimer.Check()) {
|
||||
InterserverTimer.Start();
|
||||
|
||||
@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "adventure_manager.h"
|
||||
#include "ucs.h"
|
||||
#include "queryserv.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern GroupLFPList LFPGroupList;
|
||||
@ -44,6 +45,7 @@ extern volatile bool RunLoops;
|
||||
extern AdventureManager adventure_manager;
|
||||
extern UCSConnection UCSLink;
|
||||
extern QueryServConnection QSLink;
|
||||
extern NatsManager nats;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
ZoneServer::ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection, EQ::Net::ConsoleServer *console)
|
||||
@ -413,6 +415,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
UCSLink.SendMessage(scm->from, scm->message);
|
||||
break;
|
||||
}
|
||||
nats.OnChannelMessage(scm);
|
||||
if (scm->chan_num == 7 || scm->chan_num == 14) {
|
||||
if (scm->deliverto[0] == '*') {
|
||||
|
||||
@ -505,6 +508,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
case ServerOP_EmoteMessage: {
|
||||
ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*)pack->pBuffer;
|
||||
nats.OnEmoteMessage(sem);
|
||||
zoneserver_list.SendEmoteMessageRaw(sem->to, sem->guilddbid, sem->minstatus, sem->type, sem->message);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ SET(zone_sources
|
||||
lua_raid.cpp
|
||||
lua_spawn.cpp
|
||||
lua_spell.cpp
|
||||
lua_stat_bonuses.cpp
|
||||
lua_stat_bonuses.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
entity.cpp
|
||||
@ -80,6 +80,7 @@ SET(zone_sources
|
||||
mob.cpp
|
||||
mob_ai.cpp
|
||||
mod_functions.cpp
|
||||
nats_manager.cpp
|
||||
net.cpp
|
||||
npc.cpp
|
||||
npc_ai.cpp
|
||||
@ -187,13 +188,14 @@ SET(zone_headers
|
||||
lua_raid.h
|
||||
lua_spawn.h
|
||||
lua_spell.h
|
||||
lua_stat_bonuses.h
|
||||
lua_stat_bonuses.h
|
||||
map.h
|
||||
masterentity.h
|
||||
maxskill.h
|
||||
message.h
|
||||
merc.h
|
||||
mob.h
|
||||
nats_manager.h
|
||||
net.h
|
||||
npc.h
|
||||
npc_ai.h
|
||||
|
||||
@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "worldserver.h"
|
||||
#include "zone.h"
|
||||
#include "lua_parser.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -52,6 +53,7 @@ extern WorldServer worldserver;
|
||||
|
||||
extern EntityList entity_list;
|
||||
extern Zone* zone;
|
||||
extern NatsManager nats;
|
||||
|
||||
EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills::SkillType skillinuse)
|
||||
{
|
||||
@ -2232,7 +2234,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil
|
||||
entity_list.QueueClients(killer_mob, app, false);
|
||||
|
||||
safe_delete(app);
|
||||
|
||||
nats.OnDeathEvent(d);
|
||||
if (respawn2) {
|
||||
respawn2->DeathReset(1);
|
||||
}
|
||||
@ -2816,6 +2818,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
|
||||
cds->damage = DS;
|
||||
entity_list.QueueCloseClients(this, outapp);
|
||||
safe_delete(outapp);
|
||||
nats.OnDamageEvent(cds->source, cds);
|
||||
}
|
||||
else if (DS > 0 && !spell_ds) {
|
||||
//we are healing the attacker...
|
||||
@ -3740,7 +3743,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
CastToClient()->QueuePacket(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
nats.OnDamageEvent(a->source, a);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -59,6 +59,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "water_map.h"
|
||||
#include "worldserver.h"
|
||||
#include "zone.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
@ -70,6 +71,8 @@ extern volatile bool is_zone_loaded;
|
||||
extern WorldServer worldserver;
|
||||
extern PetitionList petition_list;
|
||||
extern EntityList entity_list;
|
||||
extern NatsManager nats;
|
||||
|
||||
typedef void (Client::*ClientPacketProc)(const EQApplicationPacket *app);
|
||||
|
||||
//Use a map for connecting opcodes since it dosent get used a lot and is sparse
|
||||
@ -1262,6 +1265,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
struct in_addr ghost_addr;
|
||||
ghost_addr.s_addr = eqs->GetRemoteIP();
|
||||
|
||||
nats.SendAdminMessage(StringFormat("Ghosting client: Account ID:%i Name:%s Character:%s IP:%s",
|
||||
client->AccountID(), client->AccountName(), client->GetName(), inet_ntoa(ghost_addr)));
|
||||
Log(Logs::General, Logs::Error, "Ghosting client: Account ID:%i Name:%s Character:%s IP:%s",
|
||||
client->AccountID(), client->AccountName(), client->GetName(), inet_ntoa(ghost_addr));
|
||||
client->Save();
|
||||
@ -2931,7 +2936,7 @@ void Client::Handle_OP_Assist(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nats.OnEntityEvent(OP_Assist, this->GetID(), eid->entity_id);
|
||||
FastQueuePacket(&outapp);
|
||||
return;
|
||||
}
|
||||
@ -3978,6 +3983,7 @@ void Client::Handle_OP_Camp(const EQApplicationPacket *app)
|
||||
if (IsLFP())
|
||||
worldserver.StopLFP(CharacterID());
|
||||
|
||||
nats.OnEntityEvent(OP_Camp, this->GetID(), 0);
|
||||
if (GetGM())
|
||||
{
|
||||
OnDisconnect(true);
|
||||
@ -4203,7 +4209,7 @@ void Client::Handle_OP_ChannelMessage(const EQApplicationPacket *app)
|
||||
Message(13, "You try to speak but cant move your mouth!");
|
||||
return;
|
||||
}
|
||||
|
||||
nats.OnChannelMessageEvent(this->GetID(), cm);
|
||||
ChannelMessageReceived(cm->chan_num, cm->language, cm->skill_in_language, cm->message, cm->targetname);
|
||||
return;
|
||||
}
|
||||
@ -5165,6 +5171,7 @@ void Client::Handle_OP_Damage(const EQApplicationPacket *app)
|
||||
CombatDamage_Struct* damage = (CombatDamage_Struct*)app->pBuffer;
|
||||
//dont send to originator of falling damage packets
|
||||
entity_list.QueueClients(this, app, (damage->type == DamageTypeFalling));
|
||||
nats.OnDamageEvent(damage->source, damage);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5913,6 +5920,7 @@ void Client::Handle_OP_GMBecomeNPC(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/becomenpc");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /becomenpc attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(BecomeNPC_Struct)) {
|
||||
@ -5944,6 +5952,7 @@ void Client::Handle_OP_GMDelCorpse(const EQApplicationPacket *app)
|
||||
if (this->Admin() < commandEditPlayerCorpses) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/delcorpse");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /delcorpse attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
GMDelCorpse_Struct* dc = (GMDelCorpse_Struct *)app->pBuffer;
|
||||
@ -5965,6 +5974,7 @@ void Client::Handle_OP_GMEmoteZone(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/emote");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /emote attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(GMEmoteZone_Struct)) {
|
||||
@ -5998,6 +6008,7 @@ void Client::Handle_OP_GMFind(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/find");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /find attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(GMSummon_Struct)) {
|
||||
@ -6036,6 +6047,7 @@ void Client::Handle_OP_GMGoto(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/goto");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /goto attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
GMSummon_Struct* gmg = (GMSummon_Struct*)app->pBuffer;
|
||||
@ -6063,6 +6075,7 @@ void Client::Handle_OP_GMHideMe(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/hideme");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /hideme attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(SpawnAppearance_Struct)) {
|
||||
@ -6083,6 +6096,7 @@ void Client::Handle_OP_GMKick(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToKick) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/kick");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /kick attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
GMKick_Struct* gmk = (GMKick_Struct *)app->pBuffer;
|
||||
@ -6113,6 +6127,7 @@ void Client::Handle_OP_GMKill(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/kill");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /kill attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(GMKill_Struct)) {
|
||||
@ -6165,6 +6180,7 @@ void Client::Handle_OP_GMLastName(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(client->account_name, client->name, "/lastname");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /lastname attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -6190,6 +6206,7 @@ void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/name");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /name attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
Client* client = entity_list.GetClientByName(gmn->oldname);
|
||||
@ -6334,6 +6351,7 @@ void Client::Handle_OP_GMToggle(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToUseGMCommands) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/toggle");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /toggle attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
GMToggle_Struct *ts = (GMToggle_Struct *)app->pBuffer;
|
||||
@ -6385,6 +6403,7 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToBeGM) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/zone");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /zone attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -6433,6 +6452,7 @@ void Client::Handle_OP_GMZoneRequest2(const EQApplicationPacket *app)
|
||||
if (this->Admin() < minStatusToBeGM) {
|
||||
Message(13, "Your account has been reported for hacking.");
|
||||
database.SetHackerFlag(this->account_name, this->name, "/zone");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s /zone attempt.", GetCleanName()));
|
||||
return;
|
||||
}
|
||||
if (app->size < sizeof(uint32)) {
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
#include "../common/string_util.h"
|
||||
#include "event_codes.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "nats_manager.h"
|
||||
#include "map.h"
|
||||
#include "petitions.h"
|
||||
#include "queryserv.h"
|
||||
@ -60,6 +61,7 @@ extern volatile bool is_zone_loaded;
|
||||
extern WorldServer worldserver;
|
||||
extern PetitionList petition_list;
|
||||
extern EntityList entity_list;
|
||||
extern NatsManager nats;
|
||||
|
||||
bool Client::Process() {
|
||||
bool ret = true;
|
||||
@ -2199,7 +2201,7 @@ void Client::ClearHover()
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
nats.OnSpawnEvent(OP_ZoneEntry, this->GetID(), &sze->player.spawn);
|
||||
dead = false;
|
||||
}
|
||||
|
||||
|
||||
@ -67,10 +67,12 @@
|
||||
#include "titles.h"
|
||||
#include "water_map.h"
|
||||
#include "worldserver.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern WorldServer worldserver;
|
||||
extern TaskManager *taskmanager;
|
||||
extern NatsManager nats;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
|
||||
@ -563,6 +565,8 @@ int command_realdispatch(Client *c, const char *message)
|
||||
QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
nats.SendAdminMessage(StringFormat("%s in %s issued command: %s", c->GetCleanName(), database.GetZoneName(zone->GetZoneID()), message));
|
||||
|
||||
if(cur->access >= COMMANDS_LOGGING_MIN_STATUS) {
|
||||
Log(Logs::General, Logs::Commands, "%s (%s) used command: %s (target=%s)", c->GetName(), c->AccountName(), message, c->GetTarget()?c->GetTarget()->GetName():"NONE");
|
||||
}
|
||||
|
||||
@ -4879,3 +4879,16 @@ 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,6 +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);
|
||||
|
||||
@ -23,8 +23,10 @@
|
||||
#include "quest_parser_collection.h"
|
||||
#include "worldserver.h"
|
||||
#include "zonedb.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
extern WorldServer worldserver;
|
||||
extern NatsManager nats;
|
||||
|
||||
// @merth: this needs to be touched up
|
||||
uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
@ -626,6 +628,7 @@ void Client::DropItem(int16 slot_id, bool recurse)
|
||||
invalid_drop = nullptr;
|
||||
|
||||
database.SetHackerFlag(this->AccountName(), this->GetCleanName(), "Tried to drop an item on the ground that was nodrop!");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s: Tried to drop nodrop item on ground", GetCleanName()));
|
||||
GetInv().DeleteItem(slot_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "mob.h"
|
||||
#include "npc.h"
|
||||
#include "zonedb.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
@ -34,6 +35,8 @@
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
extern NatsManager nats;
|
||||
|
||||
// Queries the loottable: adds item & coin to the npc
|
||||
void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
|
||||
const LootTable_Struct* lts = nullptr;
|
||||
@ -242,6 +245,7 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch
|
||||
wc = (WearChange_Struct*)outapp->pBuffer;
|
||||
wc->spawn_id = GetID();
|
||||
wc->material=0;
|
||||
nats.OnWearChangeEvent(this->GetID(), wc);
|
||||
}
|
||||
|
||||
item->item_id = item2->ID;
|
||||
|
||||
9
zone/lua.hpp
Normal file
9
zone/lua.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
// lua.hpp
|
||||
// Lua header files for C++
|
||||
// <<extern "C">> not supplied automatically because Lua also compiles as C++
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
2044
zone/map.cpp
2044
zone/map.cpp
File diff suppressed because it is too large
Load Diff
51
zone/map.h
51
zone/map.h
@ -30,40 +30,41 @@
|
||||
#define BEST_Z_INVALID -99999
|
||||
|
||||
extern const ZoneConfig *Config;
|
||||
|
||||
class Map
|
||||
namespace EQEmu
|
||||
{
|
||||
public:
|
||||
Map();
|
||||
~Map();
|
||||
class Map
|
||||
{
|
||||
public:
|
||||
Map();
|
||||
~Map();
|
||||
|
||||
float FindBestZ(glm::vec3 &start, glm::vec3 *result) const;
|
||||
float FindClosestZ(glm::vec3 &start, glm::vec3 *result) const;
|
||||
bool LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const;
|
||||
bool LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const;
|
||||
bool CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const;
|
||||
float FindBestZ(glm::vec3 &start, glm::vec3 *result) const;
|
||||
float FindClosestZ(glm::vec3 &start, glm::vec3 *result) const;
|
||||
bool LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const;
|
||||
bool LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const;
|
||||
bool CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const;
|
||||
|
||||
#ifdef USE_MAP_MMFS
|
||||
bool Load(std::string filename, bool force_mmf_overwrite = false);
|
||||
bool Load(std::string filename, bool force_mmf_overwrite = false);
|
||||
#else
|
||||
bool Load(std::string filename);
|
||||
bool Load(std::string filename);
|
||||
#endif
|
||||
|
||||
static Map *LoadMapFile(std::string file);
|
||||
private:
|
||||
void RotateVertex(glm::vec3 &v, float rx, float ry, float rz);
|
||||
void ScaleVertex(glm::vec3 &v, float sx, float sy, float sz);
|
||||
void TranslateVertex(glm::vec3 &v, float tx, float ty, float tz);
|
||||
bool LoadV1(FILE *f);
|
||||
bool LoadV2(FILE *f);
|
||||
static Map *LoadMapFile(std::string file);
|
||||
private:
|
||||
void RotateVertex(glm::vec3 &v, float rx, float ry, float rz);
|
||||
void ScaleVertex(glm::vec3 &v, float sx, float sy, float sz);
|
||||
void TranslateVertex(glm::vec3 &v, float tx, float ty, float tz);
|
||||
bool LoadV1(FILE *f);
|
||||
bool LoadV2(FILE *f);
|
||||
|
||||
#ifdef USE_MAP_MMFS
|
||||
bool LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite);
|
||||
bool SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite);
|
||||
bool LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite);
|
||||
bool SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite);
|
||||
#endif /*USE_MAP_MMFS*/
|
||||
|
||||
struct impl;
|
||||
impl *imp;
|
||||
};
|
||||
|
||||
struct impl;
|
||||
impl *imp;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
23
zone/mob.cpp
23
zone/mob.cpp
@ -23,6 +23,7 @@
|
||||
#include "quest_parser_collection.h"
|
||||
#include "string_ids.h"
|
||||
#include "worldserver.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
@ -37,6 +38,7 @@ extern EntityList entity_list;
|
||||
|
||||
extern Zone* zone;
|
||||
extern WorldServer worldserver;
|
||||
extern NatsManager nats;
|
||||
|
||||
Mob::Mob(const char* in_name,
|
||||
const char* in_lastname,
|
||||
@ -944,7 +946,7 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) {
|
||||
memset(app->pBuffer, 0, app->size);
|
||||
NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer;
|
||||
FillSpawnStruct(ns, ForWho);
|
||||
|
||||
nats.OnSpawnEvent(OP_NewSpawn, ns->spawn.spawnId, &ns->spawn);
|
||||
if(RuleB(NPC, UseClassAsLastName) && strlen(ns->spawn.lastName) == 0)
|
||||
{
|
||||
switch(ns->spawn.class_)
|
||||
@ -1260,6 +1262,7 @@ void Mob::CreateDespawnPacket(EQApplicationPacket* app, bool Decay)
|
||||
ds->spawn_id = GetID();
|
||||
// The next field only applies to corpses. If 0, they vanish instantly, otherwise they 'decay'
|
||||
ds->Decay = Decay ? 1 : 0;
|
||||
nats.OnDeleteSpawnEvent(this->GetID(), ds);
|
||||
}
|
||||
|
||||
void Mob::CreateHPPacket(EQApplicationPacket* app)
|
||||
@ -1270,7 +1273,7 @@ void Mob::CreateHPPacket(EQApplicationPacket* app)
|
||||
app->pBuffer = new uchar[app->size];
|
||||
memset(app->pBuffer, 0, sizeof(SpawnHPUpdate_Struct2));
|
||||
SpawnHPUpdate_Struct2* ds = (SpawnHPUpdate_Struct2*)app->pBuffer;
|
||||
|
||||
nats.OnHPEvent(OP_MobHealth, this->GetID(), cur_hp, max_hp);
|
||||
ds->spawn_id = GetID();
|
||||
// they don't need to know the real hp
|
||||
ds->hp = (int)GetHPRatio();
|
||||
@ -1304,7 +1307,7 @@ void Mob::CreateHPPacket(EQApplicationPacket* app)
|
||||
// sends hp update of this mob to people who might care
|
||||
void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= false*/)
|
||||
{
|
||||
|
||||
nats.OnHPEvent(OP_HPUpdate, this->GetID(), cur_hp, max_hp);
|
||||
/* If our HP is different from last HP update call - let's update ourself */
|
||||
if (IsClient()) {
|
||||
if (cur_hp != last_hp || force_update_all) {
|
||||
@ -1467,7 +1470,7 @@ void Mob::SendPosition() {
|
||||
else {
|
||||
entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false);
|
||||
}
|
||||
|
||||
nats.OnClientUpdateEvent(this->GetID(), spu);
|
||||
safe_delete(app);
|
||||
}
|
||||
|
||||
@ -1481,7 +1484,7 @@ void Mob::SendPositionUpdateToClient(Client *client) {
|
||||
MakeSpawnUpdateNoDelta(spawn_update);
|
||||
|
||||
client->QueuePacket(app, false);
|
||||
|
||||
nats.OnClientUpdateEvent(this->GetID(), spawn_update);
|
||||
safe_delete(app);
|
||||
}
|
||||
|
||||
@ -1504,6 +1507,7 @@ void Mob::SendPositionUpdate(uint8 iSendToSelf) {
|
||||
else {
|
||||
entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false);
|
||||
}
|
||||
nats.OnClientUpdateEvent(this->GetID(), spu);
|
||||
safe_delete(app);
|
||||
}
|
||||
|
||||
@ -1622,7 +1626,7 @@ void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter)
|
||||
ackreq, /* Packet ACK */
|
||||
filter /* eqFilterType filter */
|
||||
);
|
||||
|
||||
nats.OnAnimationEvent(this->GetID(), anim);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -2899,7 +2903,7 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client)
|
||||
{
|
||||
one_client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
|
||||
}
|
||||
|
||||
nats.OnWearChangeEvent(this->GetID(), wc);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -2923,6 +2927,7 @@ void Mob::SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model, uin
|
||||
|
||||
|
||||
entity_list.QueueClients(this, outapp);
|
||||
nats.OnWearChangeEvent(this->GetID(), wc);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -2945,6 +2950,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
|
||||
wc->wear_slot_id = material_slot;
|
||||
|
||||
entity_list.QueueClients(this, outapp);
|
||||
nats.OnWearChangeEvent(this->GetID(), wc);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -2962,6 +2968,7 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 h
|
||||
wc->wear_slot_id = material_slot;
|
||||
|
||||
entity_list.QueueClients(this, outapp);
|
||||
nats.OnWearChangeEvent(this->GetID(), wc);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -4688,7 +4695,9 @@ void Mob::DoKnockback(Mob *caster, uint32 pushback, uint32 pushup)
|
||||
outapp_push->priority = 6;
|
||||
entity_list.QueueClients(this, outapp_push, true);
|
||||
CastToClient()->FastQueuePacket(&outapp_push);
|
||||
nats.OnClientUpdateEvent(this->GetID(), spu);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
|
||||
|
||||
867
zone/nats_manager.cpp
Normal file
867
zone/nats_manager.cpp
Normal file
@ -0,0 +1,867 @@
|
||||
#include "entity.h"
|
||||
#include "mob.h"
|
||||
//#include "client.h" //map error
|
||||
#include "event_codes.h"
|
||||
#include "nats.h"
|
||||
#include "zone_config.h"
|
||||
#include "nats_manager.h"
|
||||
//#include "guild_mgr.h" //used for database, map error
|
||||
#include "npc.h"
|
||||
|
||||
#include "../common/opcodemgr.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/string_util.h"
|
||||
#ifndef PROTO_H
|
||||
#define PROTO_H
|
||||
#include "../common/proto/message.pb.h"
|
||||
#endif
|
||||
|
||||
const ZoneConfig *zoneConfig;
|
||||
|
||||
NatsManager::NatsManager()
|
||||
{
|
||||
//new timers, object initialization
|
||||
|
||||
zoneConfig = ZoneConfig::get();
|
||||
}
|
||||
|
||||
NatsManager::~NatsManager()
|
||||
{
|
||||
nats_timer.Disable();
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
}
|
||||
|
||||
void NatsManager::Process()
|
||||
{
|
||||
if (zoneSub == NULL) {
|
||||
return;
|
||||
}
|
||||
if (!connect()) return;
|
||||
natsMsg *msg = NULL;
|
||||
|
||||
s = NATS_OK;
|
||||
std::string pubMessage;
|
||||
for (int count = 0; (s == NATS_OK) && count < 100; count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, zoneSub, 1);
|
||||
if (s != NATS_OK) break;
|
||||
Log(Logs::General, Logs::NATS, "got message '%s'", natsMsg_GetData(msg));
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
|
||||
s = NATS_OK;
|
||||
for (int count = 0; (s == NATS_OK) && count < 5; count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, commandMessageSub, 1);
|
||||
if (s != NATS_OK) break;
|
||||
Log(Logs::General, Logs::World_Server, "NATS Got Command Message '%s'", natsMsg_GetData(msg));
|
||||
eqproto::CommandMessage message;
|
||||
|
||||
if (!message.ParseFromString(natsMsg_GetData(msg))) {
|
||||
Log(Logs::General, Logs::World_Server, "Failed to marshal");
|
||||
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("spawn") == 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 {
|
||||
auto entities = eqproto::Entities();
|
||||
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_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.");
|
||||
}
|
||||
|
||||
if (!message.SerializeToString(&pubMessage)) {
|
||||
Log(Logs::General, Logs::World_Server, "NATS Failed to serialize command message to string");
|
||||
return;
|
||||
}
|
||||
|
||||
s = natsConnection_PublishString(conn, natsMsg_GetReply(msg), pubMessage.c_str());
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::World_Server, "NATS Failed to send CommandMessageEvent");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Unregister is called when a zone is being put to sleep or being swapped
|
||||
void NatsManager::Unregister()
|
||||
{
|
||||
if (!connect()) return;
|
||||
if (commandMessageSub != NULL) {
|
||||
s = natsSubscription_Unsubscribe(commandMessageSub);
|
||||
commandMessageSub = NULL;
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "unsubscribe from commandMessageSub failed: %s", nats_GetLastError(&s));
|
||||
}
|
||||
|
||||
if (zoneChannelMessageSub != NULL) {
|
||||
s = natsSubscription_Unsubscribe(zoneChannelMessageSub);
|
||||
zoneChannelMessageSub = NULL;
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "unsubscribe from zoneChannelMessageSub failed: %s", nats_GetLastError(&s));
|
||||
}
|
||||
|
||||
if (zoneEntityEventSubscribeAllSub != NULL) {
|
||||
s = natsSubscription_Unsubscribe(zoneEntityEventSubscribeAllSub);
|
||||
zoneEntityEventSubscribeAllSub = NULL;
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "unsubscribe from zoneEntityEventSubscribeAllSub failed: %s", nats_GetLastError(&s));
|
||||
}
|
||||
if (zoneEntityEventSubscribeSub != NULL) {
|
||||
s = natsSubscription_Unsubscribe(zoneEntityEventSubscribeSub);
|
||||
zoneEntityEventSubscribeSub = NULL;
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "unsubscribe from zoneEntityEventSubscribeSub failed: %s", nats_GetLastError(&s));
|
||||
}
|
||||
|
||||
if (zoneEntityEventListSub != NULL) {
|
||||
s = natsSubscription_Unsubscribe(zoneEntityEventListSub);
|
||||
zoneEntityEventListSub = NULL;
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "unsubscribe from zoneEntityEventListSub failed: %s", nats_GetLastError(&s));
|
||||
}
|
||||
|
||||
if (zoneEntityEventSub != NULL) {
|
||||
s = natsSubscription_Unsubscribe(zoneEntityEventSub);
|
||||
zoneEntityEventSub = NULL;
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "unsubscribe from zoneEntityEventSub failed: %s", nats_GetLastError(&s));
|
||||
}
|
||||
|
||||
Log(Logs::General, Logs::NATS, "unsubscribed from %s", subscribedZonename.c_str());
|
||||
subscribedZonename.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void NatsManager::ZoneSubscribe(const char* zonename) {
|
||||
if (strcmp(subscribedZonename.c_str(), zonename) == 0) return;
|
||||
if (!connect()) return;
|
||||
Unregister();
|
||||
|
||||
subscribedZonename = std::string(zonename);
|
||||
|
||||
s = natsConnection_SubscribeSync(&zoneChannelMessageSub, conn, StringFormat("zone.%s.channel_message", subscribedZonename.c_str()).c_str());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to subscribe to zoneChannelMessageSub %s", nats_GetLastError(&s));
|
||||
s = natsSubscription_SetPendingLimits(zoneChannelMessageSub, -1, -1);
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to set pending limits to zoneChannelMessageSub %s", nats_GetLastError(&s));
|
||||
|
||||
s = natsConnection_SubscribeSync(&commandMessageSub, conn, StringFormat("zone.%s.command_message", subscribedZonename.c_str()).c_str());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to subscribe to commandMessageSub %s", nats_GetLastError(&s));
|
||||
s = natsSubscription_SetPendingLimits(commandMessageSub, -1, -1);
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to set pending limits to commandMessageSub %s", nats_GetLastError(&s));
|
||||
|
||||
s = natsConnection_SubscribeSync(&zoneEntityEventSubscribeAllSub, conn, StringFormat("zone.%s.entity.event_subscribe.all", subscribedZonename.c_str()).c_str());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to subscribe to zoneEntityEventSubscribeAllSub %s", nats_GetLastError(&s));
|
||||
s = natsSubscription_SetPendingLimits(zoneEntityEventSubscribeAllSub, -1, -1);
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to set pending limits to zoneEntityEventSubscribeAllSub %s", nats_GetLastError(&s));
|
||||
|
||||
s = natsConnection_SubscribeSync(&zoneEntityEventSubscribeAllSub, conn, StringFormat("zone.%s.entity.event_subscribe.all", subscribedZonename.c_str()).c_str());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to subscribe to zoneEntityEventSubscribeAllSub %s", nats_GetLastError(&s));
|
||||
s = natsSubscription_SetPendingLimits(zoneEntityEventSubscribeAllSub, -1, -1);
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to set pending limits to zoneEntityEventSubscribeAllSub %s", nats_GetLastError(&s));
|
||||
|
||||
Log(Logs::General, Logs::NATS, "subscribed to %s", subscribedZonename.c_str());
|
||||
}
|
||||
|
||||
|
||||
void NatsManager::SendAdminMessage(std::string adminMessage) {
|
||||
if (!connect()) return;
|
||||
|
||||
eqproto::ChannelMessage message;
|
||||
message.set_message(adminMessage.c_str());
|
||||
std::string pubMessage;
|
||||
if (!message.SerializeToString(&pubMessage)) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to serialize message to string");
|
||||
return;
|
||||
}
|
||||
s = natsConnection_PublishString(conn, "NATS AdminMessage", pubMessage.c_str());
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "Failed to SendAdminMessage");
|
||||
}
|
||||
Log(Logs::General, Logs::NATS, "AdminMessage: %s", adminMessage.c_str());
|
||||
}
|
||||
|
||||
|
||||
bool NatsManager::connect() {
|
||||
auto ncs = natsConnection_Status(conn);
|
||||
if (ncs == CONNECTED) return true;
|
||||
if (nats_timer.Enabled() && !nats_timer.Check()) return false;
|
||||
natsOptions *opts = NULL;
|
||||
natsOptions_Create(&opts);
|
||||
natsOptions_SetMaxReconnect(opts, 0);
|
||||
natsOptions_SetReconnectWait(opts, 0);
|
||||
natsOptions_SetAllowReconnect(opts, false);
|
||||
//The timeout is going to cause a 100ms delay on all connected clients every X seconds (20s)
|
||||
//since this blocks the connection. It can be set lower or higher delay,
|
||||
//but since NATS is a second priority I wanted server impact minimum.
|
||||
natsOptions_SetTimeout(opts, 100);
|
||||
std::string connection = StringFormat("nats://%s:%d", zoneConfig->NATSHost.c_str(), zoneConfig->NATSPort);
|
||||
if (zoneConfig->NATSHost.length() == 0) connection = "nats://localhost:4222";
|
||||
natsOptions_SetURL(opts, connection.c_str());
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
natsOptions_Destroy(opts);
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to connect to %s: %s, retrying in 20s", connection.c_str(), nats_GetLastError(&s));
|
||||
conn = NULL;
|
||||
nats_timer.Enable();
|
||||
nats_timer.SetTimer(20000);
|
||||
return false;
|
||||
}
|
||||
Log(Logs::General, Logs::NATS, "connected to %s", connection.c_str());
|
||||
nats_timer.Disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NatsManager::Load()
|
||||
{
|
||||
if (!connect()) return;
|
||||
|
||||
s = natsConnection_SubscribeSync(&zoneSub, conn, "zone");
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to subscribe to zone: %s", nats_GetLastError(&s));
|
||||
return;
|
||||
}
|
||||
s = natsSubscription_SetPendingLimits(zoneSub, -1, -1);
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to set pending limits while subscribed to zone %s", nats_GetLastError(&s));
|
||||
return;
|
||||
}
|
||||
|
||||
s = natsConnection_SubscribeSync(&commandMessageSub, conn, "zone.command_message");
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to subscribe to commandMessageSub: %s", nats_GetLastError(&s));
|
||||
return;
|
||||
}
|
||||
s = natsSubscription_SetPendingLimits(commandMessageSub, -1, -1);
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to set pending limits while subscribed to commandMessageSub: %s", nats_GetLastError(&s));
|
||||
return;
|
||||
}
|
||||
|
||||
s = natsConnection_SubscribeSync(&channelMessageSub, conn, "zone.channel_message");
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to subscribe to channel message: %s", nats_GetLastError(&s));
|
||||
return;
|
||||
}
|
||||
s = natsSubscription_SetPendingLimits(channelMessageSub, -1, -1);
|
||||
if (s != NATS_OK) {
|
||||
Log(Logs::General, Logs::NATS, "failed to set pending limits while subscribed to channel message: %s", nats_GetLastError(&s));
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void NatsManager::DailyGain(int account_id, int character_id, const char* identity, int levels_gained, int experience_gained, int money_earned)
|
||||
{
|
||||
if (!connect()) return;
|
||||
eqproto::DailyGain daily;
|
||||
daily.set_account_id(account_id);
|
||||
daily.set_character_id(character_id);
|
||||
daily.set_identity(identity);
|
||||
daily.set_levels_gained(levels_gained);
|
||||
daily.set_experience_gained(experience_gained);
|
||||
daily.set_money_earned(money_earned);
|
||||
std::string pubMessage;
|
||||
if (!daily.SerializeToString(&pubMessage)) {
|
||||
Log(Logs::General, Logs::NATS, "failed to serialize dailygain to string");
|
||||
return;
|
||||
}
|
||||
|
||||
s = natsConnection_PublishString(conn, "DailyGain", pubMessage.c_str());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "failed to send DailyGain: %s", nats_GetLastError(&s));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void NatsManager::OnDeathEvent(Death_Struct* d) {
|
||||
if (!connect()) return;
|
||||
if (d == NULL) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(d->spawn_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::DeathEvent();
|
||||
|
||||
event.set_spawn_id(d->spawn_id);
|
||||
event.set_killer_id(d->killer_id);
|
||||
event.set_bind_zone_id(d->bindzoneid);
|
||||
event.set_spell_id(d->spell_id);
|
||||
event.set_attack_skill_id(d->attack_skill);
|
||||
event.set_damage(d->damage);
|
||||
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
finalEvent.set_op(eqproto::OP_Death);
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), d->spawn_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
|
||||
void NatsManager::OnChannelMessageEvent(uint32 entity_id, ChannelMessage_Struct* cm) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::ChannelMessageEvent();
|
||||
|
||||
event.set_target_name(cm->targetname);
|
||||
event.set_sender(cm->sender);
|
||||
event.set_language(cm->language);
|
||||
event.set_chan_num(cm->chan_num);
|
||||
event.set_cm_unknown4(*cm->cm_unknown4);
|
||||
event.set_skill_in_language(cm->skill_in_language);
|
||||
event.set_message(cm->message);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
finalEvent.set_op(eqproto::OP_ChannelMessage);
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).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) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::EntityEvent();
|
||||
|
||||
event.set_entity_id(entity_id);
|
||||
event.set_target_id(target_id);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
if (op == OP_Camp) finalEvent.set_op(eqproto::OP_Camp);
|
||||
else if (op == OP_Assist) finalEvent.set_op(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, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
|
||||
void NatsManager::OnSpawnEvent(const EmuOpcode op, uint32 entity_id, Spawn_Struct *spawn) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::SpawnEvent();
|
||||
|
||||
event.set_unknown0000(spawn->unknown0000);
|
||||
event.set_gm(spawn->gm);
|
||||
event.set_unknown0003(spawn->unknown0003);
|
||||
event.set_aaitle(spawn->aaitle);
|
||||
event.set_unknown0004(spawn->unknown0004);
|
||||
event.set_anon(spawn->anon);
|
||||
event.set_face(spawn->face);
|
||||
event.set_name(spawn->name);
|
||||
event.set_deity(spawn->deity);
|
||||
event.set_unknown0073(spawn->unknown0073);
|
||||
event.set_size(spawn->size);
|
||||
event.set_unknown0079(spawn->unknown0079);
|
||||
event.set_npc(spawn->NPC);
|
||||
event.set_invis(spawn->invis);
|
||||
event.set_haircolor(spawn->haircolor);
|
||||
event.set_curhp(spawn->curHp);
|
||||
event.set_max_hp(spawn->max_hp);
|
||||
event.set_findable(spawn->findable);
|
||||
event.set_unknown0089(*spawn->unknown0089);
|
||||
event.set_deltaheading(spawn->deltaHeading);
|
||||
event.set_x(spawn->x);
|
||||
event.set_padding0054(spawn->padding0054);
|
||||
event.set_y(spawn->y);
|
||||
event.set_animation(spawn->animation);
|
||||
event.set_padding0058(spawn->padding0058);
|
||||
event.set_z(spawn->z);
|
||||
event.set_deltay(spawn->deltaY);
|
||||
event.set_deltax(spawn->deltaX);
|
||||
event.set_heading(spawn->heading);
|
||||
event.set_padding0066(spawn->padding0066);
|
||||
event.set_deltaz(spawn->deltaZ);
|
||||
event.set_padding0070(spawn->padding0070);
|
||||
event.set_eyecolor1(spawn->eyecolor1);
|
||||
event.set_unknown0115(*spawn->unknown0115);
|
||||
event.set_standstate(spawn->StandState);
|
||||
event.set_drakkin_heritage(spawn->drakkin_heritage);
|
||||
event.set_drakkin_tattoo(spawn->drakkin_tattoo);
|
||||
event.set_drakkin_details(spawn->drakkin_details);
|
||||
event.set_showhelm(spawn->showhelm);
|
||||
event.set_unknown0140(*spawn->unknown0140);
|
||||
event.set_is_npc(spawn->is_npc);
|
||||
event.set_hairstyle(spawn->hairstyle);
|
||||
event.set_beard(spawn->beard);
|
||||
event.set_unknown0147(*spawn->unknown0147);
|
||||
event.set_level(spawn->level);
|
||||
event.set_playerstate(spawn->PlayerState);
|
||||
event.set_beardcolor(spawn->beardcolor);
|
||||
event.set_suffix(spawn->suffix);
|
||||
event.set_petownerid(spawn->petOwnerId);
|
||||
event.set_guildrank(spawn->guildrank);
|
||||
event.set_unknown0194(*spawn->unknown0194);
|
||||
|
||||
/*auto texture = eqproto::Texture();
|
||||
texture.set_elitemodel(spawn->equipment.Arms.EliteModel);
|
||||
texture.set_herosforgemodel(spawn->equipment.Arms.HerosForgeModel);
|
||||
texture.set_material(spawn->equipment.Arms.Material);
|
||||
texture.set_unknown1(spawn->equipment.Arms.Unknown1);
|
||||
texture.set_unknown2(spawn->equipment.Arms.Unknown2);
|
||||
event.set_allocated_equipment(textureProfile);*/
|
||||
event.set_runspeed(spawn->runspeed);
|
||||
event.set_afk(spawn->afk);
|
||||
event.set_guildid(spawn->guildID);
|
||||
event.set_title(spawn->title);
|
||||
event.set_unknown0274(spawn->unknown0274);
|
||||
event.set_set_to_0xff(*spawn->set_to_0xFF);
|
||||
event.set_helm(spawn->helm);
|
||||
event.set_race(spawn->race);
|
||||
event.set_unknown0288(spawn->unknown0288);
|
||||
event.set_lastname(spawn->lastName);
|
||||
event.set_walkspeed(spawn->walkspeed);
|
||||
event.set_unknown0328(spawn->unknown0328);
|
||||
event.set_is_pet(spawn->is_pet);
|
||||
event.set_light(spawn->light);
|
||||
event.set_class_(spawn->class_);
|
||||
event.set_eyecolor2(spawn->eyecolor2);
|
||||
event.set_flymode(spawn->flymode);
|
||||
event.set_gender(spawn->gender);
|
||||
event.set_bodytype(spawn->bodytype);
|
||||
event.set_unknown0336(*spawn->unknown0336);
|
||||
event.set_equip_chest2(spawn->equip_chest2);
|
||||
event.set_mount_color(spawn->mount_color);
|
||||
event.set_spawnid(spawn->spawnId);
|
||||
event.set_unknown0344(*spawn->unknown0344);
|
||||
event.set_ismercenary(spawn->IsMercenary);
|
||||
//event.set_equipment_tint(spawn->equipment_tint);
|
||||
event.set_lfg(spawn->lfg);
|
||||
event.set_destructibleobject(spawn->DestructibleObject);
|
||||
event.set_destructiblemodel(spawn->DestructibleModel);
|
||||
event.set_destructiblename2(spawn->DestructibleName2);
|
||||
event.set_destructiblestring(spawn->DestructibleString);
|
||||
event.set_destructibleappearance(spawn->DestructibleAppearance);
|
||||
event.set_destructibleunk1(spawn->DestructibleUnk1);
|
||||
event.set_destructibleid1(spawn->DestructibleID1);
|
||||
event.set_destructibleid2(spawn->DestructibleID2);
|
||||
event.set_destructibleid3(spawn->DestructibleID3);
|
||||
event.set_destructibleid4(spawn->DestructibleID4);
|
||||
event.set_destructibleunk2(spawn->DestructibleUnk2);
|
||||
event.set_destructibleunk3(spawn->DestructibleUnk3);
|
||||
event.set_destructibleunk4(spawn->DestructibleUnk4);
|
||||
event.set_destructibleunk5(spawn->DestructibleUnk5);
|
||||
event.set_destructibleunk6(spawn->DestructibleUnk6);
|
||||
event.set_destructibleunk7(spawn->DestructibleUnk7);
|
||||
event.set_destructibleunk8(spawn->DestructibleUnk8);
|
||||
event.set_destructibleunk9(spawn->DestructibleUnk9);
|
||||
event.set_targetable_with_hotkey(spawn->targetable_with_hotkey);
|
||||
event.set_show_name(spawn->show_name);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
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);
|
||||
else { Log(Logs::General, Logs::NATS, "unhandled op type passed: %i", op); return; }
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
|
||||
void NatsManager::OnWearChangeEvent(uint32 entity_id, WearChange_Struct *wc) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::WearChangeEvent();
|
||||
|
||||
|
||||
event.set_spawn_id(wc->spawn_id);
|
||||
event.set_material(wc->material);
|
||||
event.set_unknown06(wc->unknown06);
|
||||
event.set_elite_material(wc->elite_material);
|
||||
event.set_hero_forge_model(wc->hero_forge_model);
|
||||
event.set_unknown18(wc->unknown18);
|
||||
//event.set_color(wc->color); //tint
|
||||
event.set_wear_slot_id(wc->wear_slot_id);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
finalEvent.set_op(eqproto::OP_WearChange);
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
void NatsManager::OnDeleteSpawnEvent(uint32 entity_id, DeleteSpawn_Struct *ds) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::DeleteSpawnEvent();
|
||||
|
||||
|
||||
event.set_spawn_id(ds->spawn_id);
|
||||
event.set_decay(ds->Decay);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
finalEvent.set_op(eqproto::OP_DeleteSpawn);
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
void NatsManager::OnHPEvent(const EmuOpcode op, uint32 entity_id, uint32 cur_hp, uint32 max_hp) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
if (cur_hp == max_hp) return;
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::HPEvent();
|
||||
|
||||
event.set_spawn_id(entity_id);
|
||||
event.set_cur_hp(cur_hp);
|
||||
event.set_max_hp(max_hp);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
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);
|
||||
else { Log(Logs::General, Logs::NATS, "unhandled op type passed: %i", op); return; }
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
void NatsManager::OnDamageEvent(uint32 entity_id, CombatDamage_Struct *cd) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::DamageEvent();
|
||||
|
||||
event.set_target(cd->target);
|
||||
event.set_source(cd->source);
|
||||
event.set_type(cd->type);
|
||||
event.set_spellid(cd->spellid);
|
||||
event.set_damage(cd->damage);
|
||||
event.set_force(cd->force);
|
||||
event.set_meleepush_xy(cd->meleepush_xy);
|
||||
event.set_meleepush_z(cd->meleepush_z);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
finalEvent.set_op(eqproto::OP_Damage);
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
void NatsManager::OnClientUpdateEvent(uint32 entity_id, PlayerPositionUpdateServer_Struct * spu) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::PlayerPositionUpdateEvent();
|
||||
|
||||
event.set_spawn_id(spu->spawn_id);
|
||||
event.set_delta_heading(spu->delta_heading);
|
||||
event.set_x_pos(spu->x_pos);
|
||||
event.set_padding0002(spu->padding0002);
|
||||
event.set_y_pos(spu->y_pos);
|
||||
event.set_animation(spu->animation);
|
||||
event.set_padding0006(spu->padding0006);
|
||||
event.set_z_pos(spu->z_pos);
|
||||
event.set_delta_y(spu->delta_y);
|
||||
event.set_delta_x(spu->delta_x);
|
||||
event.set_heading(spu->heading);
|
||||
event.set_padding0014(spu->padding0014);
|
||||
event.set_delta_z(spu->delta_z);
|
||||
event.set_padding0018(spu->padding0018);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
finalEvent.set_op(eqproto::OP_ClientUpdate);
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
|
||||
|
||||
void NatsManager::OnAnimationEvent(uint32 entity_id, Animation_Struct *anim) {
|
||||
if (!connect()) return;
|
||||
if (entity_id == 0) return;
|
||||
if (!isEntityEventAllEnabled && !isEntitySubscribed(entity_id)) return;
|
||||
|
||||
std::string pubMessage;
|
||||
auto event = eqproto::AnimationEvent();
|
||||
|
||||
event.set_spawnid(anim->spawnid);
|
||||
event.set_speed(anim->speed);
|
||||
event.set_action(anim->action);
|
||||
|
||||
if (!event.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
auto finalEvent = eqproto::Event();
|
||||
finalEvent.set_payload(pubMessage.c_str());
|
||||
finalEvent.set_op(eqproto::OP_Animation);
|
||||
if (!finalEvent.SerializeToString(&pubMessage)) { Log(Logs::General, Logs::NATS, "Failed to serialize message to string"); return; }
|
||||
s = natsConnection_Publish(conn, StringFormat("zone.%s.entity.event.%d", subscribedZonename.c_str(), entity_id).c_str(), (const void*)pubMessage.c_str(), pubMessage.length());
|
||||
if (s != NATS_OK) Log(Logs::General, Logs::NATS, "Failed to send EntityEvent");
|
||||
}
|
||||
55
zone/nats_manager.h
Normal file
55
zone/nats_manager.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef _NATS_H
|
||||
#define _NATS_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"
|
||||
|
||||
class NatsManager
|
||||
{
|
||||
public:
|
||||
NatsManager();
|
||||
~NatsManager();
|
||||
void Process();
|
||||
void Unregister();
|
||||
void ZoneSubscribe(const char * zonename);
|
||||
void Load();
|
||||
void DailyGain(int account_id, int character_id, const char * identity, int levels_gained = 0, int experience_gained = 0, int money_earned = 0);
|
||||
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);
|
||||
void OnWearChangeEvent(uint32 entity_id, WearChange_Struct * wc);
|
||||
void OnDeleteSpawnEvent(uint32 entity_id, DeleteSpawn_Struct * ds);
|
||||
void OnHPEvent(const EmuOpcode op, uint32 entity_id, uint32 cur_hp, uint32 max_hp);
|
||||
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);
|
||||
protected:
|
||||
bool connect();
|
||||
Timer nats_timer;
|
||||
bool isEntitySubscribed(const uint16 ID);
|
||||
bool isEntityEventAllEnabled = true;
|
||||
natsConnection *conn = NULL;
|
||||
natsStatus s;
|
||||
natsOptions *opts = NULL;
|
||||
std::string subscribedZonename;
|
||||
//global zone subscriptions
|
||||
natsSubscription *zoneSub = NULL;
|
||||
natsSubscription *channelMessageSub = NULL;
|
||||
natsSubscription *commandMessageSub = NULL;
|
||||
//zone specific subscriptions
|
||||
natsSubscription *zoneChannelMessageSub = NULL;
|
||||
natsSubscription *zoneCommandMessageSub = NULL;
|
||||
natsSubscription *zoneEntityEventSubscribeAllSub = NULL;
|
||||
natsSubscription *zoneEntityEventSubscribeSub = NULL;
|
||||
natsSubscription *zoneEntityEventListSub = NULL;
|
||||
natsSubscription *zoneEntityEventSub = NULL;
|
||||
};
|
||||
|
||||
#endif
|
||||
16
zone/net.cpp
16
zone/net.cpp
@ -62,6 +62,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "embparser.h"
|
||||
#include "lua_parser.h"
|
||||
#include "questmgr.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include "../common/event/event_loop.h"
|
||||
#include "../common/event/timer.h"
|
||||
@ -100,6 +101,8 @@ WorldServer worldserver;
|
||||
uint32 numclients = 0;
|
||||
char errorname[32];
|
||||
extern Zone* zone;
|
||||
NatsManager nats;
|
||||
|
||||
npcDecayTimes_Struct npcCorpseDecayTimes[100];
|
||||
TitleManager title_manager;
|
||||
QueryServ *QServ = 0;
|
||||
@ -131,7 +134,7 @@ int main(int argc, char** argv) {
|
||||
std::string filename = Config->MapDir;
|
||||
filename += mapfile;
|
||||
|
||||
auto m = new Map();
|
||||
auto m = new EQEmu::Map();
|
||||
auto success = m->Load(filename, true);
|
||||
delete m;
|
||||
std::cout << mapfile.c_str() << " conversion " << (success ? "succeeded" : "failed") << std::endl;
|
||||
@ -148,6 +151,7 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
Config = ZoneConfig::get();
|
||||
nats.Load();
|
||||
|
||||
const char *zone_name;
|
||||
uint32 instance_id = 0;
|
||||
@ -510,10 +514,14 @@ int main(int argc, char** argv) {
|
||||
entity_list.MobProcess();
|
||||
entity_list.BeaconProcess();
|
||||
entity_list.EncounterProcess();
|
||||
|
||||
if (zone->IsLoaded()) {
|
||||
nats.ZoneSubscribe(zone->GetShortName());
|
||||
nats.Process();
|
||||
}
|
||||
if (zone) {
|
||||
if (!zone->Process()) {
|
||||
Zone::Shutdown();
|
||||
nats.Unregister();
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,8 +579,10 @@ int main(int argc, char** argv) {
|
||||
|
||||
safe_delete(Config);
|
||||
|
||||
if (zone != 0)
|
||||
if (zone != 0) {
|
||||
Zone::Shutdown(true);
|
||||
nats.Unregister();
|
||||
}
|
||||
//Fix for Linux world server problem.
|
||||
safe_delete(taskmanager);
|
||||
command_deinit();
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "quest_parser_collection.h"
|
||||
#include "string_ids.h"
|
||||
#include "worldserver.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@ -42,6 +43,7 @@
|
||||
extern Zone* zone;
|
||||
extern volatile bool is_zone_loaded;
|
||||
extern WorldServer worldserver;
|
||||
extern NatsManager nats;
|
||||
|
||||
|
||||
// the spell can still fail here, if the buff can't stack
|
||||
@ -936,6 +938,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
Save();
|
||||
safe_delete(action_packet);
|
||||
safe_delete(message_packet);
|
||||
nats.OnDamageEvent(cd->source, cd);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -987,6 +990,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
Save();
|
||||
safe_delete(action_packet);
|
||||
safe_delete(message_packet);
|
||||
nats.OnDamageEvent(cd->source, cd);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1025,6 +1029,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
Save();
|
||||
safe_delete(action_packet);
|
||||
safe_delete(message_packet);
|
||||
nats.OnDamageEvent(cd->source, cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +81,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
#include "quest_parser_collection.h"
|
||||
#include "string_ids.h"
|
||||
#include "worldserver.h"
|
||||
#include "nats_manager.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
@ -104,6 +105,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
extern Zone* zone;
|
||||
extern volatile bool is_zone_loaded;
|
||||
extern WorldServer worldserver;
|
||||
extern NatsManager nats;
|
||||
|
||||
using EQEmu::CastingSlot;
|
||||
|
||||
@ -252,6 +254,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
Log(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) which they shouldn't be able to equip!",
|
||||
CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID);
|
||||
database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking equip-only item with an invalid class");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s: Clicking equip-only item with an invalid class.", GetCleanName()));
|
||||
}
|
||||
else {
|
||||
Message_StringID(13, MUST_EQUIP_ITEM);
|
||||
@ -264,6 +267,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
Log(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click a race/class restricted effect on item %s (id: %d) which they shouldn't be able to click!",
|
||||
CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID);
|
||||
database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking race/class restricted item with an invalid class");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s: Clicking race/class restricted item with invalid class.", GetCleanName()));
|
||||
}
|
||||
else {
|
||||
if (CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::RoF)
|
||||
@ -284,6 +288,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
// They are attempting to cast a must equip clicky without having it equipped
|
||||
Log(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID);
|
||||
database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking equip-only item without equiping it");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s: Clicking equip-only item without equipping it.", GetCleanName()));
|
||||
}
|
||||
else {
|
||||
Message_StringID(13, MUST_EQUIP_ITEM);
|
||||
@ -2727,7 +2732,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
||||
}
|
||||
safe_delete(message_packet);
|
||||
safe_delete(packet);
|
||||
|
||||
nats.OnDamageEvent(cd->source, cd);
|
||||
}
|
||||
//we are done...
|
||||
return;
|
||||
@ -4047,7 +4052,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
);
|
||||
}
|
||||
safe_delete(action_packet);
|
||||
safe_delete(message_packet);
|
||||
safe_delete(message_packet);
|
||||
nats.OnDamageEvent(cd->source, cd);
|
||||
|
||||
Log(Logs::Detail, Logs::Spells, "Cast of %d by %s on %s complete successfully.", spell_id, GetName(), spelltar->GetName());
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include "client.h"
|
||||
#include "entity.h"
|
||||
#include "mob.h"
|
||||
|
||||
#include "nats_manager.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "string_ids.h"
|
||||
#include "worldserver.h"
|
||||
@ -34,6 +34,7 @@ class QueryServ;
|
||||
|
||||
extern WorldServer worldserver;
|
||||
extern QueryServ* QServ;
|
||||
extern NatsManager nats;
|
||||
|
||||
// The maximum amount of a single bazaar/barter transaction expressed in copper.
|
||||
// Equivalent to 2 Million plat
|
||||
@ -1658,6 +1659,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic
|
||||
|
||||
if(!TakeMoneyFromPP(TotalCost)) {
|
||||
database.SetHackerFlag(account_name, name, "Attempted to buy something in bazaar but did not have enough money.");
|
||||
nats.SendAdminMessage(StringFormat("Hacker %s: Attempted to buy something in bazaar but did not have enough money.", GetCleanName()));
|
||||
TradeRequestFailed(app);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
|
||||
@ -23,8 +23,10 @@
|
||||
#include "client.h"
|
||||
#include "entity.h"
|
||||
#include "mob.h"
|
||||
#include "nats_manager.h"
|
||||
#include "trap.h"
|
||||
|
||||
extern NatsManager nats;
|
||||
/*
|
||||
|
||||
Schema:
|
||||
@ -219,6 +221,7 @@ void Trap::Trigger(Mob* trigger)
|
||||
a->type = 253;
|
||||
trigger->CastToClient()->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
nats.OnDamageEvent(a->source, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -891,7 +891,7 @@ bool Zone::Init(bool iStaticZone) {
|
||||
}
|
||||
}
|
||||
|
||||
zone->zonemap = Map::LoadMapFile(zone->map_name);
|
||||
zone->zonemap = EQEmu::Map::LoadMapFile(zone->map_name);
|
||||
zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name);
|
||||
zone->pathing = PathManager::LoadPathFile(zone->map_name);
|
||||
|
||||
|
||||
@ -211,7 +211,7 @@ public:
|
||||
void ReloadWorld(uint32 Option);
|
||||
void ReloadMerchants();
|
||||
|
||||
Map* zonemap;
|
||||
EQEmu::Map* zonemap;
|
||||
WaterMap* watermap;
|
||||
PathManager *pathing;
|
||||
NewZone_Struct newzone_data;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user