Compare commits

..

2 Commits

Author SHA1 Message Date
fryguy b7eeb3b2f9 [LDoN] Update methods for removing wins/losses 2021-06-02 08:51:24 -04:00
Kinglykrab d2f8eead1f Add LDoN remove methods for losses and wins. 2021-06-01 20:57:03 -04:00
1302 changed files with 118222 additions and 196214 deletions
+2 -13
View File
@@ -7,21 +7,10 @@ name: EQEmulator Server Linux CI
concurrency:
limit: 1
volumes:
- name: cache
host:
path: /var/lib/cache
steps:
- name: server-build
# Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20
image: akkadius/eqemu-server:v11
image: akkadius/eqemu-server:latest
commands:
- sudo chown eqemu:eqemu /drone/src/ * -R
- sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R
- git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O0 -g -DNDEBUG" -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
- curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json
- ./bin/tests
volumes:
- name: cache
path: /home/eqemu/.ccache/
- git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_BOTS=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
-6
View File
@@ -54,9 +54,3 @@ bin/
/Win32
/x64
/client_files/**/CMakeFiles/
.idea
# Clangd Generated Files.
compile_flags.txt
.cache/
+19
View File
@@ -0,0 +1,19 @@
language: cpp
compiler: gcc
dist: bionic
addons:
apt:
packages:
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
- uuid-dev
- libssl-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
- make -j2
- ./bin/tests
-5
View File
@@ -1,5 +0,0 @@
{
"files.associations": {
"*.ipp": "cpp"
}
}
+11 -61
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
@@ -12,7 +12,7 @@ IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_CXX_STANDARD 20)
SET(CMAKE_CXX_STANDARD 14)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
@@ -20,8 +20,7 @@ IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-DNOMINMAX)
ADD_DEFINITIONS(-DCRASH_LOGGING)
ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
ELSE(MSVC)
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
@@ -122,6 +121,7 @@ ENDIF()
MESSAGE(STATUS "**************************************************")
#options
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
@@ -131,47 +131,6 @@ OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON)
OPTION(EQEMU_PREFER_LUA "Build with normal Lua even if LuaJIT is found." OFF)
#PRNG options
OPTION(EQEMU_ADDITIVE_LFIB_PRNG "Use Additive LFib for PRNG." OFF)
MARK_AS_ADVANCED(EQEMU_ADDITIVE_LFIB_PRNG)
OPTION(EQEMU_BIASED_INT_DIST "Use biased int dist instead of uniform." OFF)
MARK_AS_ADVANCED(EQEMU_BIASED_INT_DIST)
SET(EQEMU_CUSTOM_PRNG_ENGINE "" CACHE STRING "Custom random engine. (ex. std::default_random_engine)")
MARK_AS_ADVANCED(EQEMU_CUSTOM_PRNG_ENGINE)
IF(CMAKE_COMPILER_IS_GNUCXX)
OPTION(EQEMU_SFMT19937 "Use GCC's extention for SIMD Fast MT19937." OFF)
MARK_AS_ADVANCED(EQEMU_SFMT19937)
ENDIF()
IF(EQEMU_ADDITIVE_LFIB_PRNG)
ADD_DEFINITIONS(-DUSE_ADDITIVE_LFIB_PRNG)
IF(EQEMU_SFMT19937)
MESSAGE(STATUS "SFMT19937 and ADDITITVE_LFIB_PRNG both set, SFMT19937 ignored.")
SET(EQEMU_SFMT19937 OFF)
ENDIF()
IF(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "")
MESSAGE(STATUS "CUSTOM_PRNG_ENGINE and ADDITITVE_LFIB_PRNG both set, CUSTOM_PRNG_ENGINE ignored.")
SET(EQEMU_CUSTOM_PRNG_ENGINE "")
ENDIF()
ENDIF()
IF(EQEMU_SFMT19937)
ADD_DEFINITIONS(-DUSE_SFMT19937)
IF(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "")
MESSAGE(STATUS "CUSTOM_PRNG_ENGINE and SFMT19937 both set, CUSTOM_PRNG_ENGINE ignored.")
SET(EQEMU_CUSTOM_PRNG_ENGINE "")
ENDIF()
ENDIF()
IF(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "")
ADD_DEFINITIONS(-DUSE_CUSTOM_PRNG_ENGINE=${EQEMU_CUSTOM_PRNG_ENGINE})
ENDIF()
IF(EQEMU_BIASED_INT_DIST)
ADD_DEFINITIONS(-DBIASED_INT_DIST)
ENDIF()
IF(EQEMU_COMMANDS_LOGGING)
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
ENDIF(EQEMU_COMMANDS_LOGGING)
@@ -186,7 +145,7 @@ IF(MySQL_FOUND AND MariaDB_FOUND)
MySQL
MariaDB"
)
IF(DATABASE_LIBRARY_SELECTION STREQUAL "MySQL")
SET(DATABASE_LIBRARY_TYPE " MySQL")
SET(DATABASE_LIBRARY_LIBS ${MySQL_LIBRARIES})
@@ -217,16 +176,13 @@ IF(OpenSSL_FOUND AND MBEDTLS_FOUND)
OpenSSL
mbedTLS"
)
IF(TLS_LIBRARY_SELECTION STREQUAL "OpenSSL")
SET(TLS_LIBRARY_TYPE " OpenSSL")
SET(TLS_LIBRARY_ENABLED ON)
SET(TLS_LIBRARY_LIBS ${OPENSSL_LIBRARIES})
SET(TLS_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR})
ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL)
IF(${OPENSSL_VERSION} VERSION_GREATER_EQUAL "1.1.1")
ADD_DEFINITIONS(-DCPPHTTPLIB_OPENSSL_SUPPORT)
ENDIF()
ELSEIF(TLS_LIBRARY_SELECTION STREQUAL "mbedTLS")
SET(TLS_LIBRARY_TYPE " mbedTLS")
SET(TLS_LIBRARY_ENABLED ON)
@@ -242,9 +198,6 @@ ELSEIF(OpenSSL_FOUND)
SET(TLS_LIBRARY_LIBS ${OPENSSL_LIBRARIES})
SET(TLS_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR})
ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL)
IF(${OPENSSL_VERSION} VERSION_GREATER_EQUAL "1.1.1")
ADD_DEFINITIONS(-DCPPHTTPLIB_OPENSSL_SUPPORT)
ENDIF()
ELSEIF(MBEDTLS_FOUND)
SET(TLS_LIBRARY_TYPE " mbedTLS")
SET(TLS_LIBRARY_ENABLED ON)
@@ -340,9 +293,6 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
# silence obnoxious deprecation message
ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
OPTION(EQEMU_BUILD_LOGGING "Build Logging (To speed up compilation)" ON)
IF(EQEMU_BUILD_LOGGING)
ADD_DEFINITIONS(-DBUILD_LOGGING)
@@ -360,12 +310,12 @@ ENDIF()
IF(LUA_LIBRARY_ENABLED)
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
IF(EQEMU_BUILD_LUA)
ADD_DEFINITIONS(-DLUA_EQEMU)
SET(ZONE_LIBS ${LUA_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${LUA_LIBRARY_INCLUDE}")
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
IF(EQEMU_SANITIZE_LUA_LIBS)
ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS)
@@ -376,7 +326,7 @@ ENDIF()
IF(PERL_LIBRARY_ENABLED)
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
IF(EQEMU_BUILD_PERL)
SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS} perlbind)
SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
@@ -413,13 +363,13 @@ IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_H
ADD_SUBDIRECTORY(libs)
ADD_SUBDIRECTORY(submodules/fmt)
ADD_SUBDIRECTORY(submodules/libuv)
IF(EQEMU_BUILD_ZLIB)
SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API")
SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries")
ADD_SUBDIRECTORY(libs/zlibng)
ENDIF()
SET(RECASTNAVIGATION_DEMO OFF CACHE BOOL "Build demo")
SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests")
SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples")
+4 -4
View File
@@ -18,16 +18,16 @@
|**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)|
### > Windows
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-windows/)
* [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-windows)
### > Debian/Ubuntu/CentOS/Fedora
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-linux/)
* [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-linux)
* You can use curl or wget to kick off the installer (whichever your OS has)
> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
## Supported Clients
@@ -56,7 +56,7 @@ forum, although pull requests will be much quicker and easier on all parties.
## Resources
- [EQEmulator Forums](http://www.eqemulator.org/forums)
- [EQEmulator Wiki](https://docs.eqemu.io/)
- [EQEmulator Wiki](https://eqemu.gitbook.io/)
## Related Repositories
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
+1 -1
View File
@@ -3,7 +3,7 @@
############################################
#
# New changelog can be found here
# https://docs.eqemu.io/server/changelog/server
# https://eqemu.gitbook.io/changelog/
#
############################################
# Deprecated
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(export_sources
main.cpp
+7 -19
View File
@@ -25,15 +25,11 @@
#include "../../common/platform.h"
#include "../../common/crash.h"
#include "../../common/rulesys.h"
#include "../../common/strings.h"
#include "../../common/string_util.h"
#include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ExportSpells(SharedDatabase *db);
void ExportSkillCaps(SharedDatabase *db);
@@ -46,8 +42,6 @@ int main(int argc, char **argv)
LogSys.LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Export Utility");
if (!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file");
@@ -89,10 +83,8 @@ int main(int argc, char **argv)
content_db.SetMysql(database.getMySQL());
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
database.LoadLogSettings(LogSys.log_settings);
LogSys.StartFileLogs();
std::string arg_1;
@@ -131,8 +123,7 @@ void ExportSpells(SharedDatabase *db)
{
LogInfo("Exporting Spells");
std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
FILE *f = fopen("export/spells_us.txt", "w");
if (!f) {
LogError("Unable to open export/spells_us.txt to write, skipping.");
return;
@@ -214,8 +205,7 @@ void ExportSkillCaps(SharedDatabase *db)
{
LogInfo("Exporting Skill Caps");
std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
FILE *f = fopen("export/SkillCaps.txt", "w");
if (!f) {
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
return;
@@ -245,8 +235,7 @@ void ExportBaseData(SharedDatabase *db)
{
LogInfo("Exporting Base Data");
std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
FILE *f = fopen("export/BaseData.txt", "w");
if (!f) {
LogError("Unable to open export/BaseData.txt to write, skipping.");
return;
@@ -279,8 +268,7 @@ void ExportDBStrings(SharedDatabase *db)
{
LogInfo("Exporting DB Strings");
std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
FILE *f = fopen("export/dbstr_us.txt", "w");
if (!f) {
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
return;
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(import_sources
main.cpp
+17 -29
View File
@@ -23,15 +23,11 @@
#include "../../common/platform.h"
#include "../../common/crash.h"
#include "../../common/rulesys.h"
#include "../../common/strings.h"
#include "../../common/string_util.h"
#include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ImportSpells(SharedDatabase *db);
void ImportSkillCaps(SharedDatabase *db);
@@ -43,8 +39,6 @@ int main(int argc, char **argv) {
LogSys.LoadLogSettingsDefaults();
set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Import Utility");
if(!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file.");
@@ -86,10 +80,8 @@ int main(int argc, char **argv) {
content_db.SetMysql(database.getMySQL());
}
LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings()
->StartFileLogs();
database.LoadLogSettings(LogSys.log_settings);
LogSys.StartFileLogs();
ImportSpells(&content_db);
ImportSkillCaps(&content_db);
@@ -132,10 +124,9 @@ bool IsStringField(int i) {
void ImportSpells(SharedDatabase *db) {
LogInfo("Importing Spells");
std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
FILE *f = fopen("import/spells_us.txt", "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
LogError("Unable to open import/spells_us.txt to read, skipping.");
return;
}
@@ -154,8 +145,8 @@ void ImportSpells(SharedDatabase *db) {
}
}
std::string escaped = ::Strings::Escape(buffer);
auto split = Strings::Split(escaped, '^');
std::string escaped = ::EscapeString(buffer);
auto split = SplitString(escaped, '^');
int line_columns = (int)split.size();
std::string sql;
@@ -222,10 +213,9 @@ void ImportSpells(SharedDatabase *db) {
void ImportSkillCaps(SharedDatabase *db) {
LogInfo("Importing Skill Caps");
std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
FILE *f = fopen("import/SkillCaps.txt", "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
LogError("Unable to open import/SkillCaps.txt to read, skipping.");
return;
}
@@ -234,7 +224,7 @@ void ImportSkillCaps(SharedDatabase *db) {
char buffer[2048];
while(fgets(buffer, 2048, f)) {
auto split = Strings::Split(buffer, '^');
auto split = SplitString(buffer, '^');
if(split.size() < 4) {
continue;
@@ -258,10 +248,9 @@ void ImportSkillCaps(SharedDatabase *db) {
void ImportBaseData(SharedDatabase *db) {
LogInfo("Importing Base Data");
std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
FILE *f = fopen("import/BaseData.txt", "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
LogError("Unable to open import/BaseData.txt to read, skipping.");
return;
}
@@ -270,7 +259,7 @@ void ImportBaseData(SharedDatabase *db) {
char buffer[2048];
while(fgets(buffer, 2048, f)) {
auto split = Strings::Split(buffer, '^');
auto split = SplitString(buffer, '^');
if(split.size() < 10) {
continue;
@@ -304,10 +293,9 @@ void ImportBaseData(SharedDatabase *db) {
void ImportDBStrings(SharedDatabase *db) {
LogInfo("Importing DB Strings");
std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
FILE *f = fopen("import/dbstr_us.txt", "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
LogError("Unable to open import/dbstr_us.txt to read, skipping.");
return;
}
@@ -329,7 +317,7 @@ void ImportDBStrings(SharedDatabase *db) {
}
}
auto split = Strings::Split(buffer, '^');
auto split = SplitString(buffer, '^');
if(split.size() < 2) {
continue;
@@ -343,7 +331,7 @@ void ImportDBStrings(SharedDatabase *db) {
type = atoi(split[1].c_str());
if(split.size() >= 3) {
value = ::Strings::Escape(split[2]);
value = ::EscapeString(split[2]);
}
sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')",
+709 -748
View File
File diff suppressed because it is too large Load Diff
-147
View File
@@ -1,147 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2021 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include <cstdint>
#include <limits>
#include <type_traits>
#include <algorithm>
#include <iostream>
/*
* This is an additive lagged fibonacci generator as seen in The Art of Computer Programming, Vol. 2
* This should roughly match the implementation that EQ's client uses and be compatible with our Random class
*
* EQ's rand looks like it was from an example implementation that as posted on pscode.com
*
* You might also want to consider defining BIASED_INT_DIST as well to more closely match EQ
*/
namespace EQ {
template<typename UIntType, size_t w, size_t j, size_t k>
class additive_lagged_fibonacci_engine {
static_assert(std::is_unsigned<UIntType>::value, "result_type must be an unsigned integral type");
static_assert(0u < j && j < k, "0 < j < k");
static_assert(0u < w && w <= std::numeric_limits<UIntType>::digits,
"template argument substituting w out of bounds");
public:
using result_type = UIntType;
static constexpr size_t word_size = w;
static constexpr size_t short_lag = j;
static constexpr size_t long_lag = k;
static constexpr result_type default_seed = 19780503u; // default for subtract_with_carry_engine
additive_lagged_fibonacci_engine() : additive_lagged_fibonacci_engine(default_seed) {}
explicit additive_lagged_fibonacci_engine(result_type sd) { seed(sd); }
void seed(result_type seed = default_seed)
{
state1 = long_lag - long_lag;
state2 = long_lag - short_lag;
state[0] = static_cast<int>(seed) & ((1u << word_size) - 1);
state[1] = 1;
for (int i = 2; i < long_lag; ++i)
state[i] = (state[i - 1] + state[i - 2]) & ((1u << word_size) - 1);
return;
}
// TODO: seed via seed_seq
static constexpr result_type min() { return 0; }
static constexpr result_type max() { return ((1u << word_size) - 1) >> 6; }
void discard(unsigned long long z) {
for (; z != 0ULL; --z)
(*this)();
}
result_type operator()() {
result_type rand = (state[state1] + state[state2]) & ((1u << word_size) - 1);
state[state1] = rand;
if (++state1 == long_lag)
state1 = 0;
if (++state2 == long_lag)
state2 = 0;
return rand >> 6;
}
private:
result_type state1;
result_type state2;
result_type state[long_lag];
public:
template<typename UInt, size_t W, size_t J, size_t K>
friend bool operator==(const additive_lagged_fibonacci_engine<UInt, W, J, K> &x,
const additive_lagged_fibonacci_engine<UInt, W, J, K> &y)
{
return std::equal(x.state, x.state + long_lag, y.state) && x.state1 == y.state1 &&
x.state2 == y.state2;
}
template<typename UInt, size_t W, size_t J, size_t K>
friend bool operator!=(const additive_lagged_fibonacci_engine<UInt, W, J, K> &x,
const additive_lagged_fibonacci_engine<UInt, W, J, K> &y)
{ return !(x == y); }
template<typename UInt, size_t W, size_t J, size_t K, typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits> &
operator<<(std::basic_istream<CharT, Traits> &os, additive_lagged_fibonacci_engine<UInt, W, J, K> &x)
{
using ios_base = typename std::basic_istream<CharT, Traits>::ios_base;
const typename ios_base::fmtflags flags = os.flags();
const CharT fill = os.fill();
const CharT space = os.widen(' ');
os.flags(ios_base::dec | ios_base::fixed | ios_base::left);
os.fill(space);
for (size_t i = 0; i < long_lag; ++i)
os << x.state[i] << space;
os << x.state1 << space << x.state2;
os.flags(flags);
os.fill(fill);
return os;
}
template<typename UInt, size_t W, size_t J, size_t K, typename CharT, typename Traits>
friend std::basic_istream<CharT, Traits> &
operator>>(std::basic_istream<CharT, Traits> &is, additive_lagged_fibonacci_engine<UInt, W, J, K> &x)
{
using ios_base = typename std::basic_istream<CharT, Traits>::ios_base;
const typename ios_base::fmtflags flags = is.flags();
is.flags(ios_base::dec | ios_base::skipws);
for (size_t i = 0; i < long_lag; ++i)
is >> x.state[i];
is >> x.state1;
is >> x.state2;
is.flags(flags);
return is;
}
};
using EQRand = additive_lagged_fibonacci_engine<uint32_t, 30, 24, 55>;
};
+190
View File
@@ -0,0 +1,190 @@
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
// EQ::Any is a modified version of Boost::Any and as such retains the Boost licensing.
#ifndef EQEMU_COMMON_ANY_H
#define EQEMU_COMMON_ANY_H
#include <algorithm>
#include <typeinfo>
namespace EQ
{
class Any
{
public:
Any()
: content(nullptr)
{
}
template<typename ValueType>
Any(const ValueType &value)
: content(new Holder<ValueType>(value))
{
}
Any(const Any &other)
: content(other.content ? other.content->clone() : 0)
{
}
~Any()
{
if(content)
delete content;
}
Any& swap(Any &rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
Any& operator=(const ValueType &rhs)
{
Any(rhs).swap(*this);
return *this;
}
Any& operator=(Any rhs)
{
rhs.swap(*this);
return *this;
}
bool empty() const
{
return !content;
}
const std::type_info& type() const
{
return content ? content->type() : typeid(void);
}
class Placeholder
{
public:
virtual ~Placeholder()
{
}
virtual const std::type_info& type() const = 0;
virtual Placeholder* clone() const = 0;
};
template<typename ValueType>
class Holder : public Placeholder
{
public:
Holder(const ValueType &value)
: held(value)
{
}
virtual const std::type_info& type() const
{
return typeid(ValueType);
}
virtual Placeholder* clone() const
{
return new Holder(held);
}
ValueType held;
private:
Holder& operator=(const Holder&);
};
private:
template<typename ValueType>
friend ValueType* any_cast(Any*);
template<typename ValueType>
friend ValueType* unsafe_any_cast(Any*);
Placeholder* content;
};
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{
return "DBI::bad_any_cast: failed conversion using DBI::any_cast";
}
};
template<typename ValueType>
ValueType* any_cast(Any* operand)
{
return operand &&
operand->type() == typeid(ValueType) ? &static_cast<Any::Holder<ValueType>*>(operand->content)->held : nullptr;
}
template<typename ValueType>
inline const ValueType* any_cast(const Any* operand)
{
return any_cast<ValueType>(const_cast<Any*>(operand));
}
template<typename ValueType>
ValueType any_cast(Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
nonref* result = any_cast<nonref>(&operand);
if(!result)
throw bad_any_cast();
return *result;
}
template<typename ValueType>
inline ValueType any_cast(const Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
return any_cast<const nonref&>(const_cast<Any&>(operand));
}
template<typename ValueType>
inline ValueType* unsafe_any_cast(Any* operand)
{
return &static_cast<Any::Holder<ValueType>*>(operand->content)->held;
}
template<typename ValueType>
inline const ValueType* unsafe_any_cast(const Any* operand)
{
return unsafe_any_cast<ValueType>(const_cast<Any*>(operand));
}
}
#endif
+8 -8
View File
@@ -23,18 +23,18 @@
BasePacket::BasePacket(const unsigned char *buf, uint32 len)
{
pBuffer=nullptr;
size=0;
_wpos = 0;
_rpos = 0;
timestamp.tv_sec = 0;
this->pBuffer=nullptr;
this->size=0;
this->_wpos = 0;
this->_rpos = 0;
this->timestamp.tv_sec = 0;
if (len>0) {
size=len;
this->size=len;
pBuffer= new unsigned char[len];
if (buf) {
memcpy(pBuffer,buf,len);
memcpy(this->pBuffer,buf,len);
} else {
memset(pBuffer,0,len);
memset(this->pBuffer,0,len);
}
}
}
+8 -10
View File
@@ -27,17 +27,16 @@ typedef enum {
BT_Extraplanar = 6,
BT_Magical = 7, //this name might be a bit off,
BT_SummonedUndead = 8,
BT_RaidGiant = 9, //Velious era Raid Giant
BT_RaidColdain = 10, //Velious era Raid Coldain
BT_RaidGiant = 9,
// ...
BT_NoTarget = 11, //no name, can't target this bodytype
BT_Vampire = 12,
BT_Atenha_Ra = 13,
BT_Greater_Akheva = 14,
BT_Khati_Sha = 15,
BT_Seru = 16,
BT_Grieg_Veneficus = 17,
BT_Seru = 16, //not confirmed....
BT_Draz_Nurakk = 18,
BT_Zek = 19, //"creatures from the Plane of War."
BT_Zek = 19,
BT_Luggald = 20,
BT_Animal = 21,
BT_Insect = 22,
@@ -47,18 +46,17 @@ typedef enum {
BT_Dragon = 26,
BT_Summoned2 = 27,
BT_Summoned3 = 28,
BT_Dragon2 = 29, //database data indicates this is a dragon type (kunark and DoN?)
//29
BT_VeliousDragon = 30, //might not be a tight set
BT_Familiar = 31,
// ...
BT_Dragon3 = 32,
BT_Boxes = 33,
BT_Muramite = 34, //tribal dudes
// ...
BT_NoTarget2 = 60,
// ...
BT_SwarmPet = 63, //Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general.
BT_MonsterSummon = 64,
// 65, trap or effect related?
BT_SwarmPet = 63, //is this valid, or made up?
// ...
BT_InvisMan = 66, //no name, seen on 'InvisMan', can be /targeted
BT_Special = 67
} bodyType;
+5 -5
View File
@@ -380,12 +380,12 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Merchant";
case DISCORD_MERCHANT:
return "Discord Merchant";
case ADVENTURE_RECRUITER:
case ADVENTURERECRUITER:
return "Adventure Recruiter";
case ADVENTURE_MERCHANT:
case ADVENTUREMERCHANT:
return "Adventure Merchant";
case LDON_TREASURE:
return "LDoN Treasure";
case CORPSE_CLASS:
return "Corpse Class";
case TRIBUTE_MASTER:
return "Tribute Master";
case GUILD_TRIBUTE_MASTER:
@@ -400,7 +400,7 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Fellowship Master";
case ALT_CURRENCY_MERCHANT:
return "Alternate Currency Merchant";
case MERCENARY_MASTER:
case MERCERNARY_MASTER:
return "Mercenary Liaison";
default:
return "Unknown";
+5 -4
View File
@@ -55,9 +55,10 @@
#define BANKER 40
#define MERCHANT 41
#define DISCORD_MERCHANT 59
#define ADVENTURE_RECRUITER 60
#define ADVENTURE_MERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva
#define ADVENTURERECRUITER 60
#define ADVENTUREMERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs
#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far..
#define TRIBUTE_MASTER 63
#define GUILD_TRIBUTE_MASTER 64 // not sure
#define GUILD_BANKER 66
@@ -65,7 +66,7 @@
#define DARK_REIGN_MERCHANT 68
#define FELLOWSHIP_MASTER 69
#define ALT_CURRENCY_MERCHANT 70
#define MERCENARY_MASTER 71
#define MERCERNARY_MASTER 71
// player class values
+17 -138
View File
@@ -22,7 +22,6 @@
#include "../database.h"
#include "../rulesys.h"
#include "../eqemu_logsys.h"
#include "../loottable.h"
#include "../repositories/content_flags_repository.h"
@@ -36,12 +35,8 @@ int WorldContentService::GetCurrentExpansion() const
return current_expansion;
}
WorldContentService *WorldContentService::SetExpansionContext()
void WorldContentService::SetExpansionContext()
{
// do a rule manager reload until where we store expansion is changed to somewhere else
RuleManager::Instance()->LoadRules(GetDatabase(), "default", true);
// pull expansion from rules
int expansion = RuleI(Expansion, CurrentExpansion);
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
content_service.SetCurrentExpansion(expansion);
@@ -52,8 +47,6 @@ WorldContentService *WorldContentService::SetExpansionContext()
GetCurrentExpansion(),
GetCurrentExpansionName()
);
return this;
}
std::string WorldContentService::GetCurrentExpansionName()
@@ -80,47 +73,15 @@ void WorldContentService::SetCurrentExpansion(int current_expansion)
/**
* @return
*/
const std::vector<ContentFlagsRepository::ContentFlags> &WorldContentService::GetContentFlags() const
const std::vector<std::string> &WorldContentService::GetContentFlags() const
{
return content_flags;
}
/**
* @return
*/
std::vector<std::string> WorldContentService::GetContentFlagsEnabled()
{
std::vector<std::string> enabled_flags;
for (auto &f: GetContentFlags()) {
if (f.enabled) {
enabled_flags.emplace_back(f.flag_name);
}
}
return enabled_flags;
}
/**
* @return
*/
std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
{
std::vector<std::string> disabled_flags;
for (auto &f: GetContentFlags()) {
if (!f.enabled) {
disabled_flags.emplace_back(f.flag_name);
}
}
return disabled_flags;
}
/**
* @param content_flags
*/
void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags)
void WorldContentService::SetContentFlags(std::vector<std::string> content_flags)
{
WorldContentService::content_flags = content_flags;
}
@@ -129,10 +90,10 @@ void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::Co
* @param content_flag
* @return
*/
bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag)
{
for (auto &f: GetContentFlags()) {
if (f.flag_name == content_flag && f.enabled == true) {
for (auto &flag : GetContentFlags()) {
if (flag == content_flag) {
return true;
}
}
@@ -140,102 +101,20 @@ bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
return false;
}
/**
* @param content_flag
* @return
*/
bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
void WorldContentService::ReloadContentFlags(Database &db)
{
for (auto &f: GetContentFlags()) {
if (f.flag_name == content_flag && f.enabled == false) {
return true;
}
std::vector<std::string> set_content_flags;
auto content_flags = ContentFlagsRepository::GetWhere(db, "enabled = 1");
set_content_flags.reserve(content_flags.size());
for (auto &flags: content_flags) {
set_content_flags.push_back(flags.flag_name);
}
return false;
}
bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f)
{
// if we're not set to (-1 All) then fail when we aren't within minimum expansion
if (f.min_expansion > Expansion::EXPANSION_ALL && current_expansion < f.min_expansion && current_expansion != -1) {
return false;
}
// if we're not set to (-1 All) then fail when we aren't within max expansion
if (f.max_expansion > Expansion::EXPANSION_ALL && current_expansion > f.max_expansion && current_expansion != -1) {
return false;
}
// if we don't have any enabled flag in enabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags)) {
if (!Strings::Contains(GetContentFlagsEnabled(), flag)) {
return false;
}
}
// if we don't have any disabled flag in disabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags_disabled)) {
if (!Strings::Contains(GetContentFlagsDisabled(), flag)) {
return false;
}
}
return true;
}
void WorldContentService::ReloadContentFlags()
{
std::vector<ContentFlagsRepository::ContentFlags> set_content_flags;
auto flags = ContentFlagsRepository::All(*GetDatabase());
set_content_flags.reserve(flags.size());
for (auto &f: flags) {
set_content_flags.push_back(f);
LogInfo(
"Loaded content flag [{}] [{}]",
f.flag_name,
(f.enabled ? "Enabled" : "Disabled")
);
}
LogInfo(
"Enabled content flags [{}]",
implode(", ", set_content_flags)
);
SetContentFlags(set_content_flags);
}
Database *WorldContentService::GetDatabase() const
{
return m_database;
}
WorldContentService *WorldContentService::SetDatabase(Database *database)
{
WorldContentService::m_database = database;
return this;
}
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
{
auto flags = ContentFlagsRepository::GetWhere(
*GetDatabase(),
fmt::format("flag_name = '{}'", content_flag_name)
);
auto f = ContentFlagsRepository::NewEntity();
if (!flags.empty()) {
f = flags.front();
}
f.enabled = enabled ? 1 : 0;
f.flag_name = content_flag_name;
if (!flags.empty()) {
ContentFlagsRepository::UpdateOne(*GetDatabase(), f);
}
else {
ContentFlagsRepository::InsertOne(*GetDatabase(), f);
}
ReloadContentFlags();
}
+10 -25
View File
@@ -23,8 +23,6 @@
#include <string>
#include <vector>
#include "../loottable.h"
#include "../repositories/content_flags_repository.h"
class Database;
@@ -54,7 +52,7 @@ namespace Expansion {
VeilOfAlaris,
RainOfFear,
CallOfTheForsaken,
TheDarkenedSea,
TheDarkendSea,
TheBrokenMirror,
EmpiresOfKunark,
RingOfScale,
@@ -127,7 +125,7 @@ public:
bool IsVeilOfAlarisEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::VeilOfAlaris || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsRainOfFearEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RainOfFear || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsCallOfTheForsakenEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::CallOfTheForsaken || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheDarkenedSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheDarkenedSea || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheDarkendSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheDarkendSea || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheBrokenMirrorEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBrokenMirror || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsEmpiresOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::EmpiresOfKunark || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsRingOfScaleEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RingOfScale || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
@@ -155,35 +153,22 @@ public:
bool IsCurrentExpansionVeilOfAlaris() { return current_expansion == Expansion::ExpansionNumber::VeilOfAlaris; }
bool IsCurrentExpansionRainOfFear() { return current_expansion == Expansion::ExpansionNumber::RainOfFear; }
bool IsCurrentExpansionCallOfTheForsaken() { return current_expansion == Expansion::ExpansionNumber::CallOfTheForsaken; }
bool IsCurrentExpansionTheDarkenedSea() { return current_expansion == Expansion::ExpansionNumber::TheDarkenedSea; }
bool IsCurrentExpansionTheDarkendSea() { return current_expansion == Expansion::ExpansionNumber::TheDarkendSea; }
bool IsCurrentExpansionTheBrokenMirror() { return current_expansion == Expansion::ExpansionNumber::TheBrokenMirror; }
bool IsCurrentExpansionEmpiresOfKunark() { return current_expansion == Expansion::ExpansionNumber::EmpiresOfKunark; }
bool IsCurrentExpansionRingOfScale() { return current_expansion == Expansion::ExpansionNumber::RingOfScale; }
bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; }
bool IsCurrentExpansionTormentOfVelious() { return current_expansion == Expansion::ExpansionNumber::TormentOfVelious; }
const std::vector<ContentFlagsRepository::ContentFlags> &GetContentFlags() const;
std::vector<std::string> GetContentFlagsEnabled();
std::vector<std::string> GetContentFlagsDisabled();
bool IsContentFlagEnabled(const std::string& content_flag);
bool IsContentFlagDisabled(const std::string& content_flag);
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
void ReloadContentFlags();
WorldContentService * SetExpansionContext();
bool DoesPassContentFiltering(const ContentFlags& f);
WorldContentService * SetDatabase(Database *database);
Database *GetDatabase() const;
void SetContentFlag(const std::string &content_flag_name, bool enabled);
private:
int current_expansion{};
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
// reference to database
Database *m_database;
std::vector<std::string> content_flags;
public:
const std::vector<std::string> &GetContentFlags() const;
bool IsContentFlagEnabled(const std::string& content_flag);
void SetContentFlags(std::vector<std::string> content_flags);
void ReloadContentFlags(Database &db);
void SetExpansionContext();
};
extern WorldContentService content_service;
+4 -30
View File
@@ -1,15 +1,6 @@
#include "global_define.h"
#include "eqemu_logsys.h"
#include "crash.h"
#include "strings.h"
#include "process/process.h"
#include <cstdio>
#if WINDOWS
#define popen _popen
#endif
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
#include "StackWalker.h"
@@ -134,27 +125,9 @@ void set_exception_handler() {
void print_trace()
{
bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU");
if (!does_gdb_exist) {
LogCrash(
"[Error] GDB is not installed, if you want crash dumps on Linux to work properly you will need GDB installed"
);
std::exit(1);
}
auto uid = geteuid();
auto uid = geteuid();
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
// check for passwordless sudo if not root
if (uid != 0) {
bool sudo_password_required = Strings::Contains(Process::execute("sudo -n true"), "a password is required");
if (sudo_password_required) {
LogCrash(
"[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root."
);
std::exit(1);
}
}
std::string temp_output_file = "/tmp/dump-output";
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
@@ -163,6 +136,7 @@ void print_trace()
int child_pid = fork();
if (!child_pid) {
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
dup2(fd, 1); // redirect output to stderr
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
if (uid == 0) {
@@ -177,7 +151,7 @@ void print_trace()
abort(); /* If gdb failed to start */
}
else {
waitpid(child_pid, nullptr, 0);
waitpid(child_pid, NULL, 0);
}
std::ifstream input(temp_output_file);
+463 -391
View File
File diff suppressed because it is too large Load Diff
+35 -35
View File
@@ -78,7 +78,6 @@ class PTimerList;
#define SQL(...) #__VA_ARGS__
class LogSettings;
class Database : public DBcore {
public:
Database();
@@ -88,6 +87,7 @@ public:
/* Character Creation */
bool AddToNameFilter(const char *name);
bool CreateCharacter(
uint32 account_id,
char *name,
@@ -113,25 +113,25 @@ public:
bool SetMQDetectionFlag(const char *accountname, const char *charactername, const std::string &hacked, const char *zone);
bool UpdateName(const char *oldname, const char *newname);
bool CopyCharacter(
const std::string& source_character_name,
const std::string& destination_character_name,
const std::string& destination_account_name
std::string source_character_name,
std::string destination_character_name,
std::string destination_account_name
);
/* General Information Queries */
bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(std::string name);
bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table.
bool CheckGMIPs(std::string login_ip, uint32 account_id);
bool CheckNameFilter(std::string name, bool surname = false);
bool CheckUsedName(std::string name);
bool AddBannedIP(char* bannedIP, const char* notes); //Add IP address to the banned_ips table.
bool AddGMIP(char* ip_address, char* name);
bool CheckBannedIPs(const char* loginIP); //Check incoming connection against banned IP table.
bool CheckGMIPs(const char* loginIP, uint32 account_id);
bool CheckNameFilter(const char* name, bool surname = false);
bool CheckUsedName(const char* name);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetAccountIDByName(const char* accname, const char *loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id);
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
uint32 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id);
uint32 GetRaidIDByCharID(uint32 char_id);
@@ -140,41 +140,41 @@ public:
void GetCharName(uint32 char_id, char* name);
std::string GetCharNameByID(uint32 char_id);
std::string GetNPCNameByID(uint32 npc_id);
std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 account_id, std::string login_ip);
void LoginIP(uint32 AccountID, const char* LoginIP);
/* Instancing */
bool AddClientToInstance(uint16 instance_id, uint32 character_id);
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id);
bool AddClientToInstance(uint16 instance_id, uint32 char_id);
bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id);
bool CheckInstanceExists(uint16 instance_id);
bool CheckInstanceExpired(uint16 instance_id);
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
bool GetUnusedInstanceID(uint16 &instance_id);
bool IsGlobalInstance(uint16 instance_id);
bool GlobalInstance(uint16 instance_id);
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
bool RemoveClientsFromInstance(uint16 instance_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id);
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id);
uint8_t GetInstanceVersion(uint16 instance_id);
uint16 GetInstanceVersion(uint16 instance_id);
uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma);
uint32 GetInstanceZoneID(uint16 instance_id);
uint32 VersionFromInstanceID(uint16 instance_id);
uint32 ZoneIDFromInstanceID(uint16 instance_id);
void AssignGroupToInstance(uint32 gid, uint32 instance_id);
void AssignRaidToInstance(uint32 rid, uint32 instance_id);
void BuryCorpsesInInstance(uint16 instance_id);
void DeleteInstance(uint16 instance_id);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids);
void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid);
void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list);
void PurgeExpiredInstances();
void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
/* Adventure related. */
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win = false, bool remove = false);
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win, bool remove = false);
bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
/* Account Related */
@@ -188,8 +188,6 @@ public:
int16 CheckStatus(uint32 account_id);
void SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum);
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
@@ -198,16 +196,15 @@ public:
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 acctid);
int GetIPExemption(std::string account_ip);
void SetIPExemption(std::string account_ip, int exemption_amount);
int GetIPExemption(std::string account_ip);
int GetInstanceID(uint32 char_id, uint32 zone_id);
/* Groups */
std::string GetGroupLeaderForLogin(std::string character_name);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
char* GetGroupLeaderForLogin(const char* name,char* leaderbuf);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
uint32 GetGroupID(const char* name);
@@ -245,11 +242,14 @@ public:
/* General Queries */
bool GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, float* safe_heading = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr);
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0);
bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0);
bool LoadPTimers(uint32 charid, PTimerList &into);
uint8 GetPEQZone(uint32 zone_id, uint32 version);
uint8 GetMinStatus(uint32 zone_id, uint32 instance_version);
uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version);
uint8 GetPEQZone(uint32 zoneID, uint32 version);
uint8 GetRaceSkill(uint8 skillid, uint8 in_race);
uint8 GetServerType();
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
@@ -267,8 +267,8 @@ public:
int CountInvSnapshots();
void ClearInvSnapshots(bool from_now = false);
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
/* EQEmuLogSys */
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
private:
+51 -50
View File
@@ -23,11 +23,10 @@
#include <iterator>
#include "database_dump_service.h"
#include "../eqemu_logsys.h"
#include "../strings.h"
#include "../string_util.h"
#include "../eqemu_config.h"
#include "../database_schema.h"
#include "../file.h"
#include "../process/process.h"
#include "../file_util.h"
#include <ctime>
@@ -41,6 +40,38 @@
#define DATABASE_DUMP_PATH "backups/"
/**
* @param cmd
* @param return_result
* @return
*/
std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true)
{
const char *file_name = "db-exec-result.txt";
if (return_result) {
#ifdef _WINDOWS
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#else
std::system((cmd + " > " + file_name).c_str());
#endif
}
else {
std::system((cmd).c_str());
}
std::string result;
if (return_result) {
std::ifstream file(file_name);
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
std::remove(file_name);
}
return result;
}
/**
* @return bool
*/
@@ -57,7 +88,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
*/
bool DatabaseDumpService::IsTarAvailable()
{
std::string version_output = Process::execute("tar --version");
std::string version_output = execute("tar --version");
return version_output.find("GNU tar") != std::string::npos;
}
@@ -68,7 +99,7 @@ bool DatabaseDumpService::IsTarAvailable()
*/
bool DatabaseDumpService::Is7ZipAvailable()
{
std::string version_output = Process::execute("7z --help");
std::string version_output = execute("7z --help");
return version_output.find("7-Zip") != std::string::npos;
}
@@ -86,9 +117,9 @@ bool DatabaseDumpService::HasCompressionBinary()
*/
std::string DatabaseDumpService::GetMySQLVersion()
{
std::string version_output = Process::execute("mysql --version");
std::string version_output = execute("mysql --version");
return Strings::Trim(version_output);
return trim(version_output);
}
/**
@@ -129,21 +160,7 @@ std::string DatabaseDumpService::GetPlayerTablesList()
tables_list += table + " ";
}
return Strings::Trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetBotTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetBotTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return trim(tables_list);
}
/**
@@ -157,7 +174,7 @@ std::string DatabaseDumpService::GetLoginTableList()
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return trim(tables_list);
}
/**
@@ -171,7 +188,7 @@ std::string DatabaseDumpService::GetQueryServTables()
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return trim(tables_list);
}
/**
@@ -191,7 +208,7 @@ std::string DatabaseDumpService::GetSystemTablesList()
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return trim(tables_list);
}
/**
* @return
@@ -205,7 +222,7 @@ std::string DatabaseDumpService::GetStateTablesList()
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return trim(tables_list);
}
/**
@@ -220,7 +237,7 @@ std::string DatabaseDumpService::GetContentTablesList()
tables_list += table + " ";
}
return Strings::Trim(tables_list);
return trim(tables_list);
}
/**
@@ -301,11 +318,6 @@ void DatabaseDumpService::Dump()
dump_descriptor += "-player";
}
if (IsDumpBotTables()) {
tables_to_dump += GetBotTablesList() + " ";
dump_descriptor += "-bots";
}
if (IsDumpSystemTables()) {
tables_to_dump += GetSystemTablesList() + " ";
dump_descriptor += "-system";
@@ -352,12 +364,12 @@ void DatabaseDumpService::Dump()
pipe_file
);
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
File::Makedir(GetSetDumpPath());
if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
FileUtil::mkdir(GetSetDumpPath());
}
if (IsDumpDropTableSyntaxOnly()) {
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' ');
std::vector<std::string> tables = SplitString(tables_to_dump, ' ');
for (auto &table : tables) {
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
@@ -368,8 +380,8 @@ void DatabaseDumpService::Dump()
}
}
else {
std::string execution_result = Process::execute(execute_command);
if (!execution_result.empty() && IsDumpOutputToConsole()) {
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
if (!execution_result.empty()) {
std::cout << execution_result;
}
}
@@ -385,7 +397,7 @@ void DatabaseDumpService::Dump()
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
if (IsTarAvailable()) {
Process::execute(
execute(
fmt::format(
"tar -zcvf {}.tar.gz -C {} {}.sql",
GetDumpFileNameWithPath(),
@@ -396,7 +408,7 @@ void DatabaseDumpService::Dump()
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
}
else if (Is7ZipAvailable()) {
Process::execute(
execute(
fmt::format(
"7z a -t7z {}.zip {}.sql",
GetDumpFileNameWithPath(),
@@ -424,7 +436,6 @@ void DatabaseDumpService::Dump()
// LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false"));
// LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false"));
// LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false"));
// LogDebug("[{}] bot", (IsDumpBotTables() ? "true" : "false"));
}
bool DatabaseDumpService::IsDumpSystemTables() const
@@ -566,13 +577,3 @@ void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables)
{
DatabaseDumpService::dump_state_tables = dump_state_tables;
}
bool DatabaseDumpService::IsDumpBotTables() const
{
return dump_bot_tables;
}
void DatabaseDumpService::SetDumpBotTables(bool dump_bot_tables)
{
DatabaseDumpService::dump_bot_tables = dump_bot_tables;
}
+1 -4
View File
@@ -53,8 +53,6 @@ public:
void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only);
bool IsDumpStateTables() const;
void SetDumpStateTables(bool dump_state_tables);
bool IsDumpBotTables() const;
void SetDumpBotTables(bool dump_bot_tables);
private:
bool dump_all_tables = false;
@@ -69,15 +67,14 @@ private:
bool dump_with_compression = false;
bool dump_output_to_console = false;
bool dump_drop_table_syntax_only = false;
bool dump_bot_tables = false;
std::string dump_path;
std::string dump_file_name;
std::string execute(const std::string &cmd, bool return_result);
bool IsMySQLInstalled();
std::string GetMySQLVersion();
std::string GetBaseMySQLDumpCommand();
std::string GetPlayerTablesList();
std::string GetBotTablesList();
std::string GetSystemTablesList();
std::string GetStateTablesList();
std::string GetContentTablesList();
+97 -100
View File
@@ -18,12 +18,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h"
#include "../common/rulesys.h"
#include "../common/strings.h"
#include "../common/string_util.h"
#include "../common/timer.h"
#include "database.h"
#include "extprofile.h"
#include "path_manager.h"
#include <iomanip>
#include <iostream>
@@ -477,9 +476,7 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertCorpseDeblob();
/* Run EQEmu Server script (Checks for database updates) */
const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath());
system(fmt::format("perl {} ran_from_world", file).c_str());
if(system("perl eqemu_server.pl ran_from_world"));
return true;
}
@@ -964,7 +961,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)"
"VALUES (%u, '%s')",
character_id,
Strings::Escape(inspectmessage).c_str()
EscapeString(inspectmessage).c_str()
);
auto results = QueryDatabase(rquery);
}
@@ -1100,95 +1097,95 @@ bool Database::CheckDatabaseConvertPPDeblob(){
"e_expended_aa_spent"
")"
"VALUES ("
"%u," // id
"%u," // account_id
"'%s'," // `name`
"'%s'," // last_name
"%u," // gender
"%u," // race
"%u," // class
"%u," // `level`
"%u," // deity
"%u," // birthday
"%u," // last_login
"%u," // time_played
"%u," // pvp_status
"%u," // level2
"%u," // anon
"%u," // gm
"%u," // intoxication
"%u," // hair_color
"%u," // beard_color
"%u," // eye_color_1
"%u," // eye_color_2
"%u," // hair_style
"%u," // beard
"%u," // ability_time_seconds
"%u," // ability_number
"%u," // ability_time_minutes
"%u," // ability_time_hours
"'%s'," // title
"'%s'," // suffix
"%u," // exp
"%u," // points
"%u," // mana
"%u," // cur_hp
"%u," // str
"%u," // sta
"%u," // cha
"%u," // dex
"%u," // `int`
"%u," // agi
"%u," // wis
"%u," // face
"%f," // y
"%f," // x
"%f," // z
"%f," // heading
"%u," // pvp2
"%u," // pvp_type
"%u," // autosplit_enabled
"%u," // zone_change_count
"%u," // drakkin_heritage
"%u," // drakkin_tattoo
"%u," // drakkin_details
"%i," // toxicity
"%u," // hunger_level
"%u," // thirst_level
"%u," // ability_up
"%u," // zone_id
"%u," // zone_instance
"%u," // leadership_exp_on
"%u," // ldon_points_guk
"%u," // ldon_points_mir
"%u," // ldon_points_mmc
"%u," // ldon_points_ruj
"%u," // ldon_points_tak
"%u," // ldon_points_available
"%u," // tribute_time_remaining
"%u," // show_helm
"%u," // career_tribute_points
"%u," // tribute_points
"%u," // tribute_active
"%u," // endurance
"%u," // group_leadership_exp
"%u," // raid_leadership_exp
"%u," // group_leadership_points
"%u," // raid_leadership_points
"%u," // air_remaining
"%u," // pvp_kills
"%u," // pvp_deaths
"%u," // pvp_current_points
"%u," // pvp_career_points
"%u," // pvp_best_kill_streak
"%u," // pvp_worst_death_streak
"%u," // pvp_current_kill_streak
"%u," // aa_points_spent
"%u," // aa_exp
"%u," // aa_points
"%u," // group_auto_consent
"%u," // raid_auto_consent
"%u," // guild_auto_consent
"%u," // id
"%u," // account_id
"'%s'," // `name`
"'%s'," // last_name
"%u," // gender
"%u," // race
"%u," // class
"%u," // `level`
"%u," // deity
"%u," // birthday
"%u," // last_login
"%u," // time_played
"%u," // pvp_status
"%u," // level2
"%u," // anon
"%u," // gm
"%u," // intoxication
"%u," // hair_color
"%u," // beard_color
"%u," // eye_color_1
"%u," // eye_color_2
"%u," // hair_style
"%u," // beard
"%u," // ability_time_seconds
"%u," // ability_number
"%u," // ability_time_minutes
"%u," // ability_time_hours
"'%s'," // title
"'%s'," // suffix
"%u," // exp
"%u," // points
"%u," // mana
"%u," // cur_hp
"%u," // str
"%u," // sta
"%u," // cha
"%u," // dex
"%u," // `int`
"%u," // agi
"%u," // wis
"%u," // face
"%f," // y
"%f," // x
"%f," // z
"%f," // heading
"%u," // pvp2
"%u," // pvp_type
"%u," // autosplit_enabled
"%u," // zone_change_count
"%u," // drakkin_heritage
"%u," // drakkin_tattoo
"%u," // drakkin_details
"%i," // toxicity
"%u," // hunger_level
"%u," // thirst_level
"%u," // ability_up
"%u," // zone_id
"%u," // zone_instance
"%u," // leadership_exp_on
"%u," // ldon_points_guk
"%u," // ldon_points_mir
"%u," // ldon_points_mmc
"%u," // ldon_points_ruj
"%u," // ldon_points_tak
"%u," // ldon_points_available
"%u," // tribute_time_remaining
"%u," // show_helm
"%u," // career_tribute_points
"%u," // tribute_points
"%u," // tribute_active
"%u," // endurance
"%u," // group_leadership_exp
"%u," // raid_leadership_exp
"%u," // group_leadership_points
"%u," // raid_leadership_points
"%u," // air_remaining
"%u," // pvp_kills
"%u," // pvp_deaths
"%u," // pvp_current_points
"%u," // pvp_career_points
"%u," // pvp_best_kill_streak
"%u," // pvp_worst_death_streak
"%u," // pvp_current_kill_streak
"%u," // aa_points_spent
"%u," // aa_exp
"%u," // aa_points
"%u," // group_auto_consent
"%u," // raid_auto_consent
"%u," // guild_auto_consent
"%u," // RestTimer
"%u," // First Logon - References online status for EVENT_CONNECT/EVENT_DISCONNECt
"%u," // Looking for Group
@@ -1201,8 +1198,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
")",
character_id,
account_id,
Strings::Escape(pp->name).c_str(),
Strings::Escape(pp->last_name).c_str(),
EscapeString(pp->name).c_str(),
EscapeString(pp->last_name).c_str(),
pp->gender,
pp->race,
pp->class_,
@@ -1226,8 +1223,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
pp->ability_number,
pp->ability_time_minutes,
pp->ability_time_hours,
Strings::Escape(pp->title).c_str(),
Strings::Escape(pp->suffix).c_str(),
EscapeString(pp->title).c_str(),
EscapeString(pp->suffix).c_str(),
pp->exp,
pp->points,
pp->mana,
@@ -1455,7 +1452,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){
if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){
if (first_entry != 1){
rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
first_entry = 1;
}
rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
+313 -252
View File
@@ -18,18 +18,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h"
#include "../common/rulesys.h"
#include "../common/strings.h"
#include "../common/string_util.h"
#include "../common/timer.h"
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/dynamic_zone_members_repository.h"
#include "../common/repositories/dynamic_zones_repository.h"
#include "../common/repositories/group_id_repository.h"
#include "../common/repositories/instance_list_repository.h"
#include "../common/repositories/instance_list_player_repository.h"
#include "../common/repositories/raid_members_repository.h"
#include "../common/repositories/respawn_times_repository.h"
#include "../common/repositories/spawn_condition_values_repository.h"
#include "database.h"
@@ -49,83 +41,115 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/time.h>
#endif
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id)
/**
* @param instance_id
* @param char_id
* @return
*/
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
{
auto e = InstanceListPlayerRepository::NewEntity();
std::string query = StringFormat(
"REPLACE INTO `instance_list_player` (id, charid) "
"VALUES "
"(%lu, %lu)",
(unsigned long) instance_id,
(unsigned long) char_id
);
e.id = instance_id;
e.charid = character_id;
auto results = QueryDatabase(query);
return InstanceListPlayerRepository::ReplaceOne(*this, e);
return results.Success();
}
bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id)
bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id)
{
if (!instance_id) {
return false;
}
auto l = InstanceListPlayerRepository::GetWhere(
*this,
fmt::format(
"id = {} AND charid = {}",
instance_id,
character_id
)
);
if (l.empty()) {
std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() != 1)
return false;
}
return true;
}
bool Database::CheckInstanceExists(uint16 instance_id)
{
if (!instance_id) {
return false;
}
bool Database::CheckInstanceExists(uint16 instance_id) {
std::string query = StringFormat(
"SELECT "
"`id` "
"FROM "
"`instance_list` "
"WHERE "
"`id` = %u",
instance_id
);
auto results = QueryDatabase(query);
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
if (!results.Success())
return false;
if (results.RowCount() == 0)
return false;
}
return true;
}
bool Database::CheckInstanceExpired(uint16 instance_id)
{
if (!instance_id) {
int32 start_time = 0;
int32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat(
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
instance_id
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return true;
}
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
if (results.RowCount() == 0) {
return true;
}
if (i.never_expires) {
auto row = results.begin();
start_time = atoi(row[0]);
duration = atoi(row[1]);
never_expires = atoi(row[2]);
if (never_expires == 1) {
return false;
}
timeval tv{};
gettimeofday(&tv, nullptr);
return (i.start_time + i.duration) <= tv.tv_sec;
return (start_time + duration) <= tv.tv_sec;
}
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
{
auto e = InstanceListRepository::NewEntity();
std::string query = StringFormat(
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
instance_id,
zone_id,
version,
duration
);
e.id = instance_id;
e.zone = zone_id;
e.version = version;
e.start_time = std::time(nullptr);
e.duration = duration;
auto results = QueryDatabase(query);
return InstanceListRepository::InsertOne(*this, e).id;
return results.Success();
}
bool Database::GetUnusedInstanceID(uint16 &instance_id)
@@ -133,8 +157,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max = 32000;
auto query = fmt::format(
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}",
std::string query = StringFormat(
"SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
max_reserved_instance_id,
max_reserved_instance_id
);
@@ -178,7 +202,7 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true;
}
query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id);
query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id);
results = QueryDatabase(query);
if (!results.Success()) {
@@ -192,9 +216,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
}
max_reserved_instance_id++;
for (auto row : results) {
if (max_reserved_instance_id < std::stoul(row[0])) {
for (auto row = results.begin(); row != results.end(); ++row) {
if (max_reserved_instance_id < atoi(row[0])) {
instance_id = max_reserved_instance_id;
return true;
}
@@ -212,45 +235,57 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true;
}
bool Database::IsGlobalInstance(uint16 instance_id)
bool Database::GlobalInstance(uint16 instance_id)
{
if (!instance_id) {
return false;
}
std::string query = StringFormat(
"SELECT "
"is_global "
"FROM "
"instance_list "
"WHERE "
"id = %u "
"LIMIT 1 ",
instance_id
);
auto results = QueryDatabase(query);
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
if (!results.Success())
return false;
}
return i.is_global;
if (results.RowCount() == 0)
return false;
auto row = results.begin();
return (atoi(row[0]) == 1) ? true : false;
}
bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id)
{
return InstanceListPlayerRepository::DeleteWhere(
*this,
fmt::format(
"id = {} AND charid = {}",
instance_id,
char_id
)
);
std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu",
(unsigned long)instance_id, (unsigned long)char_id);
auto results = QueryDatabase(query);
return results.Success();
}
bool Database::RemoveClientsFromInstance(uint16 instance_id)
{
return InstanceListPlayerRepository::DeleteOne(*this, instance_id);
std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id);
auto results = QueryDatabase(query);
return results.Success();
}
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id)
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id)
{
//we are not saved to this instance so set our instance to 0
if (!IsGlobalInstance(instance_id) && !CheckInstanceByCharID(instance_id, character_id)) {
if (!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id))
return false;
}
if (CheckInstanceExpired(instance_id)) {
if (CheckInstanceExpired(instance_id))
{
DeleteInstance(instance_id);
return false;
}
@@ -260,102 +295,99 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id)
bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id)
{
auto l = InstanceListRepository::GetWhere(
*this,
fmt::format(
"id = {} AND zone = {}",
instance_id,
zone_id
)
);
if (l.empty()) {
std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u", instance_id, zone_id);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() == 0)
return false;
}
return true;
}
uint16 Database::GetInstanceID(uint32 zone_id, uint32 character_id, int16 version)
uint16 Database::GetInstanceID(uint32 zone, uint32 character_id, int16 version)
{
if (!zone_id) {
if (!zone)
return 0;
std::string query = StringFormat(
"SELECT "
"instance_list.id "
"FROM "
"instance_list, "
"instance_list_player "
"WHERE "
"instance_list.zone = %u "
"AND instance_list.version = %u "
"AND instance_list.id = instance_list_player.id "
"AND instance_list_player.charid = %u "
"LIMIT 1; ",
zone,
version,
character_id
);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint16 Database::GetInstanceVersion(uint16 instance_id) {
if (instance_id == 0)
return 0;
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
{
uint32 start_time = 0;
uint32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
{
is_perma = false;
return 0;
}
const auto query = fmt::format(
"SELECT instance_list.id FROM "
"instance_list, instance_list_player WHERE "
"instance_list.zone = {} AND "
"instance_list.version = {} AND "
"instance_list.id = instance_list_player.id AND "
"instance_list_player.charid = {} "
"LIMIT 1;",
zone_id,
version,
character_id
);
auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
if (results.RowCount() == 0)
{
is_perma = false;
return 0;
}
auto row = results.begin();
return static_cast<uint16>(std::stoul(row[0]));
}
start_time = atoi(row[0]);
duration = atoi(row[1]);
never_expires = atoi(row[2]);
std::vector<uint16> Database::GetInstanceIDs(uint32 zone_id, uint32 character_id)
{
std::vector<uint16> l;
if (!zone_id) {
return l;
}
const auto query = fmt::format(
"SELECT instance_list.id FROM "
"instance_list, instance_list_player WHERE "
"instance_list.zone = {} AND "
"instance_list.id = instance_list_player.id AND "
"instance_list_player.charid = {}",
zone_id,
character_id
);
auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
return l;
}
for (auto row : results) {
l.push_back(static_cast<uint16>(std::stoul(row[0])));
}
return l;
}
uint8_t Database::GetInstanceVersion(uint16 instance_id) {
if (!instance_id) {
return 0;
}
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return 0;
}
return i.version;
}
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
{
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
is_perma = false;
return 0;
}
if (i.never_expires) {
if (never_expires == 1)
{
is_perma = true;
return 0;
}
@@ -364,175 +396,204 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
timeval tv;
gettimeofday(&tv, nullptr);
return ((i.start_time + i.duration) - tv.tv_sec);
return ((start_time + duration) - tv.tv_sec);
}
uint32 Database::GetInstanceZoneID(uint16 instance_id)
uint32 Database::VersionFromInstanceID(uint16 instance_id)
{
if (!instance_id) {
return 0;
}
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return 0;
}
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
return i.zone;
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint32 Database::ZoneIDFromInstanceID(uint16 instance_id)
{
std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
{
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = GroupIdRepository::GetWhere(
*this,
fmt::format(
"groupid = {}",
group_id
)
);
if (l.empty()) {
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
uint16 version = VersionFromInstanceID(instance_id);
std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id);
auto results = QueryDatabase(query);
if (!results.Success())
return;
}
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
}
for (auto row = results.begin(); row != results.end(); ++row)
{
uint32 charid = atoi(row[0]);
if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
}
}
void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
{
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = GroupIdRepository::GetWhere(
*this,
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
uint16 version = VersionFromInstanceID(instance_id);
std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id);
auto results = QueryDatabase(query);
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
{
uint32 charid = atoi(row[0]);
if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
}
}
void Database::BuryCorpsesInInstance(uint16 instance_id) {
QueryDatabase(
fmt::format(
"raidid = {}",
raid_id
"UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id = {}",
instance_id
)
);
if (l.empty()) {
return;
}
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
}
}
}
void Database::DeleteInstance(uint16 instance_id)
{
std::string query;
query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id);
QueryDatabase(query);
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id));
query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id);
QueryDatabase(query);
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
QueryDatabase(query);
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
CharacterCorpsesRepository::BuryInstance(*this, instance_id);
BuryCorpsesInInstance(instance_id);
}
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id)
void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid)
{
auto instance_id = GetInstanceID(zone_id, character_id, version);
if (instance_id) {
uint16 id = GetInstanceID(zone, charid, version);
if (id != 0)
return;
}
char ln[128];
memset(ln, 0, 128);
GetGroupLeadershipInfo(group_id, ln);
GetGroupLeadershipInfo(gid, ln);
uint32 l_charid = GetCharacterID((const char*)ln);
uint16 l_id = GetInstanceID(zone, l_charid, version);
auto group_leader_id = GetCharacterID((const char*)ln);
auto group_leader_instance_id = GetInstanceID(zone_id, group_leader_id, version);
if (!group_leader_instance_id) {
if (l_id == 0)
return;
}
AddClientToInstance(group_leader_instance_id, character_id);
AddClientToInstance(l_id, charid);
}
void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id)
void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid)
{
uint16 instance_id = GetInstanceID(zone_id, character_id, version);
if (instance_id) {
uint16 id = GetInstanceID(zone, charid, version);
if (id != 0)
return;
}
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id));
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid));
uint16 l_id = GetInstanceID(zone, l_charid, version);
if (!raid_leader_instance_id) {
if (l_id == 0)
return;
}
AddClientToInstance(raid_leader_instance_id, character_id);
AddClientToInstance(l_id, charid);
}
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids)
{
auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id));
if (l.empty()) {
return;
}
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list) {
for (const auto& e : l) {
character_ids.push_back(e.charid);
}
std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
charid_list.push_back(atoi(row[0]));
}
void Database::PurgeExpiredInstances()
{
/**
* Delay purging by a day so that we can continue using adjacent free instance id's
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but
* has not been fully de-allocated
*/
auto l = InstanceListRepository::GetWhere(
*this,
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0"
);
if (l.empty()) {
std::string query =
SQL(
SELECT
id
FROM
instance_list
where
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
and never_expires = 0
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
if (results.RowCount() == 0) {
return;
}
std::vector<std::string> instance_ids;
for (const auto& e : l) {
instance_ids.emplace_back(std::to_string(e.id));
for (auto row = results.begin(); row != results.end(); ++row) {
instance_ids.emplace_back(row[0]);
}
const auto imploded_instance_ids = Strings::Implode(",", instance_ids);
std::string imploded_instance_ids = implode(",", instance_ids);
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
QueryDatabase(fmt::format("DELETE FROM instance_list WHERE id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("DELETE FROM instance_list_player WHERE id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids));
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
}
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
{
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return;
}
i.start_time = std::time(nullptr);
i.duration = new_duration;
InstanceListRepository::UpdateOne(*this, i);
std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), "
"duration=%u WHERE id=%u", new_duration, instance_id);
auto results = QueryDatabase(query);
}
+5 -54
View File
@@ -53,7 +53,6 @@ namespace DatabaseSchema {
{"character_expedition_lockouts", "character_id"},
{"character_exp_modifiers", "character_id"},
{"character_inspect_messages", "id"},
{"character_instance_safereturns", "character_id"},
{"character_item_recast", "id"},
{"character_languages", "id"},
{"character_leadership_abilities", "id"},
@@ -62,11 +61,9 @@ namespace DatabaseSchema {
{"character_pet_buffs", "char_id"},
{"character_pet_info", "char_id"},
{"character_pet_inventory", "char_id"},
{"character_peqzone_flags", "id"},
{"character_potionbelt", "id"},
{"character_skills", "id"},
{"character_spells", "id"},
{"character_task_timers", "character_id"},
{"character_tasks", "charid"},
{"character_tribute", "id"},
{"completed_tasks", "charid"},
@@ -83,6 +80,7 @@ namespace DatabaseSchema {
{"player_titlesets", "char_id"},
{"quest_globals", "charid"},
{"timers", "char_id"},
{"titles", "char_id"},
{"trader", "char_id"},
{"zone_flags", "charID"}
};
@@ -121,7 +119,6 @@ namespace DatabaseSchema {
"character_expedition_lockouts",
"character_exp_modifiers",
"character_inspect_messages",
"character_instance_safereturns",
"character_item_recast",
"character_languages",
"character_leadership_abilities",
@@ -130,11 +127,9 @@ namespace DatabaseSchema {
"character_pet_buffs",
"character_pet_info",
"character_pet_inventory",
"character_peqzone_flags",
"character_potionbelt",
"character_skills",
"character_spells",
"character_task_timers",
"character_tasks",
"character_tribute",
"completed_tasks",
@@ -159,6 +154,7 @@ namespace DatabaseSchema {
"spell_buckets",
"spell_globals",
"timers",
"titles",
"trader",
"trader_audit",
"zone_flags"
@@ -189,14 +185,13 @@ namespace DatabaseSchema {
"char_create_point_allocations",
"damageshieldtypes",
"doors",
"dynamic_zone_templates",
"faction_association",
"faction_base_data",
"faction_list",
"faction_list_mod",
"fishing",
"forage",
"global_loot",
"goallists",
"graveyard",
"grid",
"grid_entries",
@@ -222,9 +217,9 @@ namespace DatabaseSchema {
"npc_types_tint",
"object",
"pets",
"pets_beastlord_data",
"pets_equipmentset",
"pets_equipmentset_entries",
"proximities",
"skill_caps",
"spawn2",
"spawn_conditions",
@@ -270,7 +265,6 @@ namespace DatabaseSchema {
"perl_event_export_settings",
"profanity_list",
"rule_sets",
"titles",
"rule_values",
"variables",
};
@@ -315,10 +309,6 @@ namespace DatabaseSchema {
"banned_ips",
"bug_reports",
"bugs",
"completed_shared_task_activity_state",
"completed_shared_task_members",
"completed_shared_tasks",
"discord_webhooks",
"dynamic_zone_members",
"dynamic_zones",
"eventlog",
@@ -328,8 +318,8 @@ namespace DatabaseSchema {
"group_id",
"group_leaders",
"hackers",
"instance_list",
"ip_exemptions",
"instance_list",
"item_tick",
"lfguild",
"merchantlist_temp",
@@ -341,10 +331,6 @@ namespace DatabaseSchema {
"respawn_times",
"saylink",
"server_scheduled_events",
"shared_task_activity_state",
"shared_task_dynamic_zones",
"shared_task_members",
"shared_tasks",
};
}
@@ -377,41 +363,6 @@ namespace DatabaseSchema {
};
}
/**
* @description Gets all player bot tables
* @note These tables have no content in the PEQ daily dump
*
* @return
*/
static std::vector<std::string> GetBotTables()
{
return {
"bot_buffs",
"bot_command_settings",
"bot_create_combinations",
"bot_data",
"bot_group_members",
"bot_groups",
"bot_guild_members",
"bot_heal_rotation_members",
"bot_heal_rotation_targets",
"bot_heal_rotations",
"bot_inspect_messages",
"bot_inventories",
"bot_owner_options",
"bot_pet_buffs",
"bot_pet_inventories",
"bot_pets",
"bot_spell_casting_chances",
"bot_spell_settings",
"bot_spells_entries",
"bot_stances",
"bot_timers",
"vw_bot_character_mobs",
"vw_bot_groups"
};
}
}
#endif //EQEMU_DATABASE_SCHEMA_H
+2 -2
View File
@@ -167,7 +167,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
if ((strncasecmp(query, "select", 6) == 0)) {
LogMySQLQuery(
"{0}; -- ({1} row{2} returned) ({3}s)",
"{0} ({1} row{2} returned) ({3}s)",
query,
requestResult.RowCount(),
requestResult.RowCount() == 1 ? "" : "s",
@@ -176,7 +176,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
}
else {
LogMySQLQuery(
"{0}; -- ({1} row{2} affected) ({3}s)",
"{0} ({1} row{2} affected) ({3}s)",
query,
requestResult.RowsAffected(),
requestResult.RowsAffected() == 1 ? "" : "s",
-91
View File
@@ -1,91 +0,0 @@
#include "discord.h"
#include "../http/httplib.h"
#include "../json/json.h"
#include "../strings.h"
#include "../eqemu_logsys.h"
constexpr int MAX_RETRIES = 10;
void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url)
{
// validate
if (webhook_url.empty()) {
LogDiscord("[webhook_url] is empty");
return;
}
// validate
if (webhook_url.find("http://") == std::string::npos && webhook_url.find("https://") == std::string::npos) {
LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url);
return;
}
// split
auto s = Strings::Split(webhook_url, '/');
// url
std::string base_url = fmt::format("{}//{}", s[0], s[2]);
std::string endpoint = Strings::Replace(webhook_url, base_url, "");
// client
httplib::Client cli(base_url.c_str());
cli.set_connection_timeout(0, 15000000); // 15 sec
cli.set_read_timeout(15, 0); // 15 seconds
cli.set_write_timeout(15, 0); // 15 seconds
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
// payload
Json::Value p;
p["content"] = message;
std::stringstream payload;
payload << p;
bool retry = true;
int retries = 0;
int retry_timer = 1000;
while (retry) {
if (auto res = cli.Post(endpoint.c_str(), payload.str(), "application/json")) {
if (res->status != 200 && res->status != 204) {
LogError("[Discord Client] Code [{}] Error [{}]", res->status, res->body);
}
if (res->status == 429) {
if (!res->body.empty()) {
std::stringstream ss(res->body);
Json::Value response;
try {
ss >> response;
}
catch (std::exception const &ex) {
LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body);
}
retry_timer = std::stoi(response["retry_after"].asString()) + 500;
}
LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer);
std::this_thread::sleep_for(std::chrono::milliseconds(retry_timer + 500));
}
if (res->status == 204) {
retry = false;
}
if (retries > MAX_RETRIES) {
LogDiscord("Retries exceeded for message [{}]", message);
retry = false;
}
retries++;
}
}
}
std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string &message)
{
if (category_id == Logs::LogCategory::MySQLQuery) {
return fmt::format("```sql\n{}\n```", message);
}
return message + "\n";
}
-15
View File
@@ -1,15 +0,0 @@
#ifndef EQEMU_DISCORD_H
#define EQEMU_DISCORD_H
#include <string>
#include "../types.h"
class Discord {
public:
static void SendWebhookMessage(const std::string& message, const std::string& webhook_url);
static std::string FormatDiscordMessage(uint16 category_id, const std::string& message);
};
#endif //EQEMU_DISCORD_H
-69
View File
@@ -1,69 +0,0 @@
#include "discord_manager.h"
#include "../common/discord/discord.h"
#include "../common/eqemu_logsys.h"
#include "../common/strings.h"
void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message)
{
webhook_queue_lock.lock();
webhook_message_queue[webhook_id].emplace_back(message);
webhook_queue_lock.unlock();
}
constexpr int MAX_MESSAGE_LENGTH = 1900;
void DiscordManager::ProcessMessageQueue()
{
if (webhook_message_queue.empty()) {
return;
}
webhook_queue_lock.lock();
for (auto &q: webhook_message_queue) {
LogDiscord("Processing [{}] messages in queue for webhook ID [{}]...", q.second.size(), q.first);
if (q.first >= MAX_DISCORD_WEBHOOK_ID) {
LogDiscord("Out of bounds webhook ID [{}] max [{}]", q.first, MAX_DISCORD_WEBHOOK_ID);
continue;
}
auto webhook = LogSys.GetDiscordWebhooks()[q.first];
std::string message;
for (auto &m: q.second) {
// next message would become too large
bool next_message_too_large = ((int) m.length() + (int) message.length()) > MAX_MESSAGE_LENGTH;
if (next_message_too_large) {
Discord::SendWebhookMessage(
message,
webhook.webhook_url
);
message = "";
}
message += m;
// one single message was too large
// this should rarely happen but the message will need to be split
if ((int) message.length() > MAX_MESSAGE_LENGTH) {
for (unsigned mi = 0; mi < message.length(); mi += MAX_MESSAGE_LENGTH) {
Discord::SendWebhookMessage(
message.substr(mi, MAX_MESSAGE_LENGTH),
webhook.webhook_url
);
}
message = "";
}
}
// final flush
if (!message.empty()) {
Discord::SendWebhookMessage(
message,
webhook.webhook_url
);
}
}
webhook_message_queue.clear();
webhook_queue_lock.unlock();
}
-19
View File
@@ -1,19 +0,0 @@
#ifndef EQEMU_DISCORD_MANAGER_H
#define EQEMU_DISCORD_MANAGER_H
#include <mutex>
#include <map>
#include <vector>
#include "../common/types.h"
class DiscordManager {
public:
void QueueWebhookMessage(uint32 webhook_id, const std::string& message);
void ProcessMessageQueue();
private:
std::mutex webhook_queue_lock{};
std::map<uint32, std::vector<std::string>> webhook_message_queue{};
};
#endif
+48 -267
View File
@@ -5,7 +5,6 @@
#include "repositories/instance_list_player_repository.h"
#include "rulesys.h"
#include "servertalk.h"
#include "util/uuid.h"
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
{
@@ -14,12 +13,16 @@ DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& e
uint32_t DynamicZoneBase::Create()
{
if (m_id != 0)
{
return m_id;
}
if (GetInstanceID() == 0)
{
CreateInstance();
}
m_uuid = EQ::Util::UUID::Generate().ToString();
m_id = SaveToDatabase();
return m_id;
@@ -72,14 +75,8 @@ uint32_t DynamicZoneBase::CreateInstance()
void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry)
{
m_id = dz_entry.id;
m_uuid = std::move(dz_entry.uuid);
m_name = std::move(dz_entry.name);
m_leader.id = dz_entry.leader_id;
m_min_players = dz_entry.min_players;
m_max_players = dz_entry.max_players;
m_instance_id = dz_entry.instance_id;
m_type = static_cast<DynamicZoneType>(dz_entry.type);
m_dz_switch_id = dz_entry.dz_switch_id;
m_compass.zone_id = dz_entry.compass_zone_id;
m_compass.x = dz_entry.compass_x;
m_compass.y = dz_entry.compass_y;
@@ -107,12 +104,6 @@ void DynamicZoneBase::AddMemberFromRepositoryResult(
DynamicZoneMembersRepository::MemberWithName&& entry)
{
auto status = DynamicZoneMemberStatus::Unknown;
if (m_leader.id == entry.character_id)
{
m_leader.name = entry.character_name;
}
AddInternalMember({ entry.character_id, std::move(entry.character_name), status });
}
@@ -123,14 +114,8 @@ uint32_t DynamicZoneBase::SaveToDatabase()
if (m_instance_id != 0)
{
auto insert_dz = DynamicZonesRepository::NewEntity();
insert_dz.uuid = m_uuid;
insert_dz.name = m_name;
insert_dz.leader_id = m_leader.id;
insert_dz.min_players = m_min_players;
insert_dz.max_players = m_max_players;
insert_dz.instance_id = m_instance_id,
insert_dz.type = static_cast<int>(m_type);
insert_dz.dz_switch_id = m_dz_switch_id;
insert_dz.compass_zone_id = m_compass.zone_id;
insert_dz.compass_x = m_compass.x;
insert_dz.compass_y = m_compass.y;
@@ -152,80 +137,34 @@ uint32_t DynamicZoneBase::SaveToDatabase()
return 0;
}
bool DynamicZoneBase::AddMember(const DynamicZoneMember& add_member)
void DynamicZoneBase::AddCharacter(uint32_t character_id)
{
if (HasMember(add_member.id))
DynamicZoneMembersRepository::AddMember(GetDatabase(), m_id, character_id);
GetDatabase().AddClientToInstance(m_instance_id, character_id);
SendInstanceAddRemoveCharacter(character_id, false); // stops client kick timer
}
void DynamicZoneBase::RemoveCharacter(uint32_t character_id)
{
DynamicZoneMembersRepository::RemoveMember(GetDatabase(), m_id, character_id);
GetDatabase().RemoveClientFromInstance(m_instance_id, character_id);
SendInstanceAddRemoveCharacter(character_id, true); // start client kick timer
}
void DynamicZoneBase::RemoveAllCharacters(bool enable_removal_timers)
{
if (GetInstanceID() == 0)
{
return false;
return;
}
DynamicZoneMembersRepository::AddMember(GetDatabase(), m_id, add_member.id);
GetDatabase().AddClientToInstance(m_instance_id, add_member.id);
ProcessMemberAddRemove(add_member, false);
SendServerPacket(CreateServerMemberAddRemovePacket(add_member, false).get());
return true;
}
bool DynamicZoneBase::RemoveMember(uint32_t character_id)
{
auto remove_member = GetMemberData(character_id);
return RemoveMember(remove_member);
}
bool DynamicZoneBase::RemoveMember(const std::string& character_name)
{
auto remove_member = GetMemberData(character_name);
return RemoveMember(remove_member);
}
bool DynamicZoneBase::RemoveMember(const DynamicZoneMember& remove_member)
{
if (remove_member.id == 0)
if (enable_removal_timers)
{
return false;
SendInstanceRemoveAllCharacters();
}
DynamicZoneMembersRepository::RemoveMember(GetDatabase(), m_id, remove_member.id);
GetDatabase().RemoveClientFromInstance(m_instance_id, remove_member.id);
ProcessMemberAddRemove(remove_member, true);
SendServerPacket(CreateServerMemberAddRemovePacket(remove_member, true).get());
return true;
}
bool DynamicZoneBase::SwapMember(
const DynamicZoneMember& add_member, const std::string& remove_char_name)
{
auto remove_member = GetMemberData(remove_char_name);
if (!add_member.IsValid() || !remove_member.IsValid())
{
return false;
}
// make remove and add atomic to avoid racing with separate world messages
DynamicZoneMembersRepository::RemoveMember(GetDatabase(), m_id, remove_member.id);
GetDatabase().RemoveClientFromInstance(m_instance_id, remove_member.id);
DynamicZoneMembersRepository::AddMember(GetDatabase(), m_id, add_member.id);
GetDatabase().AddClientToInstance(m_instance_id, add_member.id);
ProcessMemberAddRemove(remove_member, true);
ProcessMemberAddRemove(add_member, false);
SendServerPacket(CreateServerMemberSwapPacket(remove_member, add_member).get());
return true;
}
void DynamicZoneBase::RemoveAllMembers()
{
DynamicZoneMembersRepository::RemoveAllMembers(GetDatabase(), m_id);
GetDatabase().RemoveClientsFromInstance(GetInstanceID());
ProcessRemoveAllMembers();
SendServerPacket(CreateServerRemoveAllMembersPacket().get());
}
void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
@@ -242,6 +181,7 @@ void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
member_entry.dynamic_zone_id = m_id;
member_entry.character_id = member.id;
member_entry.is_current_member = true;
insert_members.emplace_back(member_entry);
InstanceListPlayerRepository::InstanceListPlayer player_entry;
@@ -266,7 +206,7 @@ void DynamicZoneBase::SetCompass(const DynamicZoneLocation& location, bool updat
DynamicZonesRepository::UpdateCompass(GetDatabase(),
m_id, m_compass.zone_id, m_compass.x, m_compass.y, m_compass.z);
SendServerPacket(CreateServerDzLocationPacket(ServerOP_DzSetCompass, location).get());
SendGlobalLocationChange(ServerOP_DzSetCompass, location);
}
}
@@ -287,7 +227,7 @@ void DynamicZoneBase::SetSafeReturn(const DynamicZoneLocation& location, bool up
DynamicZonesRepository::UpdateSafeReturn(GetDatabase(), m_id, m_safereturn.zone_id,
m_safereturn.x, m_safereturn.y, m_safereturn.z, m_safereturn.heading);
SendServerPacket(CreateServerDzLocationPacket(ServerOP_DzSetSafeReturn, location).get());
SendGlobalLocationChange(ServerOP_DzSetSafeReturn, location);
}
}
@@ -309,7 +249,7 @@ void DynamicZoneBase::SetZoneInLocation(const DynamicZoneLocation& location, boo
DynamicZonesRepository::UpdateZoneIn(GetDatabase(), m_id, m_zone_id,
m_zonein.x, m_zonein.y, m_zonein.z, m_zonein.heading, m_has_zonein);
SendServerPacket(CreateServerDzLocationPacket(ServerOP_DzSetZoneIn, location).get());
SendGlobalLocationChange(ServerOP_DzSetZoneIn, location);
}
}
@@ -318,82 +258,35 @@ void DynamicZoneBase::SetZoneInLocation(float x, float y, float z, float heading
SetZoneInLocation({ 0, x, y, z, heading }, update_db);
}
void DynamicZoneBase::SetSwitchID(int dz_switch_id, bool update_db)
{
m_dz_switch_id = dz_switch_id;
if (update_db)
{
DynamicZonesRepository::UpdateSwitchID(GetDatabase(), m_id, dz_switch_id);
SendServerPacket(CreateServerDzSwitchIDPacket().get());
}
}
void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update_db)
{
m_leader = new_leader;
if (update_db)
{
DynamicZonesRepository::UpdateLeaderID(GetDatabase(), m_id, new_leader.id);
}
}
uint32_t DynamicZoneBase::GetSecondsRemaining() const
{
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(GetDurationRemaining()).count();
return std::max(0, static_cast<int>(remaining));
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberAddRemovePacket(
const DynamicZoneMember& member, bool removed)
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerAddRemoveCharacterPacket(
uint32_t character_id, bool removed)
{
constexpr uint32_t pack_size = sizeof(ServerDzMember_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzAddRemoveMember, pack_size);
auto buf = reinterpret_cast<ServerDzMember_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->dz_zone_id = GetZoneID();
buf->dz_instance_id = GetInstanceID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->removed = removed;
buf->character_id = member.id;
buf->character_status = static_cast<uint8_t>(member.status);
strn0cpy(buf->character_name, member.name.c_str(), sizeof(buf->character_name));
constexpr uint32_t pack_size = sizeof(ServerDzCharacter_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzAddRemoveCharacter, pack_size);
auto buf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
buf->zone_id = GetZoneID();
buf->instance_id = GetInstanceID();
buf->remove = removed;
buf->character_id = character_id;
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberSwapPacket(
const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member)
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerRemoveAllCharactersPacket()
{
constexpr uint32_t pack_size = sizeof(ServerDzMemberSwap_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzSwapMembers, pack_size);
auto buf = reinterpret_cast<ServerDzMemberSwap_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->dz_zone_id = GetZoneID();
buf->dz_instance_id = GetInstanceID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->add_character_status = static_cast<uint8_t>(add_member.status);
buf->add_character_id = add_member.id;
buf->remove_character_id = remove_member.id;
strn0cpy(buf->add_character_name, add_member.name.c_str(), sizeof(buf->add_character_name));
strn0cpy(buf->remove_character_name, remove_member.name.c_str(), sizeof(buf->remove_character_name));
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerRemoveAllMembersPacket()
{
constexpr uint32_t pack_size = sizeof(ServerDzID_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzRemoveAllMembers, pack_size);
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->dz_zone_id = GetZoneID();
buf->dz_instance_id = GetInstanceID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
constexpr uint32_t pack_size = sizeof(ServerDzCharacter_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzRemoveAllCharacters, pack_size);
auto buf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
buf->zone_id = GetZoneID();
buf->instance_id = GetInstanceID();
buf->remove = true;
buf->character_id = 0;
return pack;
}
@@ -416,36 +309,10 @@ std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzLocationPacket(
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzSwitchIDPacket()
{
constexpr uint32_t pack_size = sizeof(ServerDzSwitchID_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzSetSwitchID, pack_size);
auto buf = reinterpret_cast<ServerDzSwitchID_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->dz_switch_id = GetSwitchID();
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberStatusPacket(
uint32_t character_id, DynamicZoneMemberStatus status)
{
constexpr uint32_t pack_size = sizeof(ServerDzMemberStatus_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzUpdateMemberStatus, pack_size);
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->status = static_cast<uint8_t>(status);
buf->character_id = character_id;
return pack;
}
uint32_t DynamicZoneBase::GetDatabaseMemberCount()
{
return DynamicZoneMembersRepository::GetCountWhere(GetDatabase(),
fmt::format("dynamic_zone_id = {}", m_id));
fmt::format("dynamic_zone_id = {} AND is_current_member = TRUE", m_id));
}
bool DynamicZoneBase::HasDatabaseMember(uint32_t character_id)
@@ -456,7 +323,7 @@ bool DynamicZoneBase::HasDatabaseMember(uint32_t character_id)
}
auto entries = DynamicZoneMembersRepository::GetWhere(GetDatabase(), fmt::format(
"dynamic_zone_id = {} AND character_id = {}",
"dynamic_zone_id = {} AND character_id = {} AND is_current_member = TRUE",
m_id, character_id
));
@@ -544,33 +411,6 @@ bool DynamicZoneBase::SetInternalMemberStatus(uint32_t character_id, DynamicZone
return false;
}
void DynamicZoneBase::SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status)
{
auto update_member = GetMemberData(character_id);
if (update_member.IsValid())
{
ProcessMemberStatusChange(character_id, status);
SendServerPacket(CreateServerMemberStatusPacket(character_id, status).get());
}
}
void DynamicZoneBase::ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed)
{
if (!removed)
{
AddInternalMember(member);
}
else
{
RemoveInternalMember(member.id);
}
}
bool DynamicZoneBase::ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status)
{
return SetInternalMemberStatus(character_id, status);
}
std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
{
switch (dz_type)
@@ -585,65 +425,6 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
return "Mission";
case DynamicZoneType::Quest:
return "Quest";
default:
return "Unknown";
}
}
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
{
EQ::Net::DynamicPacket dyn_pack;
dyn_pack.PutSerialize(0, *this);
LogDynamicZonesDetail("Serialized server dz size [{}]", dyn_pack.Length());
return dyn_pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzCreatePacket(
uint16_t origin_zone_id, uint16_t origin_instance_id)
{
EQ::Net::DynamicPacket dyn_pack = GetSerializedDzPacket();
auto pack_size = sizeof(ServerDzCreateSerialized_Struct) + dyn_pack.Length();
auto pack = std::make_unique<ServerPacket>(ServerOP_DzCreated, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer);
buf->origin_zone_id = origin_zone_id;
buf->origin_instance_id = origin_instance_id;
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
return pack;
}
void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size)
{
LogDynamicZonesDetail("Deserializing server dz size [{}]", cereal_size);
EQ::Util::MemoryStreamReader ss(cereal_data, cereal_size);
cereal::BinaryInputArchive archive(ss);
archive(*this);
}
void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template)
{
m_zone_id = dz_template.zone_id;
m_zone_version = dz_template.zone_version;
m_name = dz_template.name;
m_min_players = dz_template.min_players;
m_max_players = dz_template.max_players;
m_duration = std::chrono::seconds(dz_template.duration_seconds);
m_dz_switch_id = dz_template.dz_switch_id;
m_compass.zone_id = dz_template.compass_zone_id;
m_compass.x = dz_template.compass_x;
m_compass.y = dz_template.compass_y;
m_compass.z = dz_template.compass_z;
m_safereturn.zone_id = dz_template.return_zone_id;
m_safereturn.x = dz_template.return_x;
m_safereturn.y = dz_template.return_y;
m_safereturn.z = dz_template.return_z;
m_safereturn.heading = dz_template.return_h;
m_has_zonein = dz_template.override_zone_in;
m_zonein.x = dz_template.zone_in_x;
m_zonein.y = dz_template.zone_in_y;
m_zonein.z = dz_template.zone_in_z;
m_zonein.heading = dz_template.zone_in_h;
return "Unknown";
}
+15 -81
View File
@@ -2,10 +2,8 @@
#define COMMON_DYNAMIC_ZONE_BASE_H
#include "eq_constants.h"
#include "net/packet.h"
#include "repositories/dynamic_zones_repository.h"
#include "repositories/dynamic_zone_members_repository.h"
#include "repositories/dynamic_zone_templates_repository.h"
#include <algorithm>
#include <chrono>
#include <cstdint>
@@ -20,7 +18,7 @@ struct DynamicZoneMember
{
uint32_t id = 0;
std::string name;
DynamicZoneMemberStatus status = DynamicZoneMemberStatus::Unknown;
DynamicZoneMemberStatus status = DynamicZoneMemberStatus::Online;
DynamicZoneMember() = default;
DynamicZoneMember(uint32_t id, std::string name_)
@@ -31,12 +29,6 @@ struct DynamicZoneMember
bool IsOnline() const { return status == DynamicZoneMemberStatus::Online ||
status == DynamicZoneMemberStatus::InDynamicZone; }
bool IsValid() const { return id != 0 && !name.empty(); }
template<class Archive>
void serialize(Archive& archive)
{
archive(id, name, status);
}
};
struct DynamicZoneLocation
@@ -50,12 +42,6 @@ struct DynamicZoneLocation
DynamicZoneLocation() = default;
DynamicZoneLocation(uint32_t zone_id_, float x_, float y_, float z_, float heading_)
: zone_id(zone_id_), x(x_), y(y_), z(z_), heading(heading_) {}
template<class Archive>
void serialize(Archive& archive)
{
archive(zone_id, x, y, z, heading);
}
};
class DynamicZoneBase
@@ -75,11 +61,9 @@ public:
virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0;
int GetDuration() const { return static_cast<int>(m_duration.count()); }
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint32_t GetID() const { return m_id; }
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); }
uint32_t GetLeaderID() const { return m_leader.id; }
uint32_t GetMaxPlayers() const { return m_max_players; }
uint32_t GetMemberCount() const { return static_cast<uint32_t>(m_members.size()); }
uint32_t GetMinPlayers() const { return m_min_players; }
@@ -87,11 +71,9 @@ public:
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_zone_id); }
uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); }
uint32_t GetZoneVersion() const { return m_zone_version; }
int GetSwitchID() const { return m_dz_switch_id; }
DynamicZoneType GetType() const { return m_type; }
const std::string& GetLeaderName() const { return m_leader.name; }
const std::string& GetName() const { return m_name; }
const std::string& GetUUID() const { return m_uuid; }
const DynamicZoneMember& GetLeader() const { return m_leader; }
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
const DynamicZoneLocation& GetCompassLocation() const { return m_compass; }
@@ -99,12 +81,14 @@ public:
const DynamicZoneLocation& GetZoneInLocation() const { return m_zonein; }
std::chrono::system_clock::duration GetDurationRemaining() const { return m_expire_time - std::chrono::system_clock::now(); }
bool AddMember(const DynamicZoneMember& add_member);
void AddCharacter(uint32_t character_id);
void AddInternalMember(const DynamicZoneMember& member);
void AddMemberFromRepositoryResult(DynamicZoneMembersRepository::MemberWithName&& entry);
void ClearInternalMembers() { m_members.clear(); }
uint32_t Create();
uint32_t GetDatabaseMemberCount();
DynamicZoneMember GetMemberData(uint32_t character_id);
DynamicZoneMember GetMemberData(const std::string& character_name);
EQ::Net::DynamicPacket GetSerializedDzPacket();
bool HasDatabaseMember(uint32_t character_id);
bool HasMember(uint32_t character_id);
bool HasMember(const std::string& character_name);
@@ -114,56 +98,38 @@ public:
bool IsInstanceID(uint32_t instance_id) const { return (m_instance_id != 0 && m_instance_id == instance_id); }
bool IsValid() const { return m_instance_id != 0; }
bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; }
void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
void RemoveAllMembers();
bool RemoveMember(uint32_t character_id);
bool RemoveMember(const std::string& character_name);
bool RemoveMember(const DynamicZoneMember& remove_member);
void RemoveAllCharacters(bool enable_removal_timers = true);
void RemoveCharacter(uint32_t character_id);
void RemoveInternalMember(uint32_t character_id);
void SaveMembers(const std::vector<DynamicZoneMember>& members);
void SetCompass(const DynamicZoneLocation& location, bool update_db = false);
void SetCompass(uint32_t zone_id, float x, float y, float z, bool update_db = false);
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
void SetLeader(const DynamicZoneMember& leader, bool update_db = false);
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
void SetLeader(const DynamicZoneMember& leader) { m_leader = leader; }
void SetMaxPlayers(uint32_t max_players) { m_max_players = max_players; }
void SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; }
void SetName(const std::string& name) { m_name = name; }
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
void SetSwitchID(int dz_switch_id, bool update_db = false);
void SetType(DynamicZoneType type) { m_type = type; }
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
void SetZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_char_name);
protected:
virtual uint16_t GetCurrentInstanceID() { return 0; }
virtual uint16_t GetCurrentZoneID() { return 0; }
virtual Database& GetDatabase() = 0;
virtual void ProcessCompassChange(const DynamicZoneLocation& location) { m_compass = location; }
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status);
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); }
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
virtual bool SendServerPacket(ServerPacket* packet) = 0;
virtual void SendInstanceAddRemoveCharacter(uint32_t character_id, bool remove) = 0;
virtual void SendInstanceRemoveAllCharacters() = 0;
virtual void SendGlobalLocationChange(uint16_t server_opcode, const DynamicZoneLocation& location) = 0;
void AddInternalMember(const DynamicZoneMember& member);
uint32_t Create();
uint32_t CreateInstance();
void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry);
void RemoveInternalMember(uint32_t character_id);
uint32_t SaveToDatabase();
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
std::unique_ptr<ServerPacket> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id);
std::unique_ptr<ServerPacket> CreateServerAddRemoveCharacterPacket(uint32_t character_id, bool removed);
std::unique_ptr<ServerPacket> CreateServerRemoveAllCharactersPacket();
std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket();
std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed);
std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status);
std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
std::unique_ptr<ServerPacket> CreateServerRemoveAllMembersPacket();
uint32_t m_id = 0;
uint32_t m_zone_id = 0;
@@ -171,12 +137,9 @@ protected:
uint32_t m_zone_version = 0;
uint32_t m_min_players = 0;
uint32_t m_max_players = 0;
int m_dz_switch_id = 0;
bool m_never_expires = false;
bool m_has_zonein = false;
bool m_has_member_statuses = false;
std::string m_name;
std::string m_uuid;
DynamicZoneMember m_leader;
DynamicZoneType m_type{ DynamicZoneType::None };
DynamicZoneLocation m_compass;
@@ -186,35 +149,6 @@ protected:
std::chrono::time_point<std::chrono::system_clock> m_start_time;
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
std::vector<DynamicZoneMember> m_members;
public:
template<class Archive>
void serialize(Archive& archive)
{
archive(
m_id,
m_zone_id,
m_instance_id,
m_zone_version,
m_min_players,
m_max_players,
m_dz_switch_id,
m_never_expires,
m_has_zonein,
m_has_member_statuses,
m_name,
m_uuid,
m_leader,
m_type,
m_compass,
m_safereturn,
m_zonein,
m_duration,
m_start_time,
m_expire_time,
m_members
);
}
};
#endif
+4 -431
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -18,12 +18,7 @@
*/
#include "emu_constants.h"
#include "bodytypes.h"
#include "data_verification.h"
#include "eqemu_logsys.h"
#include "eqemu_logsys_log_aliases.h"
#include "languages.h"
#include "rulesys.h"
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
static const int16 local_array[] = {
@@ -120,7 +115,7 @@ EQ::bug::CategoryID EQ::bug::CategoryNameToCategoryID(const char* category_name)
return catLoNTCG;
if (!strcmp(category_name, "Mercenaries"))
return catMercenaries;
return catOther;
}
@@ -152,430 +147,8 @@ const char *EQ::constants::GetStanceName(StanceType stance_type) {
}
int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
if (EQ::ValueWithin(stance_type, EQ::constants::stancePassive, EQ::constants::stanceBurnAE)) {
if (stance_type >= EQ::constants::stancePassive && stance_type <= EQ::constants::stanceBurnAE)
return (stance_type - EQ::constants::stancePassive);
}
return 0;
}
const std::map<int, std::string>& EQ::constants::GetLanguageMap()
{
static const std::map<int, std::string> language_map = {
{ LANG_COMMON_TONGUE, "Common Tongue" },
{ LANG_BARBARIAN, "Barbarian" },
{ LANG_ERUDIAN, "Erudian" },
{ LANG_ELVISH, "Elvish" },
{ LANG_DARK_ELVISH, "Dark Elvish" },
{ LANG_DWARVISH, "Dwarvish" },
{ LANG_TROLL, "Troll" },
{ LANG_OGRE, "Ogre" },
{ LANG_GNOMISH, "Gnomish" },
{ LANG_HALFLING, "Halfling" },
{ LANG_THIEVES_CANT, "Thieves Cant" },
{ LANG_OLD_ERUDIAN, "Old Erudian" },
{ LANG_ELDER_ELVISH, "Elder Elvish" },
{ LANG_FROGLOK, "Froglok" },
{ LANG_GOBLIN, "Goblin" },
{ LANG_GNOLL, "Gnoll" },
{ LANG_COMBINE_TONGUE, "Combine Tongue" },
{ LANG_ELDER_TEIRDAL, "Elder Teirdal" },
{ LANG_LIZARDMAN, "Lizardman" },
{ LANG_ORCISH, "Orcish" },
{ LANG_FAERIE, "Faerie" },
{ LANG_DRAGON, "Dragon" },
{ LANG_ELDER_DRAGON, "Elder Dragon" },
{ LANG_DARK_SPEECH, "Dark Speech" },
{ LANG_VAH_SHIR, "Vah Shir" },
{ LANG_ALARAN, "Alaran" },
{ LANG_HADAL, "Hadal" },
{ LANG_UNKNOWN, "Unknown" }
};
return language_map;
}
std::string EQ::constants::GetLanguageName(int language_id)
{
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
return EQ::constants::GetLanguageMap().find(language_id)->second;
}
return std::string();
}
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
{
static const std::map<uint32, std::string> ldon_theme_map = {
{ LDoNThemes::Unused, "Unused" },
{ LDoNThemes::GUK, "Deepest Guk" },
{ LDoNThemes::MIR, "Miragul's Menagerie" },
{ LDoNThemes::MMC, "Mistmoore Catacombs" },
{ LDoNThemes::RUJ, "Rujarkian Hills" },
{ LDoNThemes::TAK, "Takish-Hiz" },
};
return ldon_theme_map;
}
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
{
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
return std::string();
}
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
{
static const std::map<int8, std::string> flymode_map = {
{ GravityBehavior::Ground, "Ground" },
{ GravityBehavior::Flying, "Flying" },
{ GravityBehavior::Levitating, "Levitating" },
{ GravityBehavior::Water, "Water" },
{ GravityBehavior::Floating, "Floating" },
{ GravityBehavior::LevitateWhileRunning, "Levitating While Running" },
};
return flymode_map;
}
std::string EQ::constants::GetFlyModeName(int8 flymode_id)
{
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
}
return std::string();
}
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
{
static const std::map<bodyType, std::string> bodytype_map = {
{ BT_Humanoid, "Humanoid" },
{ BT_Lycanthrope, "Lycanthrope" },
{ BT_Undead, "Undead" },
{ BT_Giant, "Giant" },
{ BT_Construct, "Construct" },
{ BT_Extraplanar, "Extraplanar" },
{ BT_Magical, "Magical" },
{ BT_SummonedUndead, "Summoned Undead" },
{ BT_RaidGiant, "Raid Giant" },
{ BT_RaidColdain, "Raid Coldain" },
{ BT_NoTarget, "Untargetable" },
{ BT_Vampire, "Vampire" },
{ BT_Atenha_Ra, "Aten Ha Ra" },
{ BT_Greater_Akheva, "Greater Akheva" },
{ BT_Khati_Sha, "Khati Sha" },
{ BT_Seru, "Seru" },
{ BT_Grieg_Veneficus, "Grieg Veneficus" },
{ BT_Draz_Nurakk, "Draz Nurakk" },
{ BT_Zek, "Zek" },
{ BT_Luggald, "Luggald" },
{ BT_Animal, "Animal" },
{ BT_Insect, "Insect" },
{ BT_Monster, "Monster" },
{ BT_Summoned, "Summoned" },
{ BT_Plant, "Plant" },
{ BT_Dragon, "Dragon" },
{ BT_Summoned2, "Summoned 2" },
{ BT_Summoned3, "Summoned 3" },
{ BT_Dragon2, "Dragon 2" },
{ BT_VeliousDragon, "Velious Dragon" },
{ BT_Familiar, "Familiar" },
{ BT_Dragon3, "Dragon 3" },
{ BT_Boxes, "Boxes" },
{ BT_Muramite, "Muramite" },
{ BT_NoTarget2, "Untargetable 2" },
{ BT_SwarmPet, "Swarm Pet" },
{ BT_MonsterSummon, "Monster Summon" },
{ BT_InvisMan, "Invisible Man" },
{ BT_Special, "Special" },
};
return bodytype_map;
}
std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id)
{
if (EQ::constants::GetBodyTypeMap().find(bodytype_id) != EQ::constants::GetBodyTypeMap().end()) {
return EQ::constants::GetBodyTypeMap().find(bodytype_id)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetAccountStatusMap()
{
static const std::map<uint8, std::string> account_status_map = {
{ AccountStatus::Player, "Player" },
{ AccountStatus::Steward, "Steward" },
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
{ AccountStatus::Guide, "Guide" },
{ AccountStatus::QuestTroupe, "Quest Troupe" },
{ AccountStatus::SeniorGuide, "Senior Guide" },
{ AccountStatus::GMTester, "GM Tester" },
{ AccountStatus::EQSupport, "EQ Support" },
{ AccountStatus::GMStaff, "GM Staff" },
{ AccountStatus::GMAdmin, "GM Admin" },
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
{ AccountStatus::QuestMaster, "Quest Master" },
{ AccountStatus::GMAreas, "GM Areas" },
{ AccountStatus::GMCoder, "GM Coder" },
{ AccountStatus::GMMgmt, "GM Mgmt" },
{ AccountStatus::GMImpossible, "GM Impossible" },
{ AccountStatus::Max, "GM Max" }
};
return account_status_map;
}
std::string EQ::constants::GetAccountStatusName(uint8 account_status)
{
for (
auto status_level = EQ::constants::GetAccountStatusMap().rbegin();
status_level != EQ::constants::GetAccountStatusMap().rend();
++status_level
) {
if (account_status >= status_level->first) {
return status_level->second;
}
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
{
static const std::map<uint8, std::string> consider_level_map = {
{ ConsiderLevel::Ally, "Ally" },
{ ConsiderLevel::Warmly, "Warmly" },
{ ConsiderLevel::Kindly, "Kindly" },
{ ConsiderLevel::Amiably, "Amiably" },
{ ConsiderLevel::Indifferently, "Indifferently" },
{ ConsiderLevel::Apprehensively, "Apprehensively" },
{ ConsiderLevel::Dubiously, "Dubiously" },
{ ConsiderLevel::Threateningly, "Threateningly" },
{ ConsiderLevel::Scowls, "Scowls" }
};
return consider_level_map;
}
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
{
if (EQ::constants::GetConsiderLevelMap().find(faction_consider_level) != EQ::constants::GetConsiderLevelMap().end()) {
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
{
static const std::map<uint8, std::string> damage_type_map = {
{ EnvironmentalDamage::Lava, "Lava" },
{ EnvironmentalDamage::Drowning, "Drowning" },
{ EnvironmentalDamage::Falling, "Falling" },
{ EnvironmentalDamage::Trap, "Trap" }
};
return damage_type_map;
}
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
{
if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
{
static const std::map<uint8, std::string> stuck_behavior_map = {
{ StuckBehavior::RunToTarget, "Run To Target" },
{ StuckBehavior::WarpToTarget, "Warp To Target" },
{ StuckBehavior::TakeNoAction, "Take No Action" },
{ StuckBehavior::EvadeCombat, "Evade Combat" }
};
return stuck_behavior_map;
}
std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id)
{
if (EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
{
static const std::map<uint8, std::string> spawn_animation_map = {
{ SpawnAnimations::Standing, "Standing" },
{ SpawnAnimations::Sitting, "Sitting" },
{ SpawnAnimations::Crouching, "Crouching" },
{ SpawnAnimations::Laying, "Laying" },
{ SpawnAnimations::Looting, "Looting" }
};
return spawn_animation_map;
}
std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
{
if (EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
}
return std::string();
}
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
{
static const std::map<int, std::string> object_type_map = {
{ ObjectTypes::SmallBag, "Small Bag" },
{ ObjectTypes::LargeBag, "Large Bag" },
{ ObjectTypes::Quiver, "Quiver" },
{ ObjectTypes::BeltPouch, "Belt Pouch" },
{ ObjectTypes::WristPouch, "Wrist Pouch" },
{ ObjectTypes::Backpack, "Backpack" },
{ ObjectTypes::SmallChest, "Small Chest" },
{ ObjectTypes::LargeChest, "Large Chest" },
{ ObjectTypes::Bandolier, "Bandolier" },
{ ObjectTypes::Medicine, "Medicine" },
{ ObjectTypes::Tinkering, "Tinkering" },
{ ObjectTypes::Lexicon, "Lexicon" },
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
{ ObjectTypes::Quest, "Quest" },
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
{ ObjectTypes::Baking, "Baking" },
{ ObjectTypes::Tailoring, "Tailoring" },
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
{ ObjectTypes::Fletching, "Fletching" },
{ ObjectTypes::Brewing, "Brewing" },
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
{ ObjectTypes::Pottery, "Pottery" },
{ ObjectTypes::Kiln, "Kiln" },
{ ObjectTypes::KeyMaker, "Key Maker" },
{ ObjectTypes::ResearchWIZ, "Lexicon" },
{ ObjectTypes::ResearchMAG, "Lexicon" },
{ ObjectTypes::ResearchNEC, "Lexicon" },
{ ObjectTypes::ResearchENC, "Lexicon" },
{ ObjectTypes::Unknown, "Unknown" },
{ ObjectTypes::ResearchPractice, "Lexicon" },
{ ObjectTypes::Alchemy, "Alchemy" },
{ ObjectTypes::HighElfForge, "High Elf Forge" },
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
{ ObjectTypes::OgreForge, "Ogre Forge" },
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
{ ObjectTypes::GnomeForge, "Gnome Forge" },
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
{ ObjectTypes::IksarForge, "Iksar Forge" },
{ ObjectTypes::HumanForgeOne, "Human Forge" },
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
{ ObjectTypes::Fishing, "Fishing" },
{ ObjectTypes::TrollForge, "Troll Forge" },
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
{ ObjectTypes::HalflingForge, "Halfling Forge" },
{ ObjectTypes::EruditeForge, "Erudite Forge" },
{ ObjectTypes::Merchant, "Merchant" },
{ ObjectTypes::FroglokForge, "Froglok Forge" },
{ ObjectTypes::Augmenter, "Augmenter" },
{ ObjectTypes::Churn, "Churn" },
{ ObjectTypes::TransformationMold, "Transformation Mold" },
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
{ ObjectTypes::Unattuner, "Unattuner" },
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
{ ObjectTypes::NoDeposit, "No Deposit" }
};
return object_type_map;
}
std::string EQ::constants::GetObjectTypeName(int object_type)
{
if (EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
{
static const std::map<uint8, std::string> weather_type_map = {
{WeatherTypes::None, "None"},
{WeatherTypes::Raining, "Raining"},
{WeatherTypes::Snowing, "Snowing"}
};
return weather_type_map;
}
std::string EQ::constants::GetWeatherTypeName(uint8 weather_type)
{
if (EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
{
static const std::map<uint8, std::string> emote_event_type_map = {
{ EmoteEventTypes::LeaveCombat, "Leave Combat" },
{ EmoteEventTypes::EnterCombat, "Enter Combat" },
{ EmoteEventTypes::OnDeath, "On Death" },
{ EmoteEventTypes::AfterDeath, "After Death" },
{ EmoteEventTypes::Hailed, "Hailed" },
{ EmoteEventTypes::KilledPC, "Killed PC" },
{ EmoteEventTypes::KilledNPC, "Killed NPC" },
{ EmoteEventTypes::OnSpawn, "On Spawn" },
{ EmoteEventTypes::OnDespawn, "On Despawn" }
};
return emote_event_type_map;
}
std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type)
{
if (EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
{
static const std::map<uint8, std::string> emote_type_map = {
{ EmoteTypes::Emote, "Emote" },
{ EmoteTypes::Shout, "Shout" },
{ EmoteTypes::Proximity, "Proximity" }
};
return emote_type_map;
}
std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
{
if (EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
}
return std::string();
}
+14 -273
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,6 @@
#include "eq_limits.h"
#include "emu_versions.h"
#include "bodytypes.h"
#include <string.h>
@@ -32,6 +31,10 @@ namespace EQ
{
using RoF2::IINVALID;
using RoF2::INULL;
namespace inventory {
} /*inventory*/
namespace invtype {
using namespace RoF2::invtype::enum_;
@@ -197,7 +200,7 @@ namespace EQ
using RoF2::constants::EXPANSIONS_MASK;
using RoF2::constants::CHARACTER_CREATION_LIMIT;
const size_t SAY_LINK_OPENER_SIZE = 1;
using RoF2::constants::SAY_LINK_BODY_SIZE;
const size_t SAY_LINK_TEXT_SIZE = 256; // this may be varied until it breaks something (tested:374) - the others are constant
@@ -217,186 +220,9 @@ namespace EQ
stanceBurnAE
};
enum BotSpellIDs : int {
Warrior = 3001,
Cleric,
Paladin,
Ranger,
Shadowknight,
Druid,
Monk,
Bard,
Rogue,
Shaman,
Necromancer,
Wizard,
Magician,
Enchanter,
Beastlord,
Berserker
};
enum GravityBehavior : int8 {
Ground,
Flying,
Levitating,
Water,
Floating,
LevitateWhileRunning
};
enum EnvironmentalDamage : uint8 {
Lava = 250,
Drowning,
Falling,
Trap
};
enum StuckBehavior : uint8 {
RunToTarget,
WarpToTarget,
TakeNoAction,
EvadeCombat
};
enum SpawnAnimations : uint8 {
Standing,
Sitting,
Crouching,
Laying,
Looting
};
enum ObjectTypes : int {
SmallBag,
LargeBag,
Quiver,
BeltPouch,
WristPouch,
Backpack,
SmallChest,
LargeChest,
Bandolier,
Medicine,
Tinkering,
Lexicon,
PoisonMaking,
Quest,
MixingBowl,
Baking,
Tailoring,
Blacksmithing,
Fletching,
Brewing,
JewelryMaking,
Pottery,
Kiln,
KeyMaker,
ResearchWIZ,
ResearchMAG,
ResearchNEC,
ResearchENC,
Unknown,
ResearchPractice,
Alchemy,
HighElfForge,
DarkElfForge,
OgreForge,
DwarfForge,
GnomeForge,
BarbarianForge,
IksarForge,
HumanForgeOne,
HumanForgeTwo,
HalflingTailoringOne,
HalflingTailoringTwo,
EruditeTailoring,
WoodElfTailoring,
WoodElfFletching,
IksarPottery,
Fishing,
TrollForge,
WoodElfForge,
HalflingForge,
EruditeForge,
Merchant,
FroglokForge,
Augmenter,
Churn,
TransformationMold,
DetransformationMold,
Unattuner,
TradeskillBag,
CollectibleBag,
NoDeposit
};
enum WeatherTypes : uint8 {
None,
Raining,
Snowing
};
enum EmoteEventTypes : uint8 {
LeaveCombat,
EnterCombat,
OnDeath,
AfterDeath,
Hailed,
KilledPC,
KilledNPC,
OnSpawn,
OnDespawn
};
enum EmoteTypes : uint8 {
Emote,
Shout,
Proximity
};
const char *GetStanceName(StanceType stance_type);
int ConvertStanceTypeToIndex(StanceType stance_type);
extern const std::map<int, std::string>& GetLanguageMap();
std::string GetLanguageName(int language_id);
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
std::string GetLDoNThemeName(uint32 theme_id);
extern const std::map<int8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(int8 flymode_id);
extern const std::map<bodyType, std::string>& GetBodyTypeMap();
std::string GetBodyTypeName(bodyType bodytype_id);
extern const std::map<uint8, std::string>& GetAccountStatusMap();
std::string GetAccountStatusName(uint8 account_status);
extern const std::map<uint8, std::string>& GetConsiderLevelMap();
std::string GetConsiderLevelName(uint8 consider_level);
extern const std::map<uint8, std::string>& GetEnvironmentalDamageMap();
std::string GetEnvironmentalDamageName(uint8 damage_type);
extern const std::map<uint8, std::string>& GetStuckBehaviorMap();
std::string GetStuckBehaviorName(uint8 behavior_id);
extern const std::map<uint8, std::string>& GetSpawnAnimationMap();
std::string GetSpawnAnimationName(uint8 animation_id);
extern const std::map<int, std::string>& GetObjectTypeMap();
std::string GetObjectTypeName(int object_type);
extern const std::map<uint8, std::string>& GetWeatherTypeMap();
std::string GetWeatherTypeName(uint8 weather_type);
extern const std::map<uint8, std::string>& GetEmoteEventTypeMap();
std::string GetEmoteEventTypeName(uint8 emote_event_type);
extern const std::map<uint8, std::string>& GetEmoteTypeMap();
std::string GetEmoteTypeName(uint8 emote_type);
const int STANCE_TYPE_FIRST = stancePassive;
const int STANCE_TYPE_LAST = stanceBurnAE;
const int STANCE_TYPE_COUNT = stanceBurnAE;
@@ -406,7 +232,7 @@ namespace EQ
namespace profile {
using RoF2::profile::BANDOLIERS_SIZE;
using RoF2::profile::BANDOLIER_ITEM_COUNT;
using RoF2::profile::POTION_BELT_SIZE;
using RoF2::profile::SKILL_ARRAY_SIZE;
@@ -499,98 +325,13 @@ namespace EQ
Guild
};
}; // namespace consent
} /*EQEmu*/
enum ServerLockType : int {
List,
Lock,
Unlock
};
enum AccountStatus : uint8 {
Player = 0,
Steward = 10,
ApprenticeGuide = 20,
Guide = 50,
QuestTroupe = 80,
SeniorGuide = 81,
GMTester = 85,
EQSupport = 90,
GMStaff = 95,
GMAdmin = 100,
GMLeadAdmin = 150,
QuestMaster = 160,
GMAreas = 170,
GMCoder = 180,
GMMgmt = 200,
GMImpossible = 250,
Max = 255
};
enum Invisibility : uint8 {
Visible,
Invisible,
Special = 255
};
enum AugmentActions : int {
Insert,
Remove,
Swap,
Destroy
};
enum ConsiderLevel : uint8 {
Ally = 1,
Warmly,
Kindly,
Amiably,
Indifferently,
Apprehensively,
Dubiously,
Threateningly,
Scowls
};
enum TargetDescriptionType : uint8 {
LCSelf,
UCSelf,
LCYou,
UCYou,
LCYour,
UCYour
};
enum ReloadWorld : uint8 {
NoRepop = 0,
Repop,
ForceRepop
};
enum BucketComparison : uint8 {
BucketEqualTo = 0,
BucketNotEqualTo,
BucketGreaterThanOrEqualTo,
BucketLesserThanOrEqualTo,
BucketGreaterThan,
BucketLesserThan,
BucketIsAny,
BucketIsNotAny,
BucketIsBetween,
BucketIsNotBetween
};
enum class EntityFilterType {
All,
Bots,
Clients,
NPCs
};
enum class ApplySpellType {
Solo,
Group,
Raid
};
#endif /*COMMON_EMU_CONSTANTS_H*/
/* hack list to prevent circular references
eq_limits.h:EQ::inventory::LookupEntry::InventoryTypeSize[n];
*/
+5 -23
View File
@@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest),
N(OP_AltCurrencyPurchase),
N(OP_AltCurrencyReclaim),
N(OP_AltCurrencySell),
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069
N(OP_AltCurrencySellSelection),
N(OP_Animation),
N(OP_AnnoyingZoneUnknown),
N(OP_ApplyPoison),
@@ -71,7 +71,6 @@ N(OP_Camp),
N(OP_CancelSneakHide),
N(OP_CancelTask),
N(OP_CancelTrade),
N(OP_CashReward),
N(OP_CastSpell),
N(OP_ChangeSize),
N(OP_ChannelMessage),
@@ -130,8 +129,8 @@ N(OP_DisciplineTimer),
N(OP_DisciplineUpdate),
N(OP_DiscordMerchantInventory),
N(OP_DoGroupLeadershipAbility),
N(OP_DuelDecline),
N(OP_DuelAccept),
N(OP_DuelResponse),
N(OP_DuelResponse2),
N(OP_DumpName),
N(OP_Dye),
N(OP_DynamicWall),
@@ -304,7 +303,6 @@ N(OP_LockoutTimerInfo),
N(OP_Login),
N(OP_LoginAccepted),
N(OP_LoginComplete),
N(OP_LoginExpansionPacketData), //added for Rof2 client to send expansion data packet. Requires login_opcodes_sod.conf to be updated.
N(OP_LoginUnknown1),
N(OP_LoginUnknown2),
N(OP_Logout),
@@ -357,6 +355,7 @@ N(OP_OpenContainer),
N(OP_OpenDiscordMerchant),
N(OP_OpenGuildTributeMaster),
N(OP_OpenInventory),
N(OP_OpenNewTasksWindow),
N(OP_OpenTributeMaster),
N(OP_PDeletePetition),
N(OP_PetBuffWindow),
@@ -457,7 +456,6 @@ N(OP_ServerListResponse),
N(OP_SessionReady),
N(OP_SetChatServer),
N(OP_SetChatServer2),
N(OP_SetFace),
N(OP_SetGroupTarget),
N(OP_SetGuildMOTD),
N(OP_SetGuildRank),
@@ -466,19 +464,6 @@ N(OP_SetServerFilter),
N(OP_SetStartCity),
N(OP_SetTitle),
N(OP_SetTitleReply),
N(OP_SharedTaskMemberList),
N(OP_SharedTaskAddPlayer),
N(OP_SharedTaskRemovePlayer),
N(OP_SharedTaskMakeLeader),
N(OP_SharedTaskMemberInvite),
N(OP_SharedTaskInvite),
N(OP_SharedTaskInviteResponse),
N(OP_SharedTaskAcceptNew),
N(OP_SharedTaskMemberChange),
N(OP_SharedTaskPlayerList),
N(OP_SharedTaskSelectWindow),
N(OP_SharedTaskQuit),
N(OP_TaskTimers),
N(OP_Shielding),
N(OP_ShopDelItem),
N(OP_ShopEnd),
@@ -514,8 +499,7 @@ N(OP_TaskActivityComplete),
N(OP_TaskDescription),
N(OP_TaskHistoryReply),
N(OP_TaskHistoryRequest),
N(OP_TaskRequestTimer),
N(OP_TaskSelectWindow),
N(OP_TaskMemberList),
N(OP_Taunt),
N(OP_TestBuff),
N(OP_TGB),
@@ -561,7 +545,6 @@ N(OP_WhoAllRequest),
N(OP_WhoAllResponse),
N(OP_World_Client_CRC1),
N(OP_World_Client_CRC2),
N(OP_World_Client_CRC3),
N(OP_WorldClientReady),
N(OP_WorldComplete),
N(OP_WorldLogout),
@@ -584,5 +567,4 @@ N(OP_ZoneServerReady),
N(OP_ZoneSpawns),
N(OP_ZoneUnavail),
N(OP_ResetAA),
N(OP_UnderWorld),
// mail and chat opcodes located in ../mail_oplist.h
+14 -550
View File
@@ -65,7 +65,6 @@
#define AT_FindBits 46 // set FindBits, whatever those are!
#define AT_TextureType 48 // TextureType
#define AT_FacePick 49 // Turns off face pick window? maybe ...
#define AT_AntiCheat 51 // sent by the client randomly telling the server how long since last action has occured
#define AT_GuildShow 52 // this is what MQ2 call sit, not sure
#define AT_Offline 53 // Offline mode
@@ -198,491 +197,13 @@ namespace Chat {
const uint16 Stun = 340;
};
// generation SQL:
// SELECT CONCAT(' constexpr uint16 ', UPPER(short_name), ' = ' , zoneidnumber, '; // ', long_name) from zone group by zoneidnumber ORDER BY zoneidnumber;
namespace Zones {
constexpr uint16 QEYNOS = 1; // South Qeynos
constexpr uint16 QEYNOS2 = 2; // North Qeynos
constexpr uint16 QRG = 3; // The Surefall Glade
constexpr uint16 QEYTOQRG = 4; // The Qeynos Hills
constexpr uint16 HIGHPASS = 5; // Highpass Hold
constexpr uint16 HIGHKEEP = 6; // High Keep
constexpr uint16 FREPORTN = 8; // North Freeport
constexpr uint16 FREPORTW = 9; // West Freeport
constexpr uint16 FREPORTE = 10; // East Freeport
constexpr uint16 RUNNYEYE = 11; // The Liberated Citadel of Runnyeye
constexpr uint16 QEY2HH1 = 12; // The Western Plains of Karana
constexpr uint16 NORTHKARANA = 13; // The Northern Plains of Karana
constexpr uint16 SOUTHKARANA = 14; // The Southern Plains of Karana
constexpr uint16 EASTKARANA = 15; // Eastern Plains of Karana
constexpr uint16 BEHOLDER = 16; // Gorge of King Xorbb
constexpr uint16 BLACKBURROW = 17; // Blackburrow
constexpr uint16 PAW = 18; // The Lair of the Splitpaw
constexpr uint16 RIVERVALE = 19; // Rivervale
constexpr uint16 KITHICOR = 20; // Kithicor Forest
constexpr uint16 COMMONS = 21; // West Commonlands
constexpr uint16 ECOMMONS = 22; // East Commonlands
constexpr uint16 ERUDNINT = 23; // The Erudin Palace
constexpr uint16 ERUDNEXT = 24; // Erudin
constexpr uint16 NEKTULOS = 25; // The Nektulos Forest
constexpr uint16 CSHOME = 26; // Sunset Home
constexpr uint16 LAVASTORM = 27; // The Lavastorm Mountains
constexpr uint16 NEKTROPOS = 28; // Nektropos
constexpr uint16 HALAS = 29; // Halas
constexpr uint16 EVERFROST = 30; // Everfrost Peaks
constexpr uint16 SOLDUNGA = 31; // Solusek's Eye
constexpr uint16 SOLDUNGB = 32; // Nagafen's Lair
constexpr uint16 MISTY = 33; // Misty Thicket
constexpr uint16 NRO = 34; // Northern Desert of Ro
constexpr uint16 SRO = 35; // Southern Desert of Ro
constexpr uint16 BEFALLEN = 36; // Befallen
constexpr uint16 OASIS = 37; // Oasis of Marr
constexpr uint16 TOX = 38; // Toxxulia Forest
constexpr uint16 HOLE = 39; // The Hole
constexpr uint16 NERIAKA = 40; // Neriak - Foreign Quarter
constexpr uint16 NERIAKB = 41; // Neriak - Commons
constexpr uint16 NERIAKC = 42; // Neriak - 3rd Gate
constexpr uint16 NERIAKD = 43; // Neriak Palace
constexpr uint16 NAJENA = 44; // Najena
constexpr uint16 QCAT = 45; // The Qeynos Aqueduct System
constexpr uint16 INNOTHULE = 46; // Innothule Swamp
constexpr uint16 FEERROTT = 47; // The Feerrott
constexpr uint16 CAZICTHULE = 48; // Accursed Temple of CazicThule
constexpr uint16 OGGOK = 49; // Oggok
constexpr uint16 RATHEMTN = 50; // The Rathe Mountains
constexpr uint16 LAKERATHE = 51; // Lake Rathetear
constexpr uint16 GROBB = 52; // Grobb
constexpr uint16 AVIAK = 53; // Aviak Village
constexpr uint16 GFAYDARK = 54; // The Greater Faydark
constexpr uint16 AKANON = 55; // Ak'Anon
constexpr uint16 STEAMFONT = 56; // Steamfont Mountains
constexpr uint16 LFAYDARK = 57; // The Lesser Faydark
constexpr uint16 CRUSHBONE = 58; // Crushbone
constexpr uint16 MISTMOORE = 59; // The Castle of Mistmoore
constexpr uint16 KALADIMA = 60; // South Kaladim
constexpr uint16 FELWITHEA = 61; // Northern Felwithe
constexpr uint16 FELWITHEB = 62; // Southern Felwithe
constexpr uint16 UNREST = 63; // The Estate of Unrest
constexpr uint16 KEDGE = 64; // Kedge Keep
constexpr uint16 GUKTOP = 65; // The City of Guk
constexpr uint16 GUKBOTTOM = 66; // The Ruins of Old Guk
constexpr uint16 KALADIMB = 67; // North Kaladim
constexpr uint16 BUTCHER = 68; // Butcherblock Mountains
constexpr uint16 OOT = 69; // Ocean of Tears
constexpr uint16 CAULDRON = 70; // Dagnor's Cauldron
constexpr uint16 AIRPLANE = 71; // The Plane of Sky
constexpr uint16 FEARPLANE = 72; // The Plane of Fear
constexpr uint16 PERMAFROST = 73; // The Permafrost Caverns
constexpr uint16 KERRARIDGE = 74; // Kerra Isle
constexpr uint16 PAINEEL = 75; // Paineel
constexpr uint16 HATEPLANE = 76; // Plane of Hate
constexpr uint16 ARENA = 77; // The Arena
constexpr uint16 FIELDOFBONE = 78; // The Field of Bone
constexpr uint16 WARSLIKSWOOD = 79; // The Warsliks Woods
constexpr uint16 SOLTEMPLE = 80; // The Temple of Solusek Ro
constexpr uint16 DROGA = 81; // The Temple of Droga
constexpr uint16 CABWEST = 82; // Cabilis West
constexpr uint16 SWAMPOFNOHOPE = 83; // The Swamp of No Hope
constexpr uint16 FIRIONA = 84; // Firiona Vie
constexpr uint16 LAKEOFILLOMEN = 85; // Lake of Ill Omen
constexpr uint16 DREADLANDS = 86; // The Dreadlands
constexpr uint16 BURNINGWOOD = 87; // The Burning Wood
constexpr uint16 KAESORA = 88; // Kaesora
constexpr uint16 SEBILIS = 89; // The Ruins of Sebilis
constexpr uint16 CITYMIST = 90; // The City of Mist
constexpr uint16 SKYFIRE = 91; // The Skyfire Mountains
constexpr uint16 FRONTIERMTNS = 92; // Frontier Mountains
constexpr uint16 OVERTHERE = 93; // The Overthere
constexpr uint16 EMERALDJUNGLE = 94; // The Emerald Jungle
constexpr uint16 TRAKANON = 95; // Trakanon's Teeth
constexpr uint16 TIMOROUS = 96; // Timorous Deep
constexpr uint16 KURN = 97; // Kurn's Tower
constexpr uint16 ERUDSXING = 98; // Erud's Crossing
constexpr uint16 STONEBRUNT = 100; // The Stonebrunt Mountains
constexpr uint16 WARRENS = 101; // The Warrens
constexpr uint16 KARNOR = 102; // Karnor's Castle
constexpr uint16 CHARDOK = 103; // Chardok
constexpr uint16 DALNIR = 104; // The Crypt of Dalnir
constexpr uint16 CHARASIS = 105; // The Howling Stones
constexpr uint16 CABEAST = 106; // Cabilis East
constexpr uint16 NURGA = 107; // The Mines of Nurga
constexpr uint16 VEESHAN = 108; // Veeshan's Peak
constexpr uint16 VEKSAR = 109; // Veksar
constexpr uint16 ICECLAD = 110; // The Iceclad Ocean
constexpr uint16 FROZENSHADOW = 111; // The Tower of Frozen Shadow
constexpr uint16 VELKETOR = 112; // Velketor's Labyrinth
constexpr uint16 KAEL = 113; // Kael Drakkel
constexpr uint16 SKYSHRINE = 114; // Skyshrine
constexpr uint16 THURGADINA = 115; // The City of Thurgadin
constexpr uint16 EASTWASTES = 116; // Eastern Wastes
constexpr uint16 COBALTSCAR = 117; // Cobaltscar
constexpr uint16 GREATDIVIDE = 118; // The Great Divide
constexpr uint16 WAKENING = 119; // The Wakening Land
constexpr uint16 WESTWASTES = 120; // The Western Wastes
constexpr uint16 CRYSTAL = 121; // The Crystal Caverns
constexpr uint16 NECROPOLIS = 123; // Dragon Necropolis
constexpr uint16 TEMPLEVEESHAN = 124; // The Temple of Veeshan
constexpr uint16 SIRENS = 125; // Siren's Grotto
constexpr uint16 MISCHIEFPLANE = 126; // The Plane of Mischief
constexpr uint16 GROWTHPLANE = 127; // The Plane of Growth
constexpr uint16 SLEEPER = 128; // The Sleeper's Tomb
constexpr uint16 THURGADINB = 129; // Icewell Keep
constexpr uint16 ERUDSXING2 = 130; // Marauders Mire
constexpr uint16 SHADOWHAVEN = 150; // Shadow Haven
constexpr uint16 BAZAAR = 151; // The Bazaar
constexpr uint16 NEXUS = 152; // Nexus
constexpr uint16 ECHO_ = 153; // The Echo Caverns
constexpr uint16 ACRYLIA = 154; // The Acrylia Caverns
constexpr uint16 SHARVAHL = 155; // The City of Shar Vahl
constexpr uint16 PALUDAL = 156; // The Paludal Caverns
constexpr uint16 FUNGUSGROVE = 157; // The Fungus Grove
constexpr uint16 VEXTHAL = 158; // Vex Thal
constexpr uint16 SSERU = 159; // Sanctus Seru
constexpr uint16 KATTA = 160; // Katta Castellum
constexpr uint16 NETHERBIAN = 161; // Netherbian Lair
constexpr uint16 SSRATEMPLE = 162; // Ssraeshza Temple
constexpr uint16 GRIEGSEND = 163; // Grieg's End
constexpr uint16 THEDEEP = 164; // The Deep
constexpr uint16 SHADEWEAVER = 165; // Shadeweaver's Thicket
constexpr uint16 HOLLOWSHADE = 166; // Hollowshade Moor
constexpr uint16 GRIMLING = 167; // Grimling Forest
constexpr uint16 MSERU = 168; // Marus Seru
constexpr uint16 LETALIS = 169; // Mons Letalis
constexpr uint16 TWILIGHT = 170; // The Twilight Sea
constexpr uint16 THEGREY = 171; // The Grey
constexpr uint16 TENEBROUS = 172; // The Tenebrous Mountains
constexpr uint16 MAIDEN = 173; // The Maiden's Eye
constexpr uint16 DAWNSHROUD = 174; // The Dawnshroud Peaks
constexpr uint16 SCARLET = 175; // The Scarlet Desert
constexpr uint16 UMBRAL = 176; // The Umbral Plains
constexpr uint16 AKHEVA = 179; // The Akheva Ruins
constexpr uint16 ARENA2 = 180; // The Arena Two
constexpr uint16 JAGGEDPINE = 181; // The Jaggedpine Forest
constexpr uint16 NEDARIA = 182; // Nedaria's Landing
constexpr uint16 TUTORIAL = 183; // EverQuest Tutorial
constexpr uint16 LOAD = 184; // Loading Zone
constexpr uint16 LOAD2 = 185; // New Loading Zone
constexpr uint16 HATEPLANEB = 186; // The Plane of Hate
constexpr uint16 SHADOWREST = 187; // Shadowrest
constexpr uint16 TUTORIALA = 188; // The Mines of Gloomingdeep
constexpr uint16 TUTORIALB = 189; // The Mines of Gloomingdeep
constexpr uint16 CLZ = 190; // Loading
constexpr uint16 CODECAY = 200; // The Crypt of Decay
constexpr uint16 POJUSTICE = 201; // The Plane of Justice
constexpr uint16 POKNOWLEDGE = 202; // The Plane of Knowledge
constexpr uint16 POTRANQUILITY = 203; // The Plane of Tranquility
constexpr uint16 PONIGHTMARE = 204; // The Plane of Nightmares
constexpr uint16 PODISEASE = 205; // The Plane of Disease
constexpr uint16 POINNOVATION = 206; // The Plane of Innovation
constexpr uint16 POTORMENT = 207; // Torment, the Plane of Pain
constexpr uint16 POVALOR = 208; // The Plane of Valor
constexpr uint16 BOTHUNDER = 209; // Bastion of Thunder
constexpr uint16 POSTORMS = 210; // The Plane of Storms
constexpr uint16 HOHONORA = 211; // The Halls of Honor
constexpr uint16 SOLROTOWER = 212; // The Tower of Solusek Ro
constexpr uint16 POWAR = 213; // Plane of War
constexpr uint16 POTACTICS = 214; // Drunder, the Fortress of Zek
constexpr uint16 POAIR = 215; // The Plane of Air
constexpr uint16 POWATER = 216; // The Plane of Water
constexpr uint16 POFIRE = 217; // The Plane of Fire
constexpr uint16 POEARTHA = 218; // The Plane of Earth
constexpr uint16 POTIMEA = 219; // The Plane of Time
constexpr uint16 HOHONORB = 220; // The Temple of Marr
constexpr uint16 NIGHTMAREB = 221; // The Lair of Terris Thule
constexpr uint16 POEARTHB = 222; // The Plane of Earth
constexpr uint16 POTIMEB = 223; // The Plane of Time
constexpr uint16 GUNTHAK = 224; // The Gulf of Gunthak
constexpr uint16 DULAK = 225; // Dulak's Harbor
constexpr uint16 TORGIRAN = 226; // The Torgiran Mines
constexpr uint16 NADOX = 227; // The Crypt of Nadox
constexpr uint16 HATESFURY = 228; // Hate's Fury
constexpr uint16 GUKA = 229; // Deepest Guk: Cauldron of Lost Souls
constexpr uint16 RUJA = 230; // The Rujarkian Hills: Bloodied Quarries
constexpr uint16 TAKA = 231; // Takish-Hiz: Sunken Library
constexpr uint16 MIRA = 232; // Miragul's Menagerie: Silent Gallery
constexpr uint16 MMCA = 233; // Mistmoore's Catacombs: Forlorn Caverns
constexpr uint16 GUKB = 234; // The Drowning Crypt
constexpr uint16 RUJB = 235; // The Rujarkian Hills: Halls of War
constexpr uint16 TAKB = 236; // Takish-Hiz: Shifting Tower
constexpr uint16 MIRB = 237; // Miragul's Menagerie: Frozen Nightmare
constexpr uint16 MMCB = 238; // Mistmoore's Catacombs: Dreary Grotto
constexpr uint16 GUKC = 239; // Deepest Guk: Ancient Aqueducts
constexpr uint16 RUJC = 240; // The Rujarkian Hills: Wind Bridges
constexpr uint16 TAKC = 241; // Takish-Hiz: Within the Compact
constexpr uint16 MIRC = 242; // The Spider Den
constexpr uint16 MMCC = 243; // Mistmoore's Catacombs: Struggles within the Progeny
constexpr uint16 GUKD = 244; // The Mushroom Grove
constexpr uint16 RUJD = 245; // The Rujarkian Hills: Prison Break
constexpr uint16 TAKD = 246; // Takish-Hiz: Royal Observatory
constexpr uint16 MIRD = 247; // Miragul's Menagerie: Hushed Banquet
constexpr uint16 MMCD = 248; // Mistmoore's Catacombs: Chambers of Eternal Affliction
constexpr uint16 GUKE = 249; // Deepest Guk: The Curse Reborn
constexpr uint16 RUJE = 250; // The Rujarkian Hills: Drudge Hollows
constexpr uint16 TAKE = 251; // Takish-Hiz: River of Recollection
constexpr uint16 MIRE = 252; // The Frosted Halls
constexpr uint16 MMCE = 253; // Mistmoore's Catacombs: Sepulcher of the Damned
constexpr uint16 GUKF = 254; // Deepest Guk: Chapel of the Witnesses
constexpr uint16 RUJF = 255; // The Rujarkian Hills: Fortified Lair of the Taskmasters
constexpr uint16 TAKF = 256; // Takish-Hiz: Sandfall Corridors
constexpr uint16 MIRF = 257; // The Forgotten Wastes
constexpr uint16 MMCF = 258; // Mistmoore's Catacombs: Scion Lair of Fury
constexpr uint16 GUKG = 259; // The Root Garden
constexpr uint16 RUJG = 260; // The Rujarkian Hills: Hidden Vale of Deceit
constexpr uint16 TAKG = 261; // Takish-Hiz: Balancing Chamber
constexpr uint16 MIRG = 262; // Miragul's Menagerie: Heart of the Menagerie
constexpr uint16 MMCG = 263; // Mistmoore's Catacombs: Cesspits of Putrescence
constexpr uint16 GUKH = 264; // Deepest Guk: Accursed Sanctuary
constexpr uint16 RUJH = 265; // The Rujarkian Hills: Blazing Forge
constexpr uint16 TAKH = 266; // Takish-Hiz: Sweeping Tides
constexpr uint16 MIRH = 267; // The Morbid Laboratory
constexpr uint16 MMCH = 268; // Mistmoore's Catacombs: Aisles of Blood
constexpr uint16 RUJI = 269; // The Rujarkian Hills: Arena of Chance
constexpr uint16 TAKI = 270; // Takish-Hiz: Antiquated Palace
constexpr uint16 MIRI = 271; // The Theater of Imprisoned Horror
constexpr uint16 MMCI = 272; // Mistmoore's Catacombs: Halls of Sanguinary Rites
constexpr uint16 RUJJ = 273; // The Rujarkian Hills: Barracks of War
constexpr uint16 TAKJ = 274; // Takish-Hiz: Prismatic Corridors
constexpr uint16 MIRJ = 275; // Miragul's Menagerie: Grand Library
constexpr uint16 MMCJ = 276; // Mistmoore's Catacombs: Infernal Sanctuary
constexpr uint16 CHARDOKB = 277; // Chardok: The Halls of Betrayal
constexpr uint16 SOLDUNGC = 278; // The Caverns of Exile
constexpr uint16 ABYSMAL = 279; // The Abysmal Sea
constexpr uint16 NATIMBI = 280; // Natimbi, the Broken Shores
constexpr uint16 QINIMI = 281; // Qinimi, Court of Nihilia
constexpr uint16 RIWWI = 282; // Riwwi, Coliseum of Games
constexpr uint16 BARINDU = 283; // Barindu, Hanging Gardens
constexpr uint16 FERUBI = 284; // Ferubi, Forgotten Temple of Taelosia
constexpr uint16 SNPOOL = 285; // Sewers of Nihilia, Pool of Sludg
constexpr uint16 SNLAIR = 286; // Sewers of Nihilia, Lair of Trapp
constexpr uint16 SNPLANT = 287; // Sewers of Nihilia, Purifying Pla
constexpr uint16 SNCREMATORY = 288; // Sewers of Nihilia, Emanating Cre
constexpr uint16 TIPT = 289; // Tipt, Treacherous Crags
constexpr uint16 VXED = 290; // Vxed, the Crumbling Caverns
constexpr uint16 YXTTA = 291; // Yxtta, Pulpit of Exiles
constexpr uint16 UQUA = 292; // Uqua, the Ocean God Chantry
constexpr uint16 KODTAZ = 293; // Kod'Taz, Broken Trial Grounds
constexpr uint16 IKKINZ = 294; // Ikkinz, Chambers of Transcendence
constexpr uint16 QVIC = 295; // Qvic, Prayer Grounds of Calling
constexpr uint16 INKTUTA = 296; // Inktu'Ta, the Unmasked Chapel
constexpr uint16 TXEVU = 297; // Txevu, Lair of the Elite
constexpr uint16 TACVI = 298; // Tacvi, The Broken Temple
constexpr uint16 QVICB = 299; // Qvic, the Hidden Vault
constexpr uint16 WALLOFSLAUGHTER = 300; // Wall of Slaughter
constexpr uint16 BLOODFIELDS = 301; // The Bloodfields
constexpr uint16 DRANIKSSCAR = 302; // Dranik's Scar
constexpr uint16 CAUSEWAY = 303; // Nobles' Causeway
constexpr uint16 CHAMBERSA = 304; // Muramite Proving Grounds
constexpr uint16 CHAMBERSB = 305; // Muramite Proving Grounds
constexpr uint16 CHAMBERSC = 306; // Muramite Proving Grounds
constexpr uint16 CHAMBERSD = 307; // Muramite Proving Grounds
constexpr uint16 CHAMBERSE = 308; // Muramite Proving Grounds
constexpr uint16 CHAMBERSF = 309; // Muramite Proving Grounds
constexpr uint16 PROVINGGROUNDS = 316; // Muramite Proving Grounds
constexpr uint16 ANGUISH = 317; // Anguish, the Fallen Palace
constexpr uint16 DRANIKHOLLOWSA = 318; // Dranik's Hollows
constexpr uint16 DRANIKHOLLOWSB = 319; // Dranik's Hollows
constexpr uint16 DRANIKHOLLOWSC = 320; // Dranik's Hollows
constexpr uint16 DRANIKCATACOMBSA = 328; // Catacombs of Dranik
constexpr uint16 DRANIKCATACOMBSB = 329; // Catacombs of Dranik
constexpr uint16 DRANIKCATACOMBSC = 330; // Catacombs of Dranik
constexpr uint16 DRANIKSEWERSA = 331; // Sewers of Dranik
constexpr uint16 DRANIKSEWERSB = 332; // Sewers of Dranik
constexpr uint16 DRANIKSEWERSC = 333; // Sewers of Dranik
constexpr uint16 RIFTSEEKERS = 334; // Riftseekers' Sanctum
constexpr uint16 HARBINGERS = 335; // Harbinger's Spire
constexpr uint16 DRANIK = 336; // The Ruined City of Dranik
constexpr uint16 BROODLANDS = 337; // The Broodlands
constexpr uint16 STILLMOONA = 338; // Stillmoon Temple
constexpr uint16 STILLMOONB = 339; // The Ascent
constexpr uint16 THUNDERCREST = 340; // Thundercrest Isles
constexpr uint16 DELVEA = 341; // Lavaspinner's Lair
constexpr uint16 DELVEB = 342; // Tirranun's Delve
constexpr uint16 THENEST = 343; // The Nest
constexpr uint16 GUILDLOBBY = 344; // Guild Lobby
constexpr uint16 GUILDHALL = 345; // Guild Hall
constexpr uint16 BARTER = 346; // The Barter Hall
constexpr uint16 ILLSALIN = 347; // Ruins of Illsalin
constexpr uint16 ILLSALINA = 348; // Illsalin Marketplace
constexpr uint16 ILLSALINB = 349; // Temple of Korlach
constexpr uint16 ILLSALINC = 350; // The Nargil Pits
constexpr uint16 DREADSPIRE = 351; // Dreadspire Keep
constexpr uint16 DRACHNIDHIVE = 354; // The Hive
constexpr uint16 DRACHNIDHIVEA = 355; // The Hatchery
constexpr uint16 DRACHNIDHIVEB = 356; // The Cocoons
constexpr uint16 DRACHNIDHIVEC = 357; // Queen Sendaii`s Lair
constexpr uint16 WESTKORLACH = 358; // Stoneroot Falls
constexpr uint16 WESTKORLACHA = 359; // Prince's Manor
constexpr uint16 WESTKORLACHB = 360; // Caverns of the Lost
constexpr uint16 WESTKORLACHC = 361; // Lair of the Korlach
constexpr uint16 EASTKORLACH = 362; // The Undershore
constexpr uint16 EASTKORLACHA = 363; // Snarlstone Dens
constexpr uint16 SHADOWSPINE = 364; // Shadow Spine
constexpr uint16 CORATHUS = 365; // Corathus Creep
constexpr uint16 CORATHUSA = 366; // Sporali Caverns
constexpr uint16 CORATHUSB = 367; // The Corathus Mines
constexpr uint16 NEKTULOSA = 368; // Shadowed Grove
constexpr uint16 ARCSTONE = 369; // Arcstone, Isle of Spirits
constexpr uint16 RELIC = 370; // Relic, the Artifact City
constexpr uint16 SKYLANCE = 371; // Skylance
constexpr uint16 DEVASTATION = 372; // The Devastation
constexpr uint16 DEVASTATIONA = 373; // The Seething Wall
constexpr uint16 RAGE = 374; // Sverag, Stronghold of Rage
constexpr uint16 RAGEA = 375; // Razorthorn, Tower of Sullon Zek
constexpr uint16 TAKISHRUINS = 376; // Ruins of Takish-Hiz
constexpr uint16 TAKISHRUINSA = 377; // The Root of Ro
constexpr uint16 ELDDAR = 378; // The Elddar Forest
constexpr uint16 ELDDARA = 379; // Tunare's Shrine
constexpr uint16 THEATER = 380; // Theater of Blood
constexpr uint16 THEATERA = 381; // Deathknell, Tower of Dissonance
constexpr uint16 FREEPORTEAST = 382; // East Freeport
constexpr uint16 FREEPORTWEST = 383; // West Freeport
constexpr uint16 FREEPORTSEWERS = 384; // Freeport Sewers
constexpr uint16 FREEPORTACADEMY = 385; // Academy of Arcane Sciences
constexpr uint16 FREEPORTTEMPLE = 386; // Temple of Marr
constexpr uint16 FREEPORTMILITIA = 387; // Freeport Militia House: My Precious
constexpr uint16 FREEPORTARENA = 388; // Arena
constexpr uint16 FREEPORTCITYHALL = 389; // City Hall
constexpr uint16 FREEPORTTHEATER = 390; // Theater of the Tranquil
constexpr uint16 FREEPORTHALL = 391; // Hall of Truth: Bounty
constexpr uint16 NORTHRO = 392; // North Desert of Ro
constexpr uint16 SOUTHRO = 393; // South Desert of Ro
constexpr uint16 CRESCENT = 394; // Crescent Reach
constexpr uint16 MOORS = 395; // Blightfire Moors
constexpr uint16 STONEHIVE = 396; // Stone Hive
constexpr uint16 MESA = 397; // Goru`kar Mesa
constexpr uint16 ROOST = 398; // Blackfeather Roost
constexpr uint16 STEPPES = 399; // The Steppes
constexpr uint16 ICEFALL = 400; // Icefall Glacier
constexpr uint16 VALDEHOLM = 401; // Valdeholm
constexpr uint16 FROSTCRYPT = 402; // Frostcrypt, Throne of the Shade King
constexpr uint16 SUNDEROCK = 403; // Sunderock Springs
constexpr uint16 VERGALID = 404; // Vergalid Mines
constexpr uint16 DIREWIND = 405; // Direwind Cliffs
constexpr uint16 ASHENGATE = 406; // Ashengate, Reliquary of the Scale
constexpr uint16 HIGHPASSHOLD = 407; // Highpass Hold
constexpr uint16 COMMONLANDS = 408; // The Commonlands
constexpr uint16 OCEANOFTEARS = 409; // The Ocean of Tears
constexpr uint16 KITHFOREST = 410; // Kithicor Forest
constexpr uint16 BEFALLENB = 411; // Befallen
constexpr uint16 HIGHPASSKEEP = 412; // HighKeep
constexpr uint16 INNOTHULEB = 413; // The Innothule Swamp
constexpr uint16 TOXXULIA = 414; // Toxxulia Forest
constexpr uint16 MISTYTHICKET = 415; // The Misty Thicket
constexpr uint16 KATTACASTRUM = 416; // Katta Castrum
constexpr uint16 THALASSIUS = 417; // Thalassius, the Coral Keep
constexpr uint16 ATIIKI = 418; // Jewel of Atiiki
constexpr uint16 ZHISZA = 419; // Zhisza, the Shissar Sanctuary
constexpr uint16 SILYSSAR = 420; // Silyssar, New Chelsith
constexpr uint16 SOLTERIS = 421; // Solteris, the Throne of Ro
constexpr uint16 BARREN = 422; // Barren Coast
constexpr uint16 BURIEDSEA = 423; // The Buried Sea
constexpr uint16 JARDELSHOOK = 424; // Jardel's Hook
constexpr uint16 MONKEYROCK = 425; // Monkey Rock
constexpr uint16 SUNCREST = 426; // Suncrest Isle
constexpr uint16 DEADBONE = 427; // Deadbone Reef
constexpr uint16 BLACKSAIL = 428; // Blacksail Folly
constexpr uint16 MAIDENSGRAVE = 429; // Maiden's Grave
constexpr uint16 REDFEATHER = 430; // Redfeather Isle
constexpr uint16 SHIPMVP = 431; // The Open Sea
constexpr uint16 SHIPMVU = 432; // The Open Sea
constexpr uint16 SHIPPVU = 433; // The Open Sea
constexpr uint16 SHIPUVU = 434; // The Open Sea
constexpr uint16 SHIPMVM = 435; // The Open Sea
constexpr uint16 MECHANOTUS = 436; // Fortress Mechanotus
constexpr uint16 MANSION = 437; // Meldrath's Majestic Mansion
constexpr uint16 STEAMFACTORY = 438; // The Steam Factory
constexpr uint16 SHIPWORKSHOP = 439; // S.H.I.P. Workshop
constexpr uint16 GYROSPIREB = 440; // Gyrospire Beza
constexpr uint16 GYROSPIREZ = 441; // Gyrospire Zeka
constexpr uint16 DRAGONSCALE = 442; // Dragonscale Hills
constexpr uint16 LOPINGPLAINS = 443; // Loping Plains
constexpr uint16 HILLSOFSHADE = 444; // Hills of Shade
constexpr uint16 BLOODMOON = 445; // Bloodmoon Keep
constexpr uint16 CRYSTALLOS = 446; // Crystallos, Lair of the Awakened
constexpr uint16 GUARDIAN = 447; // The Mechamatic Guardian
constexpr uint16 STEAMFONTMTS = 448; // The Steamfont Mountains
constexpr uint16 CRYPTOFSHADE = 449; // Crypt of Shade
constexpr uint16 DRAGONSCALEB = 451; // Deepscar's Den
constexpr uint16 OLDFIELDOFBONE = 452; // Field of Scale
constexpr uint16 OLDKAESORAA = 453; // Kaesora Library
constexpr uint16 OLDKAESORAB = 454; // Kaesora Hatchery
constexpr uint16 OLDKURN = 455; // Kurn's Tower
constexpr uint16 OLDKITHICOR = 456; // Bloody Kithicor
constexpr uint16 OLDCOMMONS = 457; // Old Commonlands
constexpr uint16 OLDHIGHPASS = 458; // Highpass Hold
constexpr uint16 THEVOIDA = 459; // The Void
constexpr uint16 THEVOIDB = 460; // The Void
constexpr uint16 THEVOIDC = 461; // The Void
constexpr uint16 THEVOIDD = 462; // The Void
constexpr uint16 THEVOIDE = 463; // The Void
constexpr uint16 THEVOIDF = 464; // The Void
constexpr uint16 THEVOIDG = 465; // The Void
constexpr uint16 OCEANGREENHILLS = 466; // Oceangreen Hills
constexpr uint16 OCEANGREENVILLAGE = 467; // Oceangreen Village
constexpr uint16 OLDBLACKBURROW = 468; // BlackBurrow
constexpr uint16 BERTOXTEMPLE = 469; // Temple of Bertoxxulous
constexpr uint16 DISCORD = 470; // Korafax, Home of the Riders
constexpr uint16 DISCORDTOWER = 471; // Citadel of the Worldslayer
constexpr uint16 OLDBLOODFIELD = 472; // Old Bloodfields
constexpr uint16 PRECIPICEOFWAR = 473; // The Precipice of War
constexpr uint16 OLDDRANIK = 474; // City of Dranik
constexpr uint16 TOSKIRAKK = 475; // Toskirakk
constexpr uint16 KORASCIAN = 476; // Korascian Warrens
constexpr uint16 RATHECHAMBER = 477; // Rathe Council Chamber
constexpr uint16 BRELLSREST = 480; // Brell's Rest
constexpr uint16 FUNGALFOREST = 481; // Fungal Forest
constexpr uint16 UNDERQUARRY = 482; // The Underquarry
constexpr uint16 COOLINGCHAMBER = 483; // The Cooling Chamber
constexpr uint16 SHININGCITY = 484; // Kernagir, the Shining City
constexpr uint16 ARTHICREX = 485; // Arthicrex
constexpr uint16 FOUNDATION = 486; // The Foundation
constexpr uint16 LICHENCREEP = 487; // Lichen Creep
constexpr uint16 PELLUCID = 488; // Pellucid Grotto
constexpr uint16 STONESNAKE = 489; // Volska's Husk
constexpr uint16 BRELLSTEMPLE = 490; // Brell's Temple
constexpr uint16 CONVORTEUM = 491; // The Convorteum
constexpr uint16 BRELLSARENA = 492; // Brell's Arena
constexpr uint16 WEDDINGCHAPEL = 493; // Wedding Chapel
constexpr uint16 WEDDINGCHAPELDARK = 494; // Wedding Chapel
constexpr uint16 DRAGONCRYPT = 495; // Lair of the Risen
constexpr uint16 FEERROTT2 = 700; // The Feerrott
constexpr uint16 THULEHOUSE1 = 701; // House of Thule
constexpr uint16 THULEHOUSE2 = 702; // House of Thule, Upper Floors
constexpr uint16 HOUSEGARDEN = 703; // The Grounds
constexpr uint16 THULELIBRARY = 704; // The Library
constexpr uint16 WELL = 705; // The Well
constexpr uint16 FALLEN = 706; // Erudin Burning
constexpr uint16 MORELLCASTLE = 707; // Morell's Castle
constexpr uint16 SOMNIUM = 708; // Sanctum Somnium
constexpr uint16 ALKABORMARE = 709; // Al'Kabor's Nightmare
constexpr uint16 MIRAGULMARE = 710; // Miragul's Nightmare
constexpr uint16 THULEDREAM = 711; // Fear Itself
constexpr uint16 NEIGHBORHOOD = 712; // Sunrise Hills
constexpr uint16 ARGATH = 724; // Argath, Bastion of Illdaera
constexpr uint16 ARELIS = 725; // Valley of Lunanyn
constexpr uint16 SARITHCITY = 726; // Sarith, City of Tides
constexpr uint16 RUBAK = 727; // Rubak Oseka, Temple of the Sea
constexpr uint16 BEASTDOMAIN = 728; // Beasts' Domain
constexpr uint16 RESPLENDENT = 729; // The Resplendent Temple
constexpr uint16 PILLARSALRA = 730; // Pillars of Alra
constexpr uint16 WINDSONG = 731; // Windsong Sanctuary
constexpr uint16 CITYOFBRONZE = 732; // Erillion, City of Bronze
constexpr uint16 SEPULCHER = 733; // Sepulcher of Order
constexpr uint16 EASTSEPULCHER = 734; // Sepulcher East
constexpr uint16 WESTSEPULCHER = 735; // Sepulcher West
constexpr uint16 SHARDSLANDING = 752; // Shard's Landing
constexpr uint16 XORBB = 753; // Valley of King Xorbb
constexpr uint16 KAELSHARD = 754; // Kael Drakkel: The King's Madness
constexpr uint16 EASTWASTESSHARD = 755; // East Wastes: Zeixshi-Kar's Awakening
constexpr uint16 CRYSTALSHARD = 756; // The Crystal Caverns: Fragment of Fear
constexpr uint16 BREEDINGGROUNDS = 757; // The Breeding Grounds
constexpr uint16 EVILTREE = 758; // Evantil, the Vile Oak
constexpr uint16 GRELLETH = 759; // Grelleth's Palace, the Chateau of Filth
constexpr uint16 CHAPTERHOUSE = 760; // Chapterhouse of the Fallen
constexpr uint16 ARTTEST = 996; // Art Testing Domain
constexpr uint16 FHALLS = 998; // The Forgotten Halls
constexpr uint16 APPRENTICE = 999; // Designer Apprentice
}
//ZoneChange_Struct->success values
#define ZONE_ERROR_NOMSG 0
#define ZONE_ERROR_NOTREADY -1
#define ZONE_ERROR_VALIDPC -2
#define ZONE_ERROR_STORYZONE -3
#define ZONE_ERROR_NOEXPANSION -6
#define ZONE_ERROR_NOEXPERIENCE -7
typedef enum {
@@ -710,7 +231,7 @@ typedef enum {
FilterPetMisses = 21, //0=show, 1=hide
FilterFocusEffects = 22, //0=show, 1=hide
FilterPetSpells = 23, //0=show, 1=hide
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide
FilterHealOverTime = 24, //0=show, 1=hide
FilterUnknown25 = 25,
FilterUnknown26 = 26,
FilterUnknown27 = 27,
@@ -917,9 +438,12 @@ static const uint8 SkillDamageTypes[EQ::skills::HIGHEST_SKILL + 1] = // change t
static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
static const uint32 DB_FACTION_GEM_CHOPPERS = 255;
static const uint32 DB_FACTION_HERETICS = 265;
static const uint32 DB_FACTION_KING_AKANON = 333;
static const uint32 DB_SPELL_CAZIC_TOUCH = 982;
static const uint32 DB_SPELL_TOUCH_OF_VINITRAS = 2859;
static const uint32 DB_FACTION_GEM_CHOPPERS = 255;
static const uint32 DB_FACTION_HERETICS = 265;
static const uint32 DB_FACTION_KING_AKANON = 333;
enum ChatChannelNames : uint16
{
@@ -966,64 +490,4 @@ enum class DynamicZoneMemberStatus : uint8_t
LinkDead
};
enum LDoNThemes {
Unused = 0,
GUK,
MIR,
MMC,
RUJ,
TAK
};
enum LDoNThemeBits {
UnusedBit = 0,
GUKBit = 1,
MIRBit = 2,
MMCBit = 4,
RUJBit = 8,
TAKBit = 16
};
enum StartZoneIndex {
Odus = 0,
Qeynos,
Halas,
Rivervale,
Freeport,
Neriak,
Grobb,
Oggok,
Kaladim,
GreaterFaydark,
Felwithe,
Akanon,
Cabilis,
SharVahl
};
enum FVNoDropFlagRule
{
Disabled = 0,
Enabled = 1,
AdminOnly = 2
};
enum Anonymity : uint8
{
NotAnonymous,
Anonymous,
Roleplaying
};
enum ZoningMessage : int8
{
ZoneNoMessage = 0,
ZoneSuccess = 1,
ZoneNotReady = -1,
ZoneValidPC = -2,
ZoneStoryZone = -3,
ZoneNoExpansion = -6,
ZoneNoExperience = -7
};
#endif /*COMMON_EQ_CONSTANTS_H*/
+16 -16
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -11,7 +11,7 @@
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -26,7 +26,7 @@
static bool global_dictionary_init = false;
void EQ::InitializeDynamicLookups() {
if (global_dictionary_init)
if (global_dictionary_init == true)
return;
constants::InitializeDynamicLookups();
@@ -167,7 +167,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
ClientUnknown::INULL
),
ClientUnknown::INULL,
ClientUnknown::INULL,
ClientUnknown::INULL,
@@ -175,7 +175,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
ClientUnknown::INULL,
ClientUnknown::INULL,
ClientUnknown::INULL,
false,
false,
false,
@@ -194,7 +194,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Client62::INULL, Client62::INULL, Client62::INULL,
Client62::INULL
),
Client62::INULL,
Client62::INULL,
Client62::INULL,
@@ -202,7 +202,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Client62::INULL,
Client62::INULL,
Client62::INULL,
false,
false,
false,
@@ -221,7 +221,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Titanium::INULL, Titanium::INULL, Titanium::INULL,
Titanium::invtype::OTHER_SIZE
),
Titanium::invslot::EQUIPMENT_BITMASK,
Titanium::invslot::GENERAL_BITMASK,
Titanium::invslot::CURSOR_BITMASK,
@@ -229,7 +229,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Titanium::invslot::CORPSE_BITMASK,
Titanium::invbag::SLOT_COUNT,
Titanium::invaug::SOCKET_COUNT,
Titanium::inventory::AllowEmptyBagInBag,
Titanium::inventory::AllowClickCastFromBag,
Titanium::inventory::ConcatenateInvTypeLimbo,
@@ -248,7 +248,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoF::INULL, SoF::INULL, SoF::INULL,
SoF::invtype::OTHER_SIZE
),
SoF::invslot::EQUIPMENT_BITMASK,
SoF::invslot::GENERAL_BITMASK,
SoF::invslot::CURSOR_BITMASK,
@@ -256,7 +256,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoF::invslot::CORPSE_BITMASK,
SoF::invbag::SLOT_COUNT,
SoF::invaug::SOCKET_COUNT,
SoF::inventory::AllowEmptyBagInBag,
SoF::inventory::AllowClickCastFromBag,
SoF::inventory::ConcatenateInvTypeLimbo,
@@ -763,7 +763,7 @@ void EQ::inventory::InitializeDynamicLookups() {
// Notes:
// - Currently, there are only 3 known expansions that affect inventory-related settings in the clients..
// -- Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots
// -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear)
// -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear)
// -- Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 activated (set) and deactivated (clear)
// - Corspe size does not appear to reflect loss of active possessions slots
// - Inspect size does not appear to reflect loss of active equipment slots
@@ -772,7 +772,7 @@ void EQ::inventory::InitializeDynamicLookups() {
// - General9 and General10 slots are activated by GM flag when expansion bit is (clear)
// - Obviously, the client must support the expansion to allow any (set) or override condition
const uint32 dynamic_check_mask =
const uint32 dynamic_check_mask =
(
EQ::expansions::bitPoR |
EQ::expansions::bitTBS |
@@ -1210,10 +1210,10 @@ void EQ::spells::InitializeDynamicLookups() {
if (spells_dictionary_init == true)
return;
spells_dictionary_init = true;
if (RuleB(World, UseClientBasedExpansionSettings))
return;
// use static references for now
}
@@ -1239,7 +1239,7 @@ const EQ::spells::LookupEntry* EQ::spells::DynamicGMLookup(versions::ClientVersi
client_version = versions::ValidateClientVersion(client_version);
if (spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)])
return spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)].get();
return &spells_static_lookup_entries[static_cast<int>(client_version)];
}
+63 -151
View File
@@ -374,19 +374,17 @@ struct NewZone_Struct {
/*0684*/ uint16 zone_id;
/*0686*/ uint16 zone_instance;
/*0688*/ uint32 unknown688;
/*0692*/ uint8 unknown692[8];
/*0692*/ uint8 unknown692[8];
// Titanium doesn't have a translator, but we can still safely add stuff under here without issues since client memcpy's only what it knows
// Just wastes some bandwidth sending to tit clients /shrug
/*0700*/ float fog_density;
/*0704*/ uint32 suspend_buffs;
/*0708*/ uint32 fast_regen_hp;
/*0712*/ uint32 fast_regen_mana;
/*0716*/ uint32 fast_regen_endurance;
/*0720*/ uint32 npc_aggro_max_dist;
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
/*0728*/ uint32 lava_damage; // Seen 50
/*0732*/ uint32 min_lava_damage; // Seen 10
/*0736*/
/*0700*/ float fog_density;
/*0704*/ uint32 SuspendBuffs;
/*0708*/ uint32 FastRegenHP;
/*0712*/ uint32 FastRegenMana;
/*0716*/ uint32 FastRegenEndurance;
/*0720*/ uint32 NPCAggroMaxDist;
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
/*0728*/
};
/*
@@ -448,7 +446,6 @@ struct ManaChange_Struct
/*08*/ uint32 spell_id;
/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting?
/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like
/*16*/ int32 slot; // -1 normal, otherwise clear ETA and GCD
};
struct SwapSpell_Struct
@@ -2134,31 +2131,31 @@ struct AdventureLeaderboard_Struct
};*/
struct Illusion_Struct { //size: 256 - SoF
/*000*/ uint32 spawnid;
/*004*/ char charname[64]; //
/*068*/ uint16 race; //
/*070*/ char unknown006[2];
/*072*/ uint8 gender;
/*073*/ uint8 texture;
/*074*/ uint8 unknown008; //
/*075*/ uint8 unknown009; //
/*076*/ uint8 helmtexture; //
/*077*/ uint8 unknown010; //
/*078*/ uint8 unknown011; //
/*079*/ uint8 unknown012; //
/*080*/ uint32 face; //
/*084*/ uint8 hairstyle; //
/*085*/ uint8 haircolor; //
/*086*/ uint8 beard; //
/*087*/ uint8 beardcolor; //
/*088*/ float size; //
/*092*/ uint32 drakkin_heritage; //
/*096*/ uint32 drakkin_tattoo; //
/*100*/ uint32 drakkin_details; //
/*104*/ EQ::TintProfile armor_tint; //
/*140*/ uint8 eyecolor1; // Field Not Identified in any Illusion Struct
/*141*/ uint8 eyecolor2; // Field Not Identified in any Illusion Struct
/*142*/ uint8 unknown138[114]; //
/*000*/ uint32 spawnid;
/*004*/ char charname[64]; //
/*068*/ uint16 race; //
/*070*/ char unknown006[2];
/*072*/ uint8 gender;
/*073*/ uint8 texture;
/*074*/ uint8 unknown008; //
/*075*/ uint8 unknown009; //
/*076*/ uint8 helmtexture; //
/*077*/ uint8 unknown010; //
/*078*/ uint8 unknown011; //
/*079*/ uint8 unknown012; //
/*080*/ uint32 face; //
/*084*/ uint8 hairstyle; //
/*085*/ uint8 haircolor; //
/*086*/ uint8 beard; //
/*087*/ uint8 beardcolor; //
/*088*/ float size; //
/*092*/ uint32 drakkin_heritage; //
/*096*/ uint32 drakkin_tattoo; //
/*100*/ uint32 drakkin_details; //
/*104*/ EQ::TintProfile armor_tint; //
/*140*/ uint8 eyecolor1; // Field Not Identified in any Illusion Struct
/*141*/ uint8 eyecolor2; // Field Not Identified in any Illusion Struct
/*142*/ uint8 unknown138[114]; //
/*256*/
};
@@ -2192,19 +2189,11 @@ struct QuestReward_Struct
/*068*/
};
struct CashReward_Struct
{
/*000*/ uint32 copper;
/*004*/ uint32 silver;
/*008*/ uint32 gold;
/*012*/ uint32 platinum;
};
// Size: 8
struct Camera_Struct
{
uint32 duration; // Duration in ms
float intensity;
uint32 intensity; // Between 1023410176 and 1090519040
};
struct ZonePoint_Entry {
@@ -2324,12 +2313,9 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle;
/*005*/ uint8 beard;
/*006*/ uint8 face;
/*007*/ uint8 unused_padding;
/*008*/ uint32 drakkin_heritage;
/*012*/ uint32 drakkin_tattoo;
/*016*/ uint32 drakkin_details;
/*020*/ uint32 entity_id;
/*024*/
/*007*/ uint32 drakkin_heritage;
/*011*/ uint32 drakkin_tattoo;
/*015*/ uint32 drakkin_details;
//there are only 10 faces for barbs changing woad just
//increase the face value by ten so if there were 8 woad
//designs then there would be 80 barb faces
@@ -2773,7 +2759,7 @@ struct EnvDamage2_Struct {
/*0004*/ uint16 unknown4;
/*0006*/ uint32 damage;
/*0010*/ uint8 unknown10[12];
/*0022*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
/*0022*/ uint8 dmgtype; //FA = Lava; FC = Falling
/*0023*/ uint8 unknown2[4];
/*0027*/ uint16 constant; //Always FFFF
/*0029*/ uint16 unknown29;
@@ -3632,17 +3618,14 @@ struct LevelAppearance_Struct { //Sends a little graphic on level up
};
struct MerchantList {
uint32 id;
uint32 slot;
uint32 item;
int16 faction_required;
int8 level_required;
uint16 alt_currency_cost;
uint32 classes_required;
uint8 probability;
std::string bucket_name;
std::string bucket_value;
uint8 bucket_comparison;
uint32 id;
uint32 slot;
uint32 item;
int16 faction_required;
int8 level_required;
uint16 alt_currency_cost;
uint32 classes_required;
uint8 probability;
};
struct TempMerchantList {
@@ -3731,66 +3714,17 @@ struct SetTitleReply_Struct {
uint32 entity_id;
};
struct SharedTaskMemberList_Struct {
/*00*/ uint32 gopher_id;
/*04*/ uint32 unknown04;
/*08*/ uint32 member_count; //1 less than the number of members
///*12*/ char list_pointer[0];
char member_name[1]; //null terminated string
uint32 monster_mission; // class chosen
uint8 task_leader; //boolean flag
struct TaskMemberList_Struct {
/*00*/ uint32 gopher_id;
/*04*/ uint32 unknown04;
/*08*/ uint32 member_count; //1 less than the number of members
/*12*/ char list_pointer[0];
/* list is of the form:
char member_name[1] //null terminated string
uint8 task_leader //boolean flag
*/
};
struct SharedTaskQuit_Struct {
int32 field1;
int32 field2;
int32 field3;
};
struct SharedTaskAddPlayer_Struct {
int32 field1;
int32 field2;
char player_name[64];
};
struct SharedTaskMakeLeader_Struct {
int32 field1;
int32 field2;
char player_name[64];
};
struct SharedTaskRemovePlayer_Struct {
int32 field1;
int32 field2;
char player_name[64];
};
struct SharedTaskInvite_Struct {
int32_t unknown00; // probably the unique character id sent in some packets
int32_t invite_id; // invite id sent back in response
char task_name[64];
char inviter_name[64];
};
struct SharedTaskInviteResponse_Struct {
int32_t unknown00; // 0
int32_t invite_id; // same id sent in the invite, probably for server verification
int8_t accepted; // 0: declined 1: accepted
int8_t padding[3]; // padding garbage probably
};
struct SharedTaskAccept_Struct {
int32_t unknown00;
int32_t unknown04;
uint32_t npc_entity_id; // npc task giver entity id (sent in selection window)
uint32_t task_id;
float reward_multiplier; // added after titanium (sent in selection window)
};
#if 0
// Old struct not used by Task System implementation but left for reference
@@ -3883,7 +3817,7 @@ struct TaskHistory_Struct {
#endif
struct AcceptNewTask_Struct {
uint32 task_type; // type sent in selection window
uint32 unknown00;
uint32 task_id; //set to 0 for 'decline'
uint32 task_master_id; //entity ID
};
@@ -4357,8 +4291,8 @@ struct AARankPrereq_Struct
struct AARankEffect_Struct
{
int32 effect_id;
int32 base_value;
int32 limit_value;
int32 base1;
int32 base2;
int32 slot;
};
@@ -4366,8 +4300,8 @@ struct AARankEffect_Struct
struct AA_Ability {
/*00*/ uint32 skill_id;
/*04*/ uint32 base_value;
/*08*/ uint32 limit_value;
/*04*/ uint32 base1;
/*08*/ uint32 base2;
/*12*/ uint32 slot;
};
@@ -5006,7 +4940,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 dz_switch_id;
/*008*/ uint32 unknown008;
/*012*/ float y;
/*016*/ float x;
/*020*/ float z;
@@ -5163,10 +5097,10 @@ struct AltCurrencySelectItemReply_Struct {
/*000*/ uint32 unknown000;
/*004*/ uint8 unknown004; //0xff
/*005*/ uint8 unknown005; //0xff
/*006*/ uint16 unknown006; //0xffff
/*008*/ uint16 unknown008; //0xffff
/*010*/ char item_name[64];
/*074*/ uint16 unknown074;
/*006*/ uint8 unknown006; //0xff
/*007*/ uint8 unknown007; //0xff
/*008*/ char item_name[64];
/*072*/ uint32 unknown074;
/*076*/ uint32 cost;
/*080*/ uint32 unknown080;
/*084*/ uint32 unknown084;
@@ -5596,28 +5530,6 @@ struct SayLinkBodyFrame_Struct {
/*056*/
};
struct Checksum_Struct {
uint64 checksum;
uint8 data[2048];
};
struct UpdateMovementEntry {
/* 00 */ float Y;
/* 04 */ float X;
/* 08 */ float Z;
/* 12 */ uint8 type;
/* 13 */ unsigned int timestamp;
/* 17 */
};
struct UnderWorld {
/* 00 */ int spawn_id;
/* 04 */ float y;
/* 08 */ float x;
/* 12 */ float z;
/* 16 */
};
// Restore structure packing to default
#pragma pack()
+7 -7
View File
@@ -23,7 +23,7 @@
#include "op_codes.h"
#include "crc16.h"
#include "platform.h"
#include "strings.h"
#include "string_util.h"
#include <string>
#include <iomanip>
@@ -406,7 +406,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
LogNetcode(_L "Pre-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
}
//if the packet they got out of order is between our last acked packet and the last sent packet, then its valid.
if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) {
Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L,
@@ -453,7 +453,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
(unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta),
(unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta),
(unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta));
AdjustRates(ntohl(ClientStats->average_delta));
if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
@@ -951,7 +951,7 @@ EQRawApplicationPacket *p=nullptr;
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
if (emu_op == OP_Unknown) {
// Log(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str());
}
}
p->SetOpcode(emu_op);
}
}
@@ -1359,11 +1359,11 @@ void EQStream::AdjustRates(uint32 average_delta)
DecayRate=DECAYBASE/average_delta;
if (BytesWritten > RateThreshold)
BytesWritten = RateThreshold + DecayRate;
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
RateThreshold, DecayRate, average_delta);
MRate.unlock();
} else {
Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L,
Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L,
average_delta, AVERAGE_DELTA_MAX);
AverageDelta = AVERAGE_DELTA_MAX;
}
@@ -1374,7 +1374,7 @@ void EQStream::AdjustRates(uint32 average_delta)
BytesWritten = 0;
RateThreshold=RATEBASE/average_delta;
DecayRate=DECAYBASE/average_delta;
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
RateThreshold, DecayRate, average_delta);
MRate.unlock();
}
+6 -11
View File
@@ -218,13 +218,13 @@ class EQStream : public EQStreamInterface {
void init(bool resetSession=true);
public:
EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED;
StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2;
bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0;
EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED;
StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2;
bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0;
streamactive = false; }
EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr;
remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream;
compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0;
EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr;
remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream;
compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0;
create_time = Timer::GetTimeSeconds(); }
virtual ~EQStream() { RemoveData(); SetState(CLOSED); }
void SetMaxLen(uint32 length) { MaxLen=length; }
@@ -243,11 +243,6 @@ class EQStream : public EQStreamInterface {
virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; }
virtual OpcodeManager* GetOpcodeManager() const
{
return (*OpMgr);
};
void CheckTimeout(uint32 now, uint32 timeout=30);
bool HasOutgoingData();
void Process(const unsigned char *data, const uint32 length);
+1 -2
View File
@@ -30,7 +30,7 @@ struct EQStreamManagerInterfaceOptions
//World seems to support both compression and xor zone supports one or the others.
//Enforce one or the other in the convienence construct
//Login I had trouble getting to recognize compression at all
//Login I had trouble getting to recognize compression at all
//but that might be because it was still a bit buggy when i was testing that.
if (compressed) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression;
@@ -100,7 +100,6 @@ public:
virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; }
virtual EQStreamState GetState() = 0;
virtual void SetOpcodeManager(OpcodeManager **opm) = 0;
virtual OpcodeManager* GetOpcodeManager() const = 0;
virtual const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; }
virtual Stats GetStats() const = 0;
virtual void ResetStats() = 0;
+5 -6
View File
@@ -38,8 +38,12 @@ void EQStreamProxy::SetOpcodeManager(OpcodeManager **opm)
}
void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
if (p == nullptr) {
if(p == nullptr)
return;
if (p->GetOpcode() != OP_SpecialMesg) {
Log(Logs::General, Logs::PacketServerClient, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
Log(Logs::General, Logs::PacketServerClientWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
}
EQApplicationPacket *newp = p->Copy();
@@ -108,8 +112,3 @@ bool EQStreamProxy::CheckState(EQStreamState state) {
return false;
}
OpcodeManager *EQStreamProxy::GetOpcodeManager() const
{
return (*m_opcodes);
}
+1 -3
View File
@@ -34,15 +34,13 @@ public:
virtual Stats GetStats() const;
virtual void ResetStats();
virtual EQStreamManagerInterface* GetManager() const;
virtual OpcodeManager* GetOpcodeManager() const;
protected:
std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object.
const StructStrategy *const m_structs; //we do not own this object.
//this is a pointer to a pointer to make it less likely that a packet will
//reference an invalid opcode manager when they are being reloaded.
OpcodeManager **const m_opcodes;
//we do not own this object.
OpcodeManager **const m_opcodes; //we do not own this object.
};
#endif /*EQSTREAMPROXY_H_*/
+1 -18
View File
@@ -44,12 +44,6 @@ void EQEmuConfig::parse_config()
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString();
// at least today, this is wrong a majority of the time
// remove this if eqemulator ever upgrades its loginserver
if (LoginHost.find("login.eqemulator.net") != std::string::npos) {
LoginLegacy = true;
}
}
else {
char str[32];
@@ -68,19 +62,12 @@ void EQEmuConfig::parse_config()
loginconfig->LoginLegacy = false;
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") { loginconfig->LoginLegacy = true; }
// at least today, this is wrong a majority of the time
// remove this if eqemulator ever upgrades its loginserver
if (loginconfig->LoginHost.find("login.eqemulator.net") != std::string::npos) {
loginconfig->LoginLegacy = true;
}
loginlist.Insert(loginconfig);
} while (LoginCount < 100);
}
//<locked> from xml converts to json as locked: "", so i default to "false".
//<locked> from xml converts to json as locked: "", so i default to "false".
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
Locked = false;
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
@@ -100,10 +87,6 @@ void EQEmuConfig::parse_config()
WorldHTTPEnabled = true;
}
if (_root["server"].get("disable_config_checks", "false").asString() == "true") {
DisableConfigChecks = true;
}
/**
* UCS
*/
+7 -18
View File
@@ -20,9 +20,7 @@
#include "json/json.h"
#include "linked_list.h"
#include "path_manager.h"
#include <fstream>
#include <fmt/format.h>
struct LoginConfig {
std::string LoginHost;
@@ -60,7 +58,6 @@ class EQEmuConfig
uint16 WorldHTTPPort;
std::string WorldHTTPMimeFile;
std::string SharedKey;
bool DisableConfigChecks;
// From <chatserver/>
std::string ChatHost;
@@ -133,7 +130,7 @@ class EQEmuConfig
void parse_config();
EQEmuConfig()
{
{
}
virtual ~EQEmuConfig() {}
@@ -154,38 +151,30 @@ class EQEmuConfig
}
// Load the config
static bool LoadConfig(const std::string& path = "")
static bool LoadConfig()
{
if (_config != nullptr) {
return true;
}
_config = new EQEmuConfig;
return parseFile(path);
return parseFile();
}
// Load config file and parse data
static bool parseFile(const std::string& file_path = ".")
{
static bool parseFile() {
if (_config == nullptr) {
return LoadConfig(file_path);
return LoadConfig();
}
std::string file = fmt::format(
"{}/{}",
(file_path.empty() ? path.GetServerPath() : file_path),
EQEmuConfig::ConfigFile
);
std::ifstream fconfig(file, std::ifstream::binary);
std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary);
try {
fconfig >> _config->_root;
_config->parse_config();
}
catch (std::exception &) {
return false;
}
}
return true;
}
+134 -303
View File
@@ -21,11 +21,9 @@
#include "eqemu_logsys.h"
#include "rulesys.h"
#include "platform.h"
#include "strings.h"
#include "string_util.h"
#include "database.h"
#include "misc.h"
#include "discord/discord.h"
#include "repositories/discord_webhooks_repository.h"
#include "repositories/logsys_categories_repository.h"
#include <iostream>
#include <fstream>
@@ -33,7 +31,6 @@
#include <iomanip>
#include <time.h>
#include <sys/stat.h>
#include <algorithm>
std::ofstream process_log;
@@ -48,7 +45,6 @@ std::ofstream process_log;
#include <unistd.h>
#include <sys/stat.h>
#include <thread>
#endif
@@ -91,8 +87,8 @@ namespace Console {
*/
EQEmuLogSys::EQEmuLogSys()
{
m_on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
m_on_log_console_hook = [](uint16 log_type, const std::string &) {};
on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
on_log_console_hook = [](uint16 debug_level, uint16 log_type, const std::string &) {};
}
/**
@@ -100,48 +96,38 @@ EQEmuLogSys::EQEmuLogSys()
*/
EQEmuLogSys::~EQEmuLogSys() = default;
EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
void EQEmuLogSys::LoadLogSettingsDefaults()
{
/**
* Get Executable platform currently running this code (Zone/World/etc)
*/
m_log_platform = GetExecutablePlatformInt();
log_platform = GetExecutablePlatformInt();
for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) {
log_settings[log_category_id].log_to_console = 0;
log_settings[log_category_id].log_to_file = 0;
log_settings[log_category_id].log_to_gmsay = 0;
log_settings[log_category_id].log_to_discord = 0;
log_settings[log_category_id].is_category_enabled = 0;
}
m_file_logs_enabled = false;
file_logs_enabled = false;
/**
* Set Defaults
*/
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loot].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Scheduler].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::CombatRecord].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loot].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Scheduler].log_to_console = static_cast<uint8>(Logs::General);
/**
* RFC 5424
@@ -161,8 +147,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
const bool log_to_console = log_settings[log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0;
const bool log_to_discord = log_settings[log_category_id].log_to_discord > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
if (is_category_enabled) {
log_settings[log_category_id].is_category_enabled = 1;
}
@@ -171,29 +156,27 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/**
* Declare process file names for log writing=
*/
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld) {
m_platform_file_name = "world";
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) {
platform_file_name = "world";
}
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
m_platform_file_name = "query_server";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
platform_file_name = "query_server";
}
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) {
m_platform_file_name = "zone";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
platform_file_name = "zone";
}
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformUCS) {
m_platform_file_name = "ucs";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) {
platform_file_name = "ucs";
}
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLogin) {
m_platform_file_name = "login";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) {
platform_file_name = "login";
}
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLaunch) {
m_platform_file_name = "launcher";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) {
platform_file_name = "launcher";
}
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformHC) {
m_platform_file_name = "hc";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) {
platform_file_name = "hc";
}
return this;
}
/**
@@ -214,12 +197,54 @@ bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category)
);
}
/**
* @param log_category
* @param in_message
* @return
*/
std::string EQEmuLogSys::FormatOutMessageString(
uint16 log_category,
const std::string &in_message
)
{
std::string return_string = "[" + GetPlatformName() + "] ";
return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message;
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessGMSay(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
{
/**
* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
*/
if (log_category == Logs::LogCategory::Netcode) {
return;
}
/**
* Check to see if the process that actually ran this is zone
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
on_log_gmsay_hook(log_category, message);
}
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessLogWrite(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
@@ -230,16 +255,17 @@ void EQEmuLogSys::ProcessLogWrite(
std::ofstream crash_log;
EQEmuLogSys::MakeDirectory("logs/crashes");
crash_log.open(
StringFormat("logs/crashes/crash_%s_%i.log", m_platform_file_name.c_str(), getpid()),
StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
crash_log << time_stamp << " " << message << "\n";
crash_log.close();
}
char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
if (process_log) {
char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
process_log << time_stamp << " " << message << std::endl;
}
}
@@ -256,7 +282,6 @@ uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category)
return Console::Color::Yellow;
case Logs::MySQLError:
case Logs::Error:
case Logs::QuestErrors:
return Console::Color::LightRed;
case Logs::MySQLQuery:
case Logs::Debug:
@@ -284,7 +309,6 @@ std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
case Logs::Normal:
return LC_YELLOW;
case Logs::MySQLError:
case Logs::QuestErrors:
case Logs::Warning:
case Logs::Critical:
case Logs::Error:
@@ -315,7 +339,6 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
case Logs::Normal:
return Chat::Yellow;
case Logs::MySQLError:
case Logs::QuestErrors:
case Logs::Error:
return Chat::Red;
case Logs::MySQLQuery:
@@ -338,7 +361,7 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessConsoleMessage(uint16 log_category, const std::string &message)
void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message)
{
#ifdef _WINDOWS
HANDLE console_handle;
@@ -356,7 +379,7 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 log_category, const std::string &
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
#endif
m_on_log_console_hook(log_category, message);
on_log_console_hook(debug_level, log_category, message);
}
/**
@@ -413,52 +436,47 @@ void EQEmuLogSys::Out(
...
)
{
auto l = GetLogsEnabled(debug_level, log_category);
bool log_to_console = true;
if (log_settings[log_category].log_to_console < debug_level) {
log_to_console = false;
}
// bail out if nothing to log
if (!l.log_enabled) {
bool log_to_file = true;
if (log_settings[log_category].log_to_file < debug_level) {
log_to_file = false;
}
bool log_to_gmsay = true;
if (log_settings[log_category].log_to_gmsay < debug_level) {
log_to_gmsay = false;
}
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
if (nothing_to_log) {
return;
}
std::string prefix;
if (RuleB(Logging, PrintFileFunctionAndLine)) {
prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
}
// remove this when we remove all legacy logs
bool ignore_log_legacy_format = (
log_category == Logs::Netcode ||
log_category == Logs::PacketServerClient ||
log_category == Logs::PacketClientServer ||
log_category == Logs::PacketServerToServer
);
va_list args;
va_start(args, message);
std::string output_message = vStringFormat(message, args);
va_end(args);
// remove this when we remove all legacy logs
std::string output_message = message;
if (!ignore_log_legacy_format) {
va_list args;
va_start(args, message);
output_message = vStringFormat(message, args);
va_end(args);
}
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message);
if (l.log_to_console_enabled) {
EQEmuLogSys::ProcessConsoleMessage(
log_category,
fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message)
);
if (log_to_console) {
EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
}
if (l.log_to_gmsay_enabled) {
m_on_log_gmsay_hook(log_category, output_message);
if (log_to_gmsay) {
EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
}
if (l.log_to_file_enabled) {
EQEmuLogSys::ProcessLogWrite(
log_category,
fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message)
);
}
if (l.log_to_discord_enabled && m_on_log_discord_hook) {
m_on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message);
if (log_to_file) {
EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
}
}
@@ -471,7 +489,7 @@ void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp)
struct tm *time_info;
time(&raw_time);
time_info = localtime(&raw_time);
strftime(time_stamp, 80, "[%m-%d-%Y %H:%M:%S]", time_info);
strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info);
}
/**
@@ -510,45 +528,53 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
/**
* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one...
*/
if (!m_file_logs_enabled) {
if (!file_logs_enabled) {
return;
}
/**
* Zone
*/
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) {
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
if (!log_name.empty()) {
m_platform_file_name = log_name;
platform_file_name = log_name;
}
if (m_platform_file_name.empty()) {
if (platform_file_name.empty()) {
return;
}
LogInfo("Starting File Log [{}/zone/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid());
LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid());
// Make directory if not exists
EQEmuLogSys::MakeDirectory(fmt::format("{}/zone", GetLogPath()));
/**
* Make directory if not exists
*/
EQEmuLogSys::MakeDirectory("logs/zone");
// Open file pointer
/**
* Open file pointer
*/
process_log.open(
fmt::format("{}/zone/{}_{}.log", GetLogPath(), m_platform_file_name, getpid()),
StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
}
else {
// All other processes
if (m_platform_file_name.empty()) {
/**
* All other processes
*/
if (platform_file_name.empty()) {
return;
}
LogInfo("Starting File Log [{}/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid());
LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid());
// Open file pointer
/**
* Open file pointer
*/
process_log.open(
fmt::format("{}/{}_{}.log", GetLogPath(), m_platform_file_name.c_str(), getpid()),
StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
}
@@ -575,198 +601,3 @@ void EQEmuLogSys::EnableConsoleLogging()
log_settings[log_index].is_category_enabled = 1;
}
}
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
{
InjectTablesIfNotExist();
auto categories = LogsysCategoriesRepository::GetWhere(
*m_database,
"TRUE ORDER BY log_category_id"
);
// keep track of categories
std::vector<int> db_categories{};
db_categories.reserve(categories.size());
// loop through database categories
for (auto &c: categories) {
if (c.log_category_id <= Logs::None || c.log_category_id >= Logs::MaxCategoryID) {
continue;
}
log_settings[c.log_category_id].log_to_console = static_cast<uint8>(c.log_to_console);
log_settings[c.log_category_id].log_to_file = static_cast<uint8>(c.log_to_file);
log_settings[c.log_category_id].log_to_gmsay = static_cast<uint8>(c.log_to_gmsay);
log_settings[c.log_category_id].log_to_discord = static_cast<uint8>(c.log_to_discord);
log_settings[c.log_category_id].discord_webhook_id = c.discord_webhook_id;
// Determine if any output method is enabled for the category
// and set it to 1 so it can used to check if category is enabled
const bool log_to_console = log_settings[c.log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[c.log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[c.log_category_id].log_to_gmsay > 0;
const bool log_to_discord = log_settings[c.log_category_id].log_to_discord > 0 &&
log_settings[c.log_category_id].discord_webhook_id > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord;
if (is_category_enabled) {
log_settings[c.log_category_id].is_category_enabled = 1;
}
// This determines whether or not the process needs to actually file log anything.
// If we go through this whole loop and nothing is set to any debug level, there
// is no point to create a file or keep anything open
if (log_settings[c.log_category_id].log_to_file > 0) {
LogSys.m_file_logs_enabled = true;
}
db_categories.emplace_back(c.log_category_id);
}
// Auto inject categories that don't exist in the database...
for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) {
bool is_missing_in_database = std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end();
bool is_deprecated_category = Strings::Contains(fmt::format("{}", Logs::LogCategoryName[i]), "Deprecated");
if (!is_missing_in_database && is_deprecated_category) {
LogInfo(
"Logging category [{}] ({}) is now deprecated, deleting from database",
Logs::LogCategoryName[i],
i
);
LogsysCategoriesRepository::DeleteOne(*m_database, i);
}
if (is_missing_in_database && !is_deprecated_category) {
LogInfo(
"Automatically adding new log category [{}] ({})",
Logs::LogCategoryName[i],
i
);
auto new_category = LogsysCategoriesRepository::NewEntity();
new_category.log_category_id = i;
new_category.log_category_description = Strings::Escape(Logs::LogCategoryName[i]);
new_category.log_to_console = log_settings[i].log_to_console;
new_category.log_to_gmsay = log_settings[i].log_to_gmsay;
new_category.log_to_file = log_settings[i].log_to_file;
new_category.log_to_discord = log_settings[i].log_to_discord;
LogsysCategoriesRepository::InsertOne(*m_database, new_category);
}
}
LogInfo("Loaded [{}] log categories", categories.size());
auto webhooks = DiscordWebhooksRepository::GetWhere(*m_database, fmt::format("id < {}", MAX_DISCORD_WEBHOOK_ID));
if (!webhooks.empty()) {
for (auto &w: webhooks) {
m_discord_webhooks[w.id] = {w.id, w.webhook_name, w.webhook_url};
}
LogInfo("Loaded [{}] Discord webhooks", webhooks.size());
}
return this;
}
EQEmuLogSys *EQEmuLogSys::SetDatabase(Database *db)
{
m_database = db;
return this;
}
void EQEmuLogSys::InjectTablesIfNotExist()
{
// do not run injections for zone as its unnecessary hits every time a zone boots
// other processes less frequently ran can pick up injection
if (m_log_platform == EQEmuExePlatform::ExePlatformZone) {
return;
}
// inject discord_webhooks
if (!m_database->DoesTableExist("discord_webhooks")) {
LogInfo("Creating table [discord_webhooks]");
m_database->QueryDatabase(
SQL(
CREATE TABLE discord_webhooks
(
id INT auto_increment primary key NULL,
webhook_name varchar(100) NULL,
webhook_url varchar(255) NULL,
created_at DATETIME NULL,
deleted_at DATETIME NULL
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;
)
);
}
// inject logsys_categories
if (!m_database->DoesTableExist("logsys_categories")) {
LogInfo("Creating table [logsys_categories]");
m_database->QueryDatabase(
SQL(
CREATE TABLE `logsys_categories` (
`log_category_id` int(11) NOT NULL,
`log_category_description` varchar(150) DEFAULT NULL,
`log_to_console` smallint(11) DEFAULT 0,
`log_to_file` smallint(11) DEFAULT 0,
`log_to_gmsay` smallint(11) DEFAULT 0,
`log_to_discord` smallint(11) DEFAULT 0,
`discord_webhook_id` int(11) DEFAULT 0,
PRIMARY KEY (`log_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
)
);
}
}
const EQEmuLogSys::DiscordWebhooks *EQEmuLogSys::GetDiscordWebhooks() const
{
return m_discord_webhooks;
}
EQEmuLogSys::LogEnabled EQEmuLogSys::GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
auto e = LogEnabled{};
e.log_to_console_enabled = log_settings[log_category].log_to_console > 0 &&
log_settings[log_category].log_to_console >= debug_level;
e.log_to_file_enabled = log_settings[log_category].log_to_file > 0 &&
log_settings[log_category].log_to_file >= debug_level;
e.log_to_gmsay_enabled = log_settings[log_category].log_to_gmsay > 0 &&
log_settings[log_category].log_to_gmsay >= debug_level &&
log_category != Logs::LogCategory::Netcode &&
(EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld);
e.log_to_discord_enabled = EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone &&
log_settings[log_category].log_to_discord > 0 &&
log_settings[log_category].log_to_discord >= debug_level &&
log_settings[log_category].discord_webhook_id > 0 &&
log_settings[log_category].discord_webhook_id < MAX_DISCORD_WEBHOOK_ID;
e.log_enabled =
e.log_to_console_enabled || e.log_to_file_enabled || e.log_to_gmsay_enabled || e.log_to_discord_enabled;
return e;
}
bool EQEmuLogSys::IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
return GetLogsEnabled(debug_level, log_category).log_enabled;
}
const std::string &EQEmuLogSys::GetLogPath() const
{
return m_log_path;
}
EQEmuLogSys *EQEmuLogSys::SetLogPath(const std::string &log_path)
{
EQEmuLogSys::m_log_path = log_path;
return this;
}
+93 -117
View File
@@ -23,9 +23,8 @@
#include <iostream>
#include <fstream>
#include <cstdio>
#include <stdio.h>
#include <functional>
#include <algorithm>
#ifdef _WIN32
#ifdef utf16_to_utf8
@@ -38,9 +37,9 @@
namespace Logs {
enum DebugLevel {
General = 1, // 1 - Low-Level general debugging, useful info on single line
Moderate, // 2 - Informational based, used in functions, when particular things load
Detail // 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication
General = 1, /* 1 - Low-Level general debugging, useful info on single line */
Moderate, /* 2 - Informational based, used in functions, when particular things load */
Detail /* 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication */
};
/**
@@ -54,7 +53,7 @@ namespace Logs {
AI,
Aggro,
Attack,
DeprecatedCS,
PacketClientServer,
Combat,
Commands,
Crash,
@@ -88,10 +87,10 @@ namespace Logs {
MySQLQuery,
Mercenaries,
QuestDebug,
DeprecatedSC,
DeprecatedCSU,
DeprecatedSCD,
DeprecatedCSD,
PacketServerClient,
PacketClientServerUnhandled,
PacketServerClientWithDump,
PacketClientServerWithDump,
Loginserver,
ClientLogin,
HeadlessClient,
@@ -122,34 +121,19 @@ namespace Logs {
Expeditions,
DynamicZones,
Scheduler,
Cheat,
ClientList,
DiaWind,
HTTP,
Saylink,
ChecksumVerification,
CombatRecord,
Hate,
Discord,
Faction,
PacketServerClient,
PacketClientServer,
PacketServerToServer,
Bugs,
QuestErrors,
MaxCategoryID /* Don't Remove this */
};
/**
* If you add to this, make sure you update LogCategory
*/
static const char *LogCategoryName[LogCategory::MaxCategoryID] = {
static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
"",
"AA",
"AI",
"Aggro",
"Attack",
"Deprecated",
"Packet :: Client -> Server",
"Combat",
"Commands",
"Crash",
@@ -183,10 +167,10 @@ namespace Logs {
"MySQL Query",
"Mercenaries",
"Quest Debug",
"Deprecated",
"Deprecated",
"Deprecated",
"Deprecated",
"Packet :: Server -> Client",
"Packet :: Client -> Server Unhandled",
"Packet :: Server -> Client (Dump)",
"Packet :: Client -> Server (Dump)",
"Login Server",
"Client Login",
"Headless Client",
@@ -217,30 +201,11 @@ namespace Logs {
"Expeditions",
"DynamicZones",
"Scheduler",
"Cheat",
"ClientList",
"DialogueWindow",
"HTTP",
"Saylink",
"ChecksumVerification",
"CombatRecord",
"Hate",
"Discord",
"Faction",
"Packet-S->C",
"Packet-C->S",
"Packet-S->S",
"Bugs",
"QuestErrors"
};
}
#include "eqemu_logsys_log_aliases.h"
class Database;
constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300;
class EQEmuLogSys {
public:
EQEmuLogSys();
@@ -251,8 +216,7 @@ public:
* This should be handled on deconstructor but to be safe we use it anyways.
*/
void CloseFileLogs();
EQEmuLogSys *LoadLogSettingsDefaults();
EQEmuLogSys *LoadLogDatabaseSettings();
void LoadLogSettingsDefaults();
/**
* @param directory_name
@@ -282,7 +246,7 @@ public:
* Used in file logs to prepend a timestamp entry for logs
* @param time_stamp
*/
void SetCurrentTimeStamp(char *time_stamp);
void SetCurrentTimeStamp(char* time_stamp);
/**
* @param log_name
@@ -303,96 +267,108 @@ public:
uint8 log_to_file;
uint8 log_to_console;
uint8 log_to_gmsay;
uint8 log_to_discord;
int discord_webhook_id;
uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */
};
struct OriginationInfo {
std::string zone_short_name;
std::string zone_long_name;
int instance_id;
};
OriginationInfo origination_info{};
/**
* Internally used memory reference for all log settings per category
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
* Database loaded via LogSys.SetDatabase(&database)->LoadLogDatabaseSettings();
* Database loaded via Database::LoadLogSettings(log_settings)
*/
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
struct LogEnabled {
bool log_to_file_enabled;
bool log_to_console_enabled;
bool log_to_gmsay_enabled;
bool log_to_discord_enabled;
bool log_enabled;
};
bool file_logs_enabled = false;
LogEnabled GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
bool IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
/**
* Sets Executable platform (Zone/World/UCS) etc.
*/
int log_platform = 0;
struct DiscordWebhooks {
int id;
std::string webhook_name;
std::string webhook_url;
};
/**
* File name used in writing logs
*/
std::string platform_file_name;
const DiscordWebhooks *GetDiscordWebhooks() const;
// gmsay
/**
* GMSay Client Message colors mapped by category
*
* @param log_category
* @return
*/
uint16 GetGMSayColorFromCategory(uint16 log_category);
EQEmuLogSys *SetGMSayHandler(std::function<void(uint16 log_type, const std::string &)> f)
{
m_on_log_gmsay_hook = f;
return this;
}
/**
* @param f
*/
void SetGMSayHandler(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
EQEmuLogSys *SetDiscordHandler(std::function<void(uint16 log_category, int webhook_id, const std::string &)> f)
{
m_on_log_discord_hook = f;
return this;
}
/**
* @param f
*/
void SetConsoleHandler(std::function<void(uint16 debug_level, uint16 log_type, const std::string&)> f) { on_log_console_hook = f; }
// console
void SetConsoleHandler(
std::function<void(
uint16 log_type,
const std::string &
)> f
) { m_on_log_console_hook = f; }
/**
* Silence console logging
*/
void SilenceConsoleLogging();
/**
* Turn on all console logging
*/
void EnableConsoleLogging();
// database
EQEmuLogSys *SetDatabase(Database *db);
[[nodiscard]] const std::string &GetLogPath() const;
EQEmuLogSys * SetLogPath(const std::string &log_path);
private:
// reference to database
Database *m_database;
std::function<void(uint16 log_category, const std::string &)> m_on_log_gmsay_hook;
std::function<void(uint16 log_category, int webhook_id, const std::string &)> m_on_log_discord_hook;
std::function<void(uint16 log_category, const std::string &)> m_on_log_console_hook;
DiscordWebhooks m_discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{};
bool m_file_logs_enabled = false;
int m_log_platform = 0;
std::string m_platform_file_name;
std::string m_log_path;
/**
* Callback pointer to zone process for hooking logs to zone using GMSay
*/
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook;
std::function<void(uint16 debug_level, uint16 log_category, const std::string&)> on_log_console_hook;
/**
* Formats log messages like '[Category] This is a log message'
*/
std::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
/**
* Linux console color messages mapped by category
*
* @param log_category
* @return
*/
std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
/**
* Windows console color messages mapped by category
*/
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
void ProcessConsoleMessage(uint16 log_category, const std::string &message);
void ProcessLogWrite(uint16 log_category, const std::string &message);
/**
* @param debug_level
* @param log_category
* @param message
*/
void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message);
/**
* @param debug_level
* @param log_category
* @param message
*/
void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
/**
* @param debug_level
* @param log_category
* @param message
*/
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
/**
* @param log_category
* @return
*/
bool IsRfc5424LogCategory(uint16 log_category);
void InjectTablesIfNotExist();
};
extern EQEmuLogSys LogSys;
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,14 +1,14 @@
#pragma once
#include <any>
#include <functional>
#include <exception>
#include "event_loop.h"
#include "../any.h"
namespace EQ {
class Task
{
public:
typedef std::function<void(const std::any&)> ResolveFn;
typedef std::function<void(const EQ::Any&)> ResolveFn;
typedef std::function<void(const std::exception&)> RejectFn;
typedef std::function<void()> FinallyFn;
typedef std::function<void(ResolveFn, RejectFn)> TaskFn;
@@ -19,7 +19,7 @@ namespace EQ {
RejectFn on_catch;
FinallyFn on_finally;
bool has_result;
std::any result;
EQ::Any result;
bool has_error;
std::exception error;
};
@@ -63,7 +63,7 @@ namespace EQ {
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
TaskBaton *baton = (TaskBaton*)req->data;
baton->fn([baton](const std::any& result) {
baton->fn([baton](const EQ::Any& result) {
baton->has_error = false;
baton->has_result = true;
baton->result = result;
+2 -2
View File
@@ -60,8 +60,8 @@ namespace EQ
}
template<typename Fn, typename... Args>
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::invoke_result<Fn, Args...>::type> {
using return_type = typename std::invoke_result<Fn, Args...>::type;
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
using return_type = typename std::result_of<Fn(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
+23
View File
@@ -0,0 +1,23 @@
#include "expedition_base.h"
#include "repositories/expeditions_repository.h"
ExpeditionBase::ExpeditionBase(uint32_t id, const std::string& uuid,
const std::string& expedition_name, const DynamicZoneMember& leader
) :
m_id(id),
m_uuid(uuid),
m_expedition_name(expedition_name),
m_leader(leader)
{
}
void ExpeditionBase::LoadRepositoryResult(ExpeditionsRepository::ExpeditionWithLeader&& entry)
{
m_id = entry.id;
m_uuid = std::move(entry.uuid);
m_expedition_name = std::move(entry.expedition_name);
m_add_replay_on_join = entry.add_replay_on_join;
m_is_locked = entry.is_locked;
m_leader.id = entry.leader_id;
m_leader.name = std::move(entry.leader_name);
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef COMMON_EXPEDITION_BASE_H
#define COMMON_EXPEDITION_BASE_H
#include "dynamic_zone_base.h"
#include "repositories/expeditions_repository.h"
#include <cstdint>
#include <string>
class ExpeditionBase
{
public:
virtual ~ExpeditionBase() = default;
ExpeditionBase(const ExpeditionBase&) = default;
ExpeditionBase(ExpeditionBase&&) = default;
ExpeditionBase& operator=(const ExpeditionBase&) = default;
ExpeditionBase& operator=(ExpeditionBase&&) = default;
uint32_t GetID() const { return m_id; }
uint32_t GetLeaderID() const { return m_leader.id; }
const std::string& GetName() const { return m_expedition_name; }
const std::string& GetLeaderName() const { return m_leader.name; }
const std::string& GetUUID() const { return m_uuid; }
const DynamicZoneMember& GetLeader() const { return m_leader; }
void LoadRepositoryResult(ExpeditionsRepository::ExpeditionWithLeader&& entry);
protected:
ExpeditionBase() = default;
ExpeditionBase(uint32_t id, const std::string& uuid, const std::string& expedition_name,
const DynamicZoneMember& leader);
uint32_t m_id = 0;
bool m_is_locked = false;
bool m_add_replay_on_join = true;
std::string m_uuid;
std::string m_expedition_name;
DynamicZoneMember m_leader;
};
#endif
+1 -1
View File
@@ -19,7 +19,7 @@
*/
#include "expedition_lockout_timer.h"
#include "../common/strings.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/util/uuid.h"
#include <fmt/format.h>
+24 -24
View File
@@ -20,31 +20,31 @@
#include "races.h"
#include "rulesys.h"
const char *FactionValueToString(FACTION_VALUE faction_value)
const char *FactionValueToString(FACTION_VALUE fv)
{
switch (faction_value) {
switch (fv) {
case FACTION_ALLY:
return "Ally";
return ("Ally");
case FACTION_WARMLY:
return "Warmly";
return ("Warmly");
case FACTION_KINDLY:
return "Kindly";
case FACTION_AMIABLY:
return "Amiably";
case FACTION_INDIFFERENTLY:
return "Indifferently";
case FACTION_APPREHENSIVELY:
return "Apprehensively";
case FACTION_DUBIOUSLY:
return "Dubiously";
case FACTION_THREATENINGLY:
return "Threateningly";
return ("Kindly");
case FACTION_AMIABLE:
return ("Amiable");
case FACTION_INDIFFERENT:
return ("Indifferent");
case FACTION_APPREHENSIVE:
return ("Apprehensive");
case FACTION_DUBIOUS:
return ("Dubious");
case FACTION_THREATENLY:
return ("Threatenly");
case FACTION_SCOWLS:
return "Scowls";
return ("Scowls, ready to attack.");
default:
break;
}
return "Unknown";
return ("Unknown Faction Con");
}
@@ -70,19 +70,19 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
return FACTION_KINDLY;
}
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) {
return FACTION_AMIABLY;
return FACTION_AMIABLE;
}
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) {
return FACTION_INDIFFERENTLY;
return FACTION_INDIFFERENT;
}
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) {
return FACTION_APPREHENSIVELY;
return FACTION_APPREHENSIVE;
}
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) {
return FACTION_DUBIOUSLY;
return FACTION_DUBIOUS;
}
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) {
return FACTION_THREATENINGLY;
return FACTION_THREATENLY;
}
return FACTION_SCOWLS;
}
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
// TODO: add more values
switch (r1) {
case DARK_ELF:
if (r2 == RACE_NERIAK_CITIZEN_77) {
if (r2 == 77) {
return true;
}
break;
case BARBARIAN:
if (r2 == RACE_HALAS_CITIZEN_90) {
if (r2 == 90) {
return true;
}
}
+10 -27
View File
@@ -27,13 +27,13 @@ enum FACTION_VALUE {
FACTION_ALLY = 1,
FACTION_WARMLY = 2,
FACTION_KINDLY = 3,
FACTION_AMIABLY = 4,
FACTION_AMIABLE = 4,
FACTION_INDIFFERENTLY = 5,
FACTION_INDIFFERENT = 5,
FACTION_APPREHENSIVELY = 6,
FACTION_DUBIOUSLY = 7,
FACTION_THREATENINGLY = 8,
FACTION_APPREHENSIVE = 6,
FACTION_DUBIOUS = 7,
FACTION_THREATENLY = 8,
FACTION_SCOWLS = 9
};
@@ -50,8 +50,8 @@ struct NPCFactionList {
struct FactionMods
{
int32 base;
int16 min; // The lowest your personal earned faction can go - before race/class/deity adjustments.
int16 max; // The highest your personal earned faction can go - before race/class/deity adjustments.
int16 min; // The lowest your personal earned faction can go - before race/class/diety adjustments.
int16 max; // The highest your personal earned faction can go - before race/class/diety adjustments.
int32 class_mod;
int32 race_mod;
int32 deity_mod;
@@ -61,8 +61,8 @@ struct Faction {
int32 id;
std::map<std::string, int16> mods;
int16 base;
int16 min; // The lowest your personal earned faction can go - before race/class/deity adjustments.
int16 max; // The highest your personal earned faction can go - before race/class/deity adjustments.
int16 min; // The lowest your personal earned faction can go - before race/class/diety adjustments.
int16 max; // The highest your personal earned faction can go - before race/class/diety adjustments.
char name[50];
};
@@ -75,23 +75,6 @@ struct NPCFaction
uint8 temp;
};
// Faction Associations give a much more live like faction system
// Basically the primary faction and magnitude of a faction hit will generate the rest of them
// Largest faction I could find quickly was Lord Inquisitor Seru with 9 total hits (8 associations) so 8 + 2 for max for now
#define MAX_FACTION_ASSOC 10
// this is the ID of a faction association and it's multiplier
struct FactionAssociationHit {
int id;
float multiplier;
};
struct FactionAssociations {
// maybe there should be more data here, fine for now
FactionAssociationHit hits[MAX_FACTION_ASSOC];
};
const char *FactionValueToString(FACTION_VALUE faction_value);
const char *FactionValueToString(FACTION_VALUE fv);
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
#endif
+1 -1
View File
@@ -204,7 +204,7 @@ enum { //some random constants
#define MIN_LEVEL_ALCHEMY 25
//chance ratio that a
#define THREATENINGLY_AGGRO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
#define THREATENLY_ARRGO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
//max factions per npc faction list
#define MAX_NPC_FACTIONS 20
+18 -33
View File
@@ -19,7 +19,7 @@
*/
#include <fstream>
#include "file.h"
#include "file_util.h"
#ifdef _WINDOWS
#include <direct.h>
@@ -35,48 +35,33 @@
#endif
#include <fmt/format.h>
#include <filesystem>
namespace fs = std::filesystem;
/**
* @param name
* @return
*/
bool File::Exists(const std::string &name)
bool FileUtil::exists(const std::string &name)
{
return fs::exists(fs::path{name});
std::ifstream f(name.c_str());
return f.good();
}
/**
* @param directory_name
*/
void File::Makedir(const std::string &directory_name)
void FileUtil::mkdir(const std::string& directory_name)
{
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
}
std::string File::FindEqemuConfigPath()
{
if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) {
return File::GetCwd();
#ifdef _WINDOWS
struct _stat st;
if (_stat(directory_name.c_str(), &st) == 0) // exists
return;
_mkdir(directory_name.c_str());
#else
struct stat st{};
if (stat(directory_name.c_str(), &st) == 0) { // exists
return;
}
else if (File::Exists(fs::path{File::GetCwd() + "/../eqemu_config.json"}.string())) {
return canonical(fs::path{File::GetCwd() + "/../"}).string();
}
else if (File::Exists(fs::path{File::GetCwd() + "/login.json"}.string())) {
return File::GetCwd();
}
else if (File::Exists(fs::path{File::GetCwd() + "/../login.json"}.string())) {
return canonical(fs::path{File::GetCwd() + "/../"}).string();
}
return {};
}
std::string File::GetCwd()
{
return fs::current_path().string();
}
::mkdir(directory_name.c_str(), 0755);
#endif
}
+6 -12
View File
@@ -18,21 +18,15 @@
*
*/
#ifndef EQEMU_FILE_H
#define EQEMU_FILE_H
#ifndef EQEMU_FILE_UTIL_H
#define EQEMU_FILE_UTIL_H
#include <filesystem>
namespace fs = std::filesystem;
class File {
class FileUtil {
public:
static bool Exists(const std::string &name);
static void Makedir(const std::string& directory_name);
static std::string FindEqemuConfigPath();
static std::string GetCwd();
static bool exists(const std::string &name);
static void mkdir(const std::string& directory_name);
};
bool Exists(const std::string& name);
#endif //EQEMU_FILE_H
#endif //EQEMU_FILE_UTIL_H
+7 -67
View File
@@ -20,7 +20,7 @@
#include "database.h"
//#include "misc_functions.h"
#include "strings.h"
#include "string_util.h"
#include <cstdlib>
#include <cstring>
@@ -63,7 +63,7 @@ bool BaseGuildManager::LoadGuilds() {
for (auto row=results.begin();row!=results.end();++row)
_CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]);
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
query = "SELECT guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
results = m_db->QueryDatabase(query);
if (!results.Success())
@@ -131,7 +131,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
info = _CreateGuild(guild_id, row[0], atoi(row[1]), atoi(row[2]), row[3], row[4], row[5], row[6]);
query = StringFormat("SELECT guild_id, `rank`, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
query = StringFormat("SELECT guild_id, rank, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
"FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id);
results = m_db->QueryDatabase(query);
@@ -268,7 +268,7 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length());
query = StringFormat("INSERT INTO guild_ranks "
"(guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)"
"(guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)"
" VALUES(%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d)",
guild_id, rank, title_esc,
rankInfo.permissions[GUILD_HEAR],
@@ -738,7 +738,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
std::string query;
if(guild_id != GUILD_NONE) {
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,`rank`,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
auto results = m_db->QueryDatabase(query);
if (!results.Success()) {
@@ -758,7 +758,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
}
bool BaseGuildManager::DBSetGuildRank(uint32 charid, uint8 rank) {
std::string query = StringFormat("UPDATE guild_members SET `rank`=%d WHERE char_id=%d", rank, charid);
std::string query = StringFormat("UPDATE guild_members SET rank=%d WHERE char_id=%d", rank, charid);
return(QueryWithLogging(query, "setting a guild member's rank"));
}
@@ -1208,7 +1208,7 @@ BaseGuildManager::RankInfo::RankInfo() {
BaseGuildManager::GuildInfo::GuildInfo() {
leader_char_id = 0;
minstatus = AccountStatus::Player;
minstatus = 0;
}
uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
@@ -1225,66 +1225,6 @@ uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
return results.RowCount();
}
std::string BaseGuildManager::GetGuildNameByID(uint32 guild_id) const {
if(guild_id == GUILD_NONE) {
return std::string();
}
std::map<uint32, GuildInfo *>::const_iterator res;
res = m_guilds.find(guild_id);
if(res == m_guilds.end()) {
return "Invalid Guild";
}
return res->second->name;
}
std::string BaseGuildManager::GetGuildRankName(uint32 guild_id, uint8 rank) const
{
if(rank > GUILD_MAX_RANK) {
return "Invalid Rank";
}
std::map<uint32, GuildInfo *>::const_iterator res;
res = m_guilds.find(guild_id);
if(res == m_guilds.end()) {
return "Invalid Guild Rank";
}
return res->second->ranks[rank].name;
}
uint32 BaseGuildManager::GetGuildIDByCharacterID(uint32 character_id)
{
if(!m_db) {
return GUILD_NONE;
}
std::string query = fmt::format(
"SELECT `guild_id` FROM `guild_members` WHERE char_id = {} LIMIT 1",
character_id
);
auto results = m_db->QueryDatabase(query);
if(!results.Success() || !results.RowCount()) {
return GUILD_NONE;
}
auto row = results.begin();
auto guild_id = std::stoul(row[0]);
return guild_id;
}
bool BaseGuildManager::IsCharacterInGuild(uint32 character_id, uint32 guild_id)
{
auto current_guild_id = GetGuildIDByCharacterID(character_id);
if (current_guild_id == GUILD_NONE) {
return false;
}
if (guild_id && current_guild_id != guild_id) {
return false;
}
return true;
}
-4
View File
@@ -76,12 +76,8 @@ class BaseGuildManager
bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const;
const char *GetRankName(uint32 guild_id, uint8 rank) const;
const char *GetGuildName(uint32 guild_id) const;
std::string GetGuildNameByID(uint32 guild_id) const;
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
bool GetGuildNameByID(uint32 guild_id, std::string &into) const;
uint32 GetGuildIDByName(const char *GuildName);
uint32 GetGuildIDByCharacterID(uint32 character_id);
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
+1747 -7439
View File
File diff suppressed because it is too large Load Diff
-633
View File
@@ -1,633 +0,0 @@
// Copyright (C) 2015 Ben Lewis <benjf5+github@gmail.com>
// Licensed under the MIT license.
// https://github.com/ben-zen/uri-library
#pragma once
#include <cctype>
#include <map>
#include <string>
#include <stdexcept>
#include <utility>
class uri {
/* URIs are broadly divided into two categories: hierarchical and
* non-hierarchical. Both hierarchical URIs and non-hierarchical URIs have a
* few elements in common; all URIs have a scheme of one or more alphanumeric
* characters followed by a colon, and they all may optionally have a query
* component preceded by a question mark, and a fragment component preceded by
* an octothorpe (hash mark: '#'). The query consists of stanzas separated by
* either ampersands ('&') or semicolons (';') (but only one or the other),
* and each stanza consists of a key and an optional value; if the value
* exists, the key and value must be divided by an equals sign.
*
* The following is an example from Wikipedia of a hierarchical URI:
* scheme:[//[user:password@]domain[:port]][/]path[?query][#fragment]
*/
public:
enum class scheme_category {
Hierarchical,
NonHierarchical
};
enum class component {
Scheme,
Content,
Username,
Password,
Host,
Port,
Path,
Query,
Fragment
};
enum class query_argument_separator {
ampersand,
semicolon
};
uri(
char const *uri_text, scheme_category category = scheme_category::Hierarchical,
query_argument_separator separator = query_argument_separator::ampersand
) :
m_category(category),
m_path_is_rooted(false),
m_port(0),
m_separator(separator)
{
setup(std::string(uri_text), category);
};
uri(
std::string const &uri_text, scheme_category category = scheme_category::Hierarchical,
query_argument_separator separator = query_argument_separator::ampersand
) :
m_category(category),
m_path_is_rooted(false),
m_port(0),
m_separator(separator)
{
setup(uri_text, category);
};
uri(
std::map<component, std::string> const &components,
scheme_category category,
bool rooted_path,
query_argument_separator separator = query_argument_separator::ampersand
) :
m_category(category),
m_path_is_rooted(rooted_path),
m_separator(separator)
{
if (components.count(component::Scheme)) {
if (components.at(component::Scheme).length() == 0) {
throw std::invalid_argument("Scheme cannot be empty.");
}
m_scheme = components.at(component::Scheme);
}
else {
throw std::invalid_argument("A URI must have a scheme.");
}
if (category == scheme_category::Hierarchical) {
if (components.count(component::Content)) {
throw std::invalid_argument("The content component is only for use in non-hierarchical URIs.");
}
bool has_username = components.count(component::Username);
bool has_password = components.count(component::Password);
if (has_username && has_password) {
m_username = components.at(component::Username);
m_password = components.at(component::Password);
}
else if ((has_username && !has_password) || (!has_username && has_password)) {
throw std::invalid_argument("If a username or password is supplied, both must be provided.");
}
if (components.count(component::Host)) {
m_host = components.at(component::Host);
}
if (components.count(component::Port)) {
m_port = std::stoul(components.at(component::Port));
}
if (components.count(component::Path)) {
m_path = components.at(component::Path);
}
else {
throw std::invalid_argument("A path is required on a hierarchical URI, even an empty path.");
}
}
else {
if (components.count(component::Username)
|| components.count(component::Password)
|| components.count(component::Host)
|| components.count(component::Port)
|| components.count(component::Path)) {
throw std::invalid_argument("None of the hierarchical components are allowed in a non-hierarchical URI.");
}
if (components.count(component::Content)) {
m_content = components.at(component::Content);
}
else {
throw std::invalid_argument(
"Content is a required component for a non-hierarchical URI, even an empty string."
);
}
}
if (components.count(component::Query)) {
m_query = components.at(component::Query);
}
if (components.count(component::Fragment)) {
m_fragment = components.at(component::Fragment);
}
}
uri(uri const &other, std::map<component, std::string> const &replacements) :
m_category(other.m_category),
m_path_is_rooted(other.m_path_is_rooted),
m_separator(other.m_separator)
{
m_scheme = (replacements.count(component::Scheme))
? replacements.at(component::Scheme) : other.m_scheme;
if (m_category == scheme_category::Hierarchical) {
m_username = (replacements.count(component::Username))
? replacements.at(component::Username) : other.m_username;
m_password = (replacements.count(component::Password))
? replacements.at(component::Password) : other.m_password;
m_host = (replacements.count(component::Host))
? replacements.at(component::Host) : other.m_host;
m_port = (replacements.count(component::Port))
? std::stoul(replacements.at(component::Port)) : other.m_port;
m_path = (replacements.count(component::Path))
? replacements.at(component::Path) : other.m_path;
}
else {
m_content = (replacements.count(component::Content))
? replacements.at(component::Content) : other.m_content;
}
m_query = (replacements.count(component::Query))
? replacements.at(component::Query) : other.m_query;
m_fragment = (replacements.count(component::Fragment))
? replacements.at(component::Fragment) : other.m_fragment;
}
// Copy constructor; just use the copy assignment operator internally.
uri(uri const &other)
{
*this = other;
};
// Copy assignment operator
uri &operator=(uri const &other)
{
if (this != &other) {
m_scheme = other.m_scheme;
m_content = other.m_content;
m_username = other.m_username;
m_password = other.m_password;
m_host = other.m_host;
m_path = other.m_path;
m_query = other.m_query;
m_fragment = other.m_fragment;
m_query_dict = other.m_query_dict;
m_category = other.m_category;
m_port = other.m_port;
m_path_is_rooted = other.m_path_is_rooted;
m_separator = other.m_separator;
}
return *this;
}
~uri() {};
std::string const &get_scheme() const
{
return m_scheme;
};
scheme_category get_scheme_category() const
{
return m_category;
};
std::string const &get_content() const
{
if (m_category != scheme_category::NonHierarchical) {
throw std::domain_error("The content component is only valid for non-hierarchical URIs.");
}
return m_content;
};
std::string const &get_username() const
{
if (m_category != scheme_category::Hierarchical) {
throw std::domain_error("The username component is only valid for hierarchical URIs.");
}
return m_username;
};
std::string const &get_password() const
{
if (m_category != scheme_category::Hierarchical) {
throw std::domain_error("The password component is only valid for hierarchical URIs.");
}
return m_password;
};
std::string const &get_host() const
{
if (m_category != scheme_category::Hierarchical) {
throw std::domain_error("The host component is only valid for hierarchical URIs.");
}
return m_host;
};
unsigned long get_port() const
{
if (m_category != scheme_category::Hierarchical) {
throw std::domain_error("The port component is only valid for hierarchical URIs.");
}
return m_port;
};
std::string const &get_path() const
{
if (m_category != scheme_category::Hierarchical) {
throw std::domain_error("The path component is only valid for hierarchical URIs.");
}
return m_path;
};
std::string const &get_query() const
{
return m_query;
};
std::map<std::string, std::string> const &get_query_dictionary() const
{
return m_query_dict;
};
std::string const &get_fragment() const
{
return m_fragment;
};
std::string to_string() const
{
std::string full_uri;
full_uri.append(m_scheme);
full_uri.append(":");
if (m_content.length() > m_path.length()) {
full_uri.append("//");
if (!(m_username.empty() || m_password.empty())) {
full_uri.append(m_username);
full_uri.append(":");
full_uri.append(m_password);
full_uri.append("@");
}
full_uri.append(m_host);
if (m_port != 0) {
full_uri.append(":");
full_uri.append(std::to_string(m_port));
}
}
if (m_path_is_rooted) {
full_uri.append("/");
}
full_uri.append(m_path);
if (!m_query.empty()) {
full_uri.append("?");
full_uri.append(m_query);
}
if (!m_fragment.empty()) {
full_uri.append("#");
full_uri.append(m_fragment);
}
return full_uri;
};
private:
void setup(std::string const &uri_text, scheme_category category)
{
size_t const uri_length = uri_text.length();
if (uri_length == 0) {
throw std::invalid_argument("URIs cannot be of zero length.");
}
std::string::const_iterator cursor = parse_scheme(
uri_text,
uri_text.begin());
// After calling parse_scheme, *cursor == ':'; none of the following parsers
// expect a separator character, so we advance the cursor upon calling them.
cursor = parse_content(uri_text, (cursor + 1));
if ((cursor != uri_text.end()) && (*cursor == '?')) {
cursor = parse_query(uri_text, (cursor + 1));
}
if ((cursor != uri_text.end()) && (*cursor == '#')) {
cursor = parse_fragment(uri_text, (cursor + 1));
}
init_query_dictionary(); // If the query string is empty, this will be empty too.
};
std::string::const_iterator parse_scheme(
std::string const &uri_text,
std::string::const_iterator scheme_start
)
{
std::string::const_iterator scheme_end = scheme_start;
while ((scheme_end != uri_text.end()) && (*scheme_end != ':')) {
if (!(std::isalnum(*scheme_end) || (*scheme_end == '-')
|| (*scheme_end == '+') || (*scheme_end == '.'))) {
throw std::invalid_argument(
"Invalid character found in the scheme component. Supplied URI was: \""
+ uri_text + "\"."
);
}
++scheme_end;
}
if (scheme_end == uri_text.end()) {
throw std::invalid_argument(
"End of URI found while parsing the scheme. Supplied URI was: \""
+ uri_text + "\"."
);
}
if (scheme_start == scheme_end) {
throw std::invalid_argument(
"Scheme component cannot be zero-length. Supplied URI was: \""
+ uri_text + "\"."
);
}
m_scheme = std::move(std::string(scheme_start, scheme_end));
return scheme_end;
};
std::string::const_iterator parse_content(
std::string const &uri_text,
std::string::const_iterator content_start
)
{
std::string::const_iterator content_end = content_start;
while ((content_end != uri_text.end()) && (*content_end != '?') && (*content_end != '#')) {
++content_end;
}
m_content = std::move(std::string(content_start, content_end));
if ((m_category == scheme_category::Hierarchical) && (m_content.length() > 0)) {
// If it's a hierarchical URI, the content should be parsed for the hierarchical components.
std::string::const_iterator path_start = m_content.begin();
std::string::const_iterator path_end = m_content.end();
if (!m_content.compare(0, 2, "//")) {
// In this case an authority component is present.
std::string::const_iterator authority_cursor = (m_content.begin() + 2);
if (m_content.find_first_of('@') != std::string::npos) {
std::string::const_iterator userpass_divider = parse_username(
uri_text,
m_content,
authority_cursor
);
authority_cursor = parse_password(uri_text, m_content, (userpass_divider + 1));
// After this call, *authority_cursor == '@', so we skip over it.
++authority_cursor;
}
authority_cursor = parse_host(uri_text, m_content, authority_cursor);
if ((authority_cursor != m_content.end()) && (*authority_cursor == ':')) {
authority_cursor = parse_port(uri_text, m_content, (authority_cursor + 1));
}
if ((authority_cursor != m_content.end()) && (*authority_cursor == '/')) {
// Then the path is rooted, and we should note this.
m_path_is_rooted = true;
path_start = authority_cursor + 1;
}
// If we've reached the end and no path is present then set path_start
// to the end.
if (authority_cursor == m_content.end()) {
path_start = m_content.end();
}
}
else if (!m_content.compare(0, 1, "/")) {
m_path_is_rooted = true;
++path_start;
}
// We can now build the path based on what remains in the content string,
// since that's all that exists after the host and optional port component.
m_path = std::move(std::string(path_start, path_end));
}
return content_end;
};
std::string::const_iterator parse_username(
std::string const &uri_text,
std::string const &content,
std::string::const_iterator username_start
)
{
std::string::const_iterator username_end = username_start;
// Since this is only reachable when '@' was in the content string, we can
// ignore the end-of-string case.
while (*username_end != ':') {
if (*username_end == '@') {
throw std::invalid_argument(
"Username must be followed by a password. Supplied URI was: \""
+ uri_text + "\"."
);
}
++username_end;
}
m_username = std::move(std::string(username_start, username_end));
return username_end;
};
std::string::const_iterator parse_password(
std::string const &uri_text,
std::string const &content,
std::string::const_iterator password_start
)
{
std::string::const_iterator password_end = password_start;
while (*password_end != '@') {
++password_end;
}
m_password = std::move(std::string(password_start, password_end));
return password_end;
};
std::string::const_iterator parse_host(
std::string const &uri_text,
std::string const &content,
std::string::const_iterator host_start
)
{
std::string::const_iterator host_end = host_start;
// So, the host can contain a few things. It can be a domain, it can be an
// IPv4 address, it can be an IPv6 address, or an IPvFuture literal. In the
// case of those last two, it's of the form [...] where what's between the
// brackets is a matter of which IPv?? version it is.
while (host_end != content.end()) {
if (*host_end == '[') {
// We're parsing an IPv6 or IPvFuture address, so we should handle that
// instead of the normal procedure.
while ((host_end != content.end()) && (*host_end != ']')) {
++host_end;
}
if (host_end == content.end()) {
throw std::invalid_argument(
"End of content component encountered "
"while parsing the host component. "
"Supplied URI was: \""
+ uri_text + "\"."
);
}
++host_end;
break;
// We can stop looping, we found the end of the IP literal, which is the
// whole of the host component when one's in use.
}
else if ((*host_end == ':') || (*host_end == '/')) {
break;
}
else {
++host_end;
}
}
m_host = std::move(std::string(host_start, host_end));
return host_end;
};
std::string::const_iterator parse_port(
std::string const &uri_text,
std::string const &content,
std::string::const_iterator port_start
)
{
std::string::const_iterator port_end = port_start;
while ((port_end != content.end()) && (*port_end != '/')) {
if (!std::isdigit(*port_end)) {
throw std::invalid_argument(
"Invalid character while parsing the port. "
"Supplied URI was: \"" + uri_text + "\"."
);
}
++port_end;
}
m_port = std::stoul(std::string(port_start, port_end));
return port_end;
};
std::string::const_iterator parse_query(
std::string const &uri_text,
std::string::const_iterator query_start
)
{
std::string::const_iterator query_end = query_start;
while ((query_end != uri_text.end()) && (*query_end != '#')) {
// Queries can contain almost any character except hash, which is reserved
// for the start of the fragment.
++query_end;
}
m_query = std::move(std::string(query_start, query_end));
return query_end;
};
std::string::const_iterator parse_fragment(
std::string const &uri_text,
std::string::const_iterator fragment_start
)
{
m_fragment = std::move(std::string(fragment_start, uri_text.end()));
return uri_text.end();
};
void init_query_dictionary()
{
if (!m_query.empty()) {
// Loop over the query string looking for '&'s, then check each one for
// an '=' to find keys and values; if there's not an '=' then the key
// will have an empty value in the map.
char separator = (m_separator == query_argument_separator::ampersand) ? '&' : ';';
size_t carat = 0;
size_t stanza_end = m_query.find_first_of(separator);
do {
std::string stanza = m_query.substr(
carat,
((stanza_end != std::string::npos) ? (stanza_end - carat) : std::string::npos));
size_t key_value_divider = stanza.find_first_of('=');
std::string key = stanza.substr(0, key_value_divider);
std::string value;
if (key_value_divider != std::string::npos) {
value = stanza.substr((key_value_divider + 1));
}
if (m_query_dict.count(key) != 0) {
throw std::invalid_argument("Bad key in the query string!");
}
m_query_dict.emplace(key, value);
carat = ((stanza_end != std::string::npos) ? (stanza_end + 1)
: std::string::npos);
stanza_end = m_query.find_first_of(separator, carat);
} while ((stanza_end != std::string::npos)
|| (carat != std::string::npos));
}
}
std::string m_scheme;
std::string m_content;
std::string m_username;
std::string m_password;
std::string m_host;
std::string m_path;
std::string m_query;
std::string m_fragment;
std::map<std::string, std::string> m_query_dict;
scheme_category m_category;
unsigned long m_port;
bool m_path_is_rooted;
query_argument_separator m_separator;
};
+11 -87
View File
@@ -25,7 +25,7 @@
//#include "races.h"
//#include "rulesys.h"
//#include "shareddb.h"
#include "strings.h"
#include "string_util.h"
#include "../common/light_source.h"
@@ -224,7 +224,7 @@ EQ::ItemInstance* EQ::InventoryProfile::GetItem(int16 slot_id, uint8 bagidx) con
return GetItem(InventoryProfile::CalcSlotId(slot_id, bagidx));
}
// Put an item into specified slot
// Put an item snto specified slot
int16 EQ::InventoryProfile::PutItem(int16 slot_id, const ItemInstance& inst)
{
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) {
@@ -245,7 +245,7 @@ int16 EQ::InventoryProfile::PutItem(int16 slot_id, const ItemInstance& inst)
if (temp_slot >= m_lookup->InventoryTypeSize.Bank)
return EQ::invslot::SLOT_INVALID;
}
// Clean up item already in slot (if exists)
DeleteItem(slot_id);
@@ -399,7 +399,7 @@ bool EQ::InventoryProfile::SwapItem(
}
// Remove item from inventory (with memory delete)
bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
bool EQ::InventoryProfile::DeleteItem(int16 slot_id, uint8 quantity) {
// Pop item out of inventory map (or queue)
ItemInstance *item_to_delete = PopItem(slot_id);
@@ -590,68 +590,6 @@ bool EQ::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quan
// Checks that user has at least 'quantity' number of items in a given inventory slot
// Returns first slot it was found in, or SLOT_INVALID if not found
bool EQ::InventoryProfile::HasAugmentEquippedByID(uint32 item_id)
{
bool has_equipped = false;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->ContainsAugmentByID(item_id)) {
has_equipped = true;
break;
}
}
return has_equipped;
}
int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id)
{
int quantity = 0;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->ContainsAugmentByID(item_id)) {
quantity += item->CountAugmentByID(item_id);
}
}
return quantity;
}
bool EQ::InventoryProfile::HasItemEquippedByID(uint32 item_id)
{
bool has_equipped = false;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->GetID() == item_id) {
has_equipped = true;
break;
}
}
return has_equipped;
}
int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id)
{
int quantity = 0;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->GetID() == item_id) {
quantity += item->IsStackable() ? item->GetCharges() : 1;
}
}
return quantity;
}
//This function has a flaw in that it only returns the last stack that it looked at
//when quantity is greater than 1 and not all of quantity can be found in 1 stack.
int16 EQ::InventoryProfile::HasItem(uint32 item_id, uint8 quantity, uint8 where)
@@ -993,7 +931,7 @@ int16 EQ::InventoryProfile::CalcSlotId(int16 slot_id) {
//else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END)
// parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE;
//else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range)
if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) {
parent_slot_id = invslot::GENERAL_BEGIN + (slot_id - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT;
}
@@ -1231,7 +1169,7 @@ uint8 EQ::InventoryProfile::FindBrightestLightType()
for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) {
if ((iter->first < invslot::EQUIPMENT_BEGIN || iter->first > invslot::EQUIPMENT_END))
continue;
if (iter->first == invslot::slotAmmo)
continue;
@@ -1369,7 +1307,7 @@ EQ::ItemInstance* EQ::InventoryProfile::_GetItem(const std::map<int16, ItemInsta
if (slot_id - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank)
return nullptr;
}
auto it = bucket.find(slot_id);
if (it != bucket.end()) {
return it->second;
@@ -1441,7 +1379,7 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
result = slot_id;
}
}
if (result == INVALID_INDEX) {
LogError("InventoryProfile::_PutItem: Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
InventoryProfile::MarkDirty(inst); // Slot not found, clean up
@@ -1478,7 +1416,7 @@ int16 EQ::InventoryProfile::_HasItem(std::map<int16, ItemInstance*>& bucket, uin
if (inst->GetAugmentItemID(index) == item_id && quantity <= 1)
return invslot::SLOT_AUGMENT_GENERIC_RETURN;
}
if (!inst->IsClassBag()) { continue; }
for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
@@ -1509,7 +1447,7 @@ int16 EQ::InventoryProfile::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint
// is sufficient. However, in cases where referential criteria is considered, this can lead
// to unintended results. Funtionality should be observed when referencing the return value
// of this query
uint32 quantity_found = 0;
for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
@@ -1715,20 +1653,6 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 lo
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
break;
}
return EQ::invslot::SLOT_INVALID;
}
std::vector<uint32> EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id)
{
std::vector<uint32> augments;
const auto* item = GetItem(slot_id);
if (item) {
for (uint8 i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
augments.push_back(item->GetAugment(i) ? item->GetAugmentItemID(i) : 0);
}
}
return augments;
}
+1 -18
View File
@@ -28,7 +28,6 @@
#include "item_instance.h"
#include <list>
#include <vector>
//FatherNitwit: location bits for searching specific
@@ -133,7 +132,7 @@ namespace EQ
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0);
// Remove item from inventory
bool DeleteItem(int16 slot_id, int16 quantity = 0);
bool DeleteItem(int16 slot_id, uint8 quantity = 0);
// Checks All items in a bag for No Drop
bool CheckNoDrop(int16 slot_id, bool recurse = true);
@@ -141,21 +140,6 @@ namespace EQ
// Remove item from inventory (and take control of memory)
ItemInstance* PopItem(int16 slot_id);
// Check if player has a specific item equipped by Item ID
bool HasItemEquippedByID(uint32 item_id);
// Check how many of a specific item the player has equipped by Item ID
int CountItemEquippedByID(uint32 item_id);
// Check if player has a specific augment equipped by Item ID
bool HasAugmentEquippedByID(uint32 item_id);
// Check how many of a specific augment the player has equipped by Item ID
int CountAugmentEquippedByID(uint32 item_id);
// Get a list of augments from a specific slot ID
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
// Check whether there is space for the specified number of the specified item.
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
@@ -206,7 +190,6 @@ namespace EQ
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value);
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value);
std::string GetCustomItemData(int16 slot_id, std::string identifier);
static const int GetItemStatValue(uint32 item_id, std::string identifier);
protected:
///////////////////////////////
// Protected Methods
+5 -5
View File
@@ -19,7 +19,7 @@
#include "inventory_slot.h"
#include "textures.h"
#include "strings.h"
#include "string_util.h"
int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index)
@@ -86,7 +86,7 @@ bool EQ::InventorySlot::IsValidSlot() const
{
if (_typeless)
return false;
int16 slot_count = invtype::GetInvTypeSize(_type_index);
if (!slot_count || _slot_index < invslot::SLOT_BEGIN || _slot_index >= slot_count)
return false;
@@ -136,7 +136,7 @@ bool EQ::InventorySlot::IsWeaponIndex(int16 slot_index)
{
if (slot_index == invslot::slotPrimary || slot_index == invslot::slotSecondary || slot_index == invslot::slotRange)
return true;
return false;
}
@@ -364,7 +364,7 @@ bool EQ::InventorySlot::operator<(const InventorySlot& rhs) const
{
if (Typeless() || rhs.Typeless())
return inventory_slot_typeless_lessthan(*this, rhs);
if (TypeIndex() < rhs.TypeIndex())
return true;
@@ -384,6 +384,6 @@ bool EQ::operator==(const InventorySlot& lhs, const InventorySlot& rhs)
{
if (lhs.Typeless() || rhs.Typeless())
return ((lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex()));
return ((lhs.TypeIndex() == rhs.TypeIndex()) && (lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex()));
}
-155
View File
@@ -18,17 +18,7 @@
*
*/
#include <cstring>
#include <fmt/format.h>
#include <csignal>
#include <vector>
#include "ip_util.h"
#include "http/httplib.h"
#include "http/uri.h"
#include "eqemu_logsys.h"
#include "event/event_loop.h"
#include "net/dns.h"
#include "event/task_scheduler.h"
/**
* @param ip
@@ -80,148 +70,3 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0")
);
}
/**
* Gets local address - pings google to inspect what interface was used locally
* @return
*/
std::string IpUtil::GetLocalIPAddress()
{
char my_ip_address[16];
unsigned int my_port;
struct sockaddr_in server_address{};
struct sockaddr_in my_address{};
int sockfd;
// Connect to server
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return "";
}
// Set server_addr
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("172.217.160.99");
server_address.sin_port = htons(80);
// Connect to server
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
close(sockfd);
return "";
}
// Get my ip address and port
memset(&my_address, 0, sizeof(my_address));
socklen_t len = sizeof(my_address);
getsockname(sockfd, (struct sockaddr *) &my_address, &len);
inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address));
my_port = ntohs(my_address.sin_port);
return fmt::format("{}", my_ip_address);
}
/**
* Gets public address
* Uses various websites as options to return raw public IP back to the client
* @return
*/
std::string IpUtil::GetPublicIPAddress()
{
std::vector<std::string> endpoints = {
"http://ifconfig.me",
"http://api.ipify.org",
"http://ipinfo.io/ip",
"http://ipecho.net/plain",
};
for (auto &s: endpoints) {
// http get request
uri u(s);
httplib::Client r(
fmt::format(
"{}://{}",
u.get_scheme(),
u.get_host()
).c_str()
);
httplib::Headers headers = {
{"Content-type", "text/plain; charset=utf-8"},
{"User-Agent", "curl/7.81.0"}
};
r.set_connection_timeout(1, 0);
r.set_read_timeout(1, 0);
r.set_write_timeout(1, 0);
if (auto res = r.Get(fmt::format("/{}", u.get_path()).c_str(), headers)) {
if (res->status == 200) {
if (res->body.find('.') != std::string::npos) {
return res->body;
}
}
}
}
return {};
}
std::string IpUtil::DNSLookupSync(const std::string &addr, int port)
{
auto task_runner = new EQ::Event::TaskScheduler();
auto res = task_runner->Enqueue(
[&]() -> std::string {
bool running = true;
std::string ret;
EQ::Net::DNSLookup(
addr, port, false, [&](const std::string &addr) {
ret = addr;
if (addr.empty()) {
ret = "";
running = false;
}
return ret;
}
);
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
auto &loop = EQ::EventLoop::Get();
while (running) {
if (!ret.empty()) {
running = false;
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() > 1500) {
LogInfo(
"[DNSLookupSync] Deadline exceeded [{}]",
1500
);
running = false;
}
loop.Process();
}
return ret;
}
);
std::string result = res.get();
safe_delete(task_runner);
return result;
}
bool IpUtil::IsIPAddress(const std::string &ip_address)
{
struct sockaddr_in sa{};
int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr));
return result != 0;
}
+1 -8
View File
@@ -30,14 +30,7 @@ public:
static uint32_t IPToUInt(const std::string &ip);
static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask);
static bool IsIpInPrivateRfc1918(const std::string &ip);
static std::string GetLocalIPAddress();
static std::string GetPublicIPAddress();
static std::string DNSLookupSync(
const std::string &addr,
int port
);
static bool IsIPAddress(const std::string &ip_address);
};
#endif //EQEMU_IP_UTIL_H
#endif //EQEMU_IP_UTIL_H
+6 -4
View File
@@ -30,7 +30,6 @@
#include "types.h"
#include "eqemu_exception.h"
#include "eqemu_config.h"
#include "path_manager.h"
namespace EQ {
struct IPCMutex::Implementation {
@@ -41,11 +40,12 @@ namespace EQ {
#endif
};
IPCMutex::IPCMutex(const std::string& name) : locked_(false) {
IPCMutex::IPCMutex(std::string name) : locked_(false) {
imp_ = new Implementation;
#ifdef _WINDOWS
auto Config = EQEmuConfig::get();
std::string final_name = fmt::format("{}/EQEmuMutex_{}", Config->SharedMemDir, name);
std::string final_name = Config->SharedMemDir + "EQEmuMutex_";
final_name += name;
imp_->mut_ = CreateMutex(nullptr,
FALSE,
@@ -55,7 +55,9 @@ namespace EQ {
EQ_EXCEPT("IPC Mutex", "Could not create mutex.");
}
#else
std::string final_name = fmt::format("{}/{}.lock", path.GetSharedMemoryPath(), name);
auto Config = EQEmuConfig::get();
std::string final_name = Config->SharedMemDir + name;
final_name += ".lock";
#ifdef __DARWIN
#if __DARWIN_C_LEVEL < 200809L
+1 -1
View File
@@ -37,7 +37,7 @@ namespace EQ {
Creates a named binary semaphore, basically a semaphore that is init S <- 1
\param name The name of this mutex.
*/
IPCMutex(const std::string& name);
IPCMutex(std::string name);
//! Destructor
~IPCMutex();
+2 -24
View File
@@ -169,33 +169,11 @@ uint8 EQ::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit)
bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const
{
if (!(Races & GetPlayerRaceBit(race_id))) {
if (!(Races & GetPlayerRaceBit(race_id)))
return false;
}
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id))))
return false;
}
return true;
}
bool EQ::ItemData::IsClassEquipable(uint16 class_id) const
{
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
return false;
}
return true;
}
bool EQ::ItemData::IsRaceEquipable(uint16 race_id) const
{
if (!(Races & GetPlayerRaceBit(race_id))) {
return false;
}
return true;
}
+10 -12
View File
@@ -370,7 +370,7 @@ namespace EQ
uint32 Slots; // Bitfield for which slots this item can be used in
uint32 Price; // Item cost (?)
uint32 Icon; // Icon Number
int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
uint32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
bool LoreFlag; // This will be true if LoreGroup is non-zero
bool PendingLoreFlag;
bool ArtifactFlag;
@@ -473,16 +473,16 @@ namespace EQ
uint32 LDoNSold;
uint32 BaneDmgRaceAmt;
uint32 AugRestrict;
int32 Endur;
int32 DotShielding;
int32 Attack;
int32 Regen;
int32 ManaRegen;
int32 EnduranceRegen;
int32 Haste;
int32 DamageShield;
uint32 Endur;
uint32 DotShielding;
uint32 Attack;
uint32 Regen;
uint32 ManaRegen;
uint32 EnduranceRegen;
uint32 Haste;
uint32 DamageShield;
uint32 RecastDelay;
int RecastType;
uint32 RecastType;
uint32 AugDistiller;
bool Attuneable;
bool NoPet;
@@ -533,8 +533,6 @@ namespace EQ
//BardName
bool IsEquipable(uint16 Race, uint16 Class) const;
bool IsClassEquipable(uint16 Class) const;
bool IsRaceEquipable(uint16 Race) const;
bool IsClassCommon() const;
bool IsClassBag() const;
bool IsClassBook() const;
+29 -114
View File
@@ -23,7 +23,7 @@
//#include "races.h"
#include "rulesys.h"
#include "shareddb.h"
#include "strings.h"
#include "string_util.h"
//#include "../common/light_source.h"
@@ -214,7 +214,7 @@ EQ::ItemInstance::~ItemInstance()
bool EQ::ItemInstance::IsType(item::ItemClass item_class) const
{
// IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr'
// Check usage type
if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag))
return true;
@@ -245,7 +245,7 @@ bool EQ::ItemInstance::IsStackable() const
{
if (!m_item)
return false;
return m_item->Stackable;
}
@@ -253,7 +253,7 @@ bool EQ::ItemInstance::IsCharged() const
{
if (!m_item)
return false;
if (m_item->MaxCharges > 1)
return true;
else
@@ -263,43 +263,20 @@ bool EQ::ItemInstance::IsCharged() const
// Can item be equipped?
bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const
{
if (!m_item || !m_item->Slots) {
if (!m_item || (m_item->Slots == 0))
return false;
}
return m_item->IsEquipable(race, class_);
}
// Can item be equipped by Class?
bool EQ::ItemInstance::IsClassEquipable(uint16 class_) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsClassEquipable(class_);
}
// Can item be equipped by Race?
bool EQ::ItemInstance::IsRaceEquipable(uint16 race) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsRaceEquipable(race);
}
// Can equip at this slot?
bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
{
if (!m_item || !m_item->Slots) {
if (!m_item)
return false;
}
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END)
return false;
}
return ((m_item->Slots & (1 << slot_id)) != 0);
}
@@ -332,30 +309,19 @@ bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
return (index <= EQ::invslot::EQUIPMENT_END);
}
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augtype) const
{
if (!m_item || !m_item->IsClassCommon()) {
if (!m_item || !m_item->IsClassCommon())
return INVALID_INDEX;
}
auto i = invaug::SOCKET_BEGIN;
for (; i <= invaug::SOCKET_END; ++i) {
if (GetItem(i)) {
continue;
}
if (
augment_type == -1 ||
(
m_item->AugSlotType[i] &&
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
)
) {
int index = invaug::SOCKET_BEGIN;
for (; index <= invaug::SOCKET_END; ++index) {
if (GetItem(index)) { continue; }
if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype)))
break;
}
}
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
return (index <= invaug::SOCKET_END) ? index : INVALID_INDEX;
}
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
@@ -415,7 +381,7 @@ EQ::ItemInstance* EQ::ItemInstance::PopItem(uint8 index)
m_contents.erase(index);
return inst; // Return pointer that needs to be deleted (or otherwise managed)
}
return nullptr;
}
@@ -510,7 +476,7 @@ uint8 EQ::ItemInstance::GetTotalItemCount() const
{
if (!m_item)
return 0;
uint8 item_count = 1;
if (m_item && !m_item->IsClassBag()) { return item_count; }
@@ -560,7 +526,7 @@ EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugty
{
continue;
}
return GetAugment(i);
return this->GetAugment(i);
}
}
@@ -583,7 +549,7 @@ uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const {
bool EQ::ItemInstance::UpdateOrnamentationInfo() {
if (!m_item || !m_item->IsClassCommon())
return false;
bool ornamentSet = false;
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
@@ -676,7 +642,7 @@ void EQ::ItemInstance::PutAugment(uint8 slot, const ItemInstance& augment)
{
if (!m_item || !m_item->IsClassCommon())
return;
PutItem(slot, augment);
}
@@ -689,7 +655,7 @@ void EQ::ItemInstance::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id
if (aug) {
PutAugment(slot, *aug);
safe_delete(aug);
}
}
}
// Remove augment from item and destroy it
@@ -697,7 +663,7 @@ void EQ::ItemInstance::DeleteAugment(uint8 index)
{
if (!m_item || !m_item->IsClassCommon())
return;
DeleteItem(index);
}
@@ -706,7 +672,7 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
{
if (!m_item || !m_item->IsClassCommon())
return nullptr;
return PopItem(index);
}
@@ -714,7 +680,7 @@ bool EQ::ItemInstance::IsAugmented()
{
if (!m_item || !m_item->IsClassCommon())
return false;
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
if (GetAugmentItemID(index))
return true;
@@ -723,45 +689,6 @@ bool EQ::ItemInstance::IsAugmented()
return false;
}
bool EQ::ItemInstance::ContainsAugmentByID(uint32 item_id)
{
if (!m_item || !m_item->IsClassCommon()) {
return false;
}
if (!item_id) {
return false;
}
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
if (GetAugmentItemID(augment_slot) == item_id) {
return true;
}
}
return false;
}
int EQ::ItemInstance::CountAugmentByID(uint32 item_id)
{
int quantity = 0;
if (!m_item || !m_item->IsClassCommon()) {
return quantity;
}
if (!item_id) {
return quantity;
}
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
if (GetAugmentItemID(augment_slot) == item_id) {
quantity++;
}
}
return quantity;
}
// Has attack/delay?
bool EQ::ItemInstance::IsWeapon() const
{
@@ -907,7 +834,7 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
return false;
}
}
return true;
}
@@ -1131,7 +1058,7 @@ int EQ::ItemInstance::GetItemElementalFlag(bool augments) const
int EQ::ItemInstance::GetItemElementalDamage(bool augments) const
{
int64 damage = 0;
int damage = 0;
const auto item = GetItem();
if (item) {
damage = item->ElemDmgAmt;
@@ -1196,7 +1123,7 @@ int EQ::ItemInstance::GetItemRequiredLevel(bool augments) const
int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
{
int64 damage = 0;
int damage = 0;
const auto item = GetItem();
if (item) {
damage = item->Damage;
@@ -1212,7 +1139,7 @@ int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
int EQ::ItemInstance::GetItemBackstabDamage(bool augments) const
{
int64 damage = 0;
int damage = 0;
const auto item = GetItem();
if (item) {
damage = item->BackstabDmg;
@@ -1270,7 +1197,7 @@ int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const
{
int64 damage = 0;
int damage = 0;
const auto item = GetItem();
if (item) {
if (item->BaneDmgBody == against)
@@ -1287,7 +1214,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) con
int EQ::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) const
{
int64 damage = 0;
int damage = 0;
const auto item = GetItem();
if (item) {
if (item->BaneDmgRace == against)
@@ -1755,18 +1682,6 @@ int EQ::ItemInstance::GetItemHaste(bool augments) const
return total;
}
int EQ::ItemInstance::RemoveTaskDeliveredItems()
{
int count = IsStackable() ? GetCharges() : 1;
count -= GetTaskDeliveredCount();
if (IsStackable())
{
SetCharges(count);
}
SetTaskDeliveredCount(0);
return count;
}
//
// class EvolveInfo
//
-14
View File
@@ -92,8 +92,6 @@ namespace EQ
// Can item be equipped by/at?
bool IsEquipable(uint16 race, uint16 class_) const;
bool IsClassEquipable(uint16 class_) const;
bool IsRaceEquipable(uint16 race) const;
bool IsEquipable(int16 slot_id) const;
//
@@ -134,8 +132,6 @@ namespace EQ
void DeleteAugment(uint8 slot);
ItemInstance* RemoveAugment(uint8 index);
bool IsAugmented();
bool ContainsAugmentByID(uint32 item_id);
int CountAugmentByID(uint32 item_id);
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
bool UpdateOrnamentationInfo();
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
@@ -150,8 +146,6 @@ namespace EQ
const ItemData* GetItem() const;
const ItemData* GetUnscaledItem() const;
const uint8 GetItemType() const { return m_item ? m_item->ItemType : 255; } // Return 255 so you know there's no valid item
int16 GetCharges() const { return m_charges; }
void SetCharges(int16 charges) { m_charges = charges; }
@@ -233,13 +227,6 @@ namespace EQ
void StopTimer(std::string name);
void ClearTimers();
int GetTaskDeliveredCount() const { return m_task_delivered_count; }
void SetTaskDeliveredCount(int count) { m_task_delivered_count = count; }
// This function should only be used by trade return apis
// Removes delivered task items from stack count and returns remaining count
// Return value should be used to determine if an item still exists (for stackable and non-stackable)
int RemoveTaskDeliveredItems();
// Get a total of a stat, including augs
// These functions should be used in place of other code manually totaling
// to centralize where it is done to make future changes easier (ex. whenever powersources come around)
@@ -324,7 +311,6 @@ namespace EQ
uint32 m_new_id_file;
uint32 m_ornament_hero_model;
uint32 m_recast_timestamp;
int m_task_delivered_count = 0;
//
// Items inside of this item (augs or contents);
+5 -14
View File
@@ -30,19 +30,11 @@ struct LootTableEntries_Struct {
float probability;
};
struct ContentFlags {
int16 min_expansion;
int16 max_expansion;
char content_flags[100];
char content_flags_disabled[100];
};
struct LootTable_Struct {
uint32 mincash;
uint32 maxcash;
uint32 avgcoin;
uint32 NumEntries;
ContentFlags content_flags;
uint32 mincash;
uint32 maxcash;
uint32 avgcoin;
uint32 NumEntries;
LootTableEntries_Struct Entries[0];
};
@@ -59,8 +51,7 @@ struct LootDropEntries_Struct {
};
struct LootDrop_Struct {
uint32 NumEntries;
ContentFlags content_flags;
uint32 NumEntries;
LootDropEntries_Struct Entries[0];
};
#pragma pack()
+2 -2
View File
@@ -9,7 +9,7 @@
*/
#include <string.h> /* for memcpy() */
#include "../common/md5.h"
#include "../common/strings.h"
#include "../common/string_util.h"
#include "../common/seperator.h"
MD5::MD5() {
@@ -194,7 +194,7 @@ void MD5::Final(uint8 digest[16], MD5Context *ctx) {
/* The heart of the MD5 algorithm. */
void MD5::Transform(uint32 hash[4], const uint32 input[16]) {
uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
register uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
MD5STEP(F1, a, b, c, d, input[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, input[ 1]+0xe8c7b756, 12);
+7 -7
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@ namespace EQ
MemoryBuffer& operator+=(const MemoryBuffer &rhs);
friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; }
~MemoryBuffer();
uchar& operator[](size_t pos);
const uchar& operator[](size_t pos) const;
@@ -64,20 +64,20 @@ namespace EQ
size_t Size() const;
size_t Capacity();
size_t Capacity() const;
void Resize(size_t sz);
void Clear();
void Zero();
template<typename T>
void Write(T val) {
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
Write((const char*)&val, sizeof(T));
}
template<typename T>
T Read() {
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
T temp;
Read((uchar*)&temp, sizeof(T));
return temp;
@@ -102,7 +102,7 @@ namespace EQ
read_pos_ += len + 1;
return ret;
}
void Write(const char *val, size_t len);
void Read(uchar *buf, size_t len);
void Read(char *str);
@@ -113,7 +113,7 @@ namespace EQ
inline size_t GetReadPosition() { return read_pos_; }
inline void SetReadPosition(size_t rp) { read_pos_ = rp; }
inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; }
private:
uchar *buffer_;
size_t size_;
-3
View File
@@ -33,9 +33,6 @@
#include <sys/stat.h>
#endif
#include <filesystem>
namespace fs = std::filesystem;
namespace EQ {
struct MemoryMappedFile::Implementation {
+1 -7
View File
@@ -10,14 +10,8 @@
#include <iterator>
#include "types.h"
class MySQLRequestRow
class MySQLRequestRow : public std::iterator<std::input_iterator_tag, MYSQL_ROW>
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = MYSQL_ROW;
using difference_type = std::ptrdiff_t;
using pointer = MYSQL_ROW*;
using reference = MYSQL_ROW&;
private:
MYSQL_RES* m_Result;
+6 -6
View File
@@ -1,5 +1,5 @@
#include "console_server.h"
#include "../strings.h"
#include "../string_util.h"
#include <fmt/format.h>
EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
@@ -52,11 +52,11 @@ void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c)
void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd)
{
auto split = Strings::Split(cmd, ' ');
auto split = SplitString(cmd, ' ');
if (split.size() > 0) {
auto command = split[0];
command = Strings::ToLower(command);
ToLowerString(command);
if (command == "help" || command == "?") {
c->SendLine("Commands:");
@@ -70,9 +70,9 @@ void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const st
c->SendPrompt();
return;
}
split.erase(split.begin(), split.begin() + 1);
auto cmd_def = m_commands.find(command);
if (cmd_def != m_commands.end()) {
if (c->Admin() >= cmd_def->second.status_required) {
+17 -16
View File
@@ -15,7 +15,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
memset(m_line, 0, MaxConsoleLineLength);
m_accept_messages = false;
m_user_id = 0;
m_admin = AccountStatus::Player;
m_admin = 0;
m_connection->OnRead(std::bind(&ConsoleServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
@@ -29,7 +29,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
if (addr.find("127.0.0.1") != std::string::npos || addr.find("::0") != std::string::npos) {
SendLine("Connection established from localhost, assuming admin");
m_status = ConsoleStatusLoggedIn;
m_admin = AccountStatus::Max;
m_admin = 255;
SendPrompt();
}
else {
@@ -116,42 +116,43 @@ bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMes
}
switch (scm->chan_num) {
case ChatChannel_Guild: {
QueueMessage(fmt::format("{} tells the guild [{}], '{}'", scm->from, scm->guilddbid, scm->message));
break;
}
case ChatChannel_Auction: {
case 4: {
if (RuleB(Chat, ServerWideAuction)) {
QueueMessage(fmt::format("{} auctions, '{}'", scm->from, scm->message));
QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
case ChatChannel_OOC: {
case 5: {
if (RuleB(Chat, ServerWideOOC)) {
QueueMessage(fmt::format("{} says ooc, '{}'", scm->from, scm->message));
QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
case ChatChannel_Broadcast: {
QueueMessage(fmt::format("{} BROADCASTS, '{}'", scm->from, scm->message));
case 6: {
QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message));
break;
}
case ChatChannel_Tell: {
QueueMessage(fmt::format("[{}] tells {}, '{}'", scm->from, scm->to, scm->message));
case 7: {
QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message));
if (onTell) {
onTell();
}
break;
}
case ChatChannel_GMSAY: {
QueueMessage(fmt::format("{} GMSAYS, '{}'", scm->from, scm->message));
case 11: {
QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message));
break;
}
default: {
return false;
}
+6 -24
View File
@@ -3,7 +3,6 @@
#include "../event/task.h"
#include "../data_verification.h"
#include "crc32.h"
#include "../eqemu_logsys.h"
#include <zlib.h>
#include <fmt/format.h>
#include <sstream>
@@ -309,8 +308,6 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_combined[1] = OP_Combined;
m_last_session_stats = Clock::now();
m_outgoing_budget = owner->m_options.outgoing_data_rate;
LogNetcode("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
}
//new connection made as client
@@ -469,7 +466,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
for (int i = 1; i >= 0; --i) {
switch (m_encode_passes[i]) {
case EncodeXOR:
if (temp.GetInt8(0) == 0)
if (temp.GetInt8(0) == 0)
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
else
Decode(temp, 1, temp.Length() - 1);
@@ -633,8 +630,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
DynamicPacket p;
p.PutSerialize(0, reply);
InternalSend(p);
LogNetcode("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
}
break;
@@ -652,12 +647,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
m_max_packet_size = reply.max_packet_size;
ChangeStatus(StatusConnected);
LogNetcode(
"[OP_SessionResponse] Session [{}] refresh with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
}
}
break;
@@ -782,12 +771,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
SendDisconnect();
}
LogNetcode(
"[OP_SessionDisconnect] Session [{}] disconnect with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
ChangeStatus(StatusDisconnecting);
break;
}
@@ -852,7 +835,6 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
}
if (p.Length() < (size_t)m_crc_bytes) {
LogNetcode("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code);
return false;
}
@@ -1096,7 +1078,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
if (m_status == DbProtocolStatus::StatusDisconnected) {
return;
}
auto resends = 0;
auto now = Clock::now();
auto s = &m_streams[stream];
@@ -1131,7 +1113,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
Close();
return;
}
if ((size_t)time_since_last_send.count() > entry.second.resend_delay) {
auto &p = entry.second.packet;
if (p.Length() >= DaybreakHeader::size()) {
@@ -1412,7 +1394,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length);
size_t used = 0;
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size() - 1; // -1 for compress flag
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size();
DynamicPacket first_packet;
first_packet.PutSerialize(0, first_header);
first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen);
@@ -1424,8 +1406,8 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
sent.first_sent = Clock::now();
sent.times_resent = 0;
sent.resend_delay = EQ::Clamp(
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
m_owner->m_options.resend_delay_min,
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
m_owner->m_options.resend_delay_min,
m_owner->m_options.resend_delay_max);
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
stream->sequence_out++;
-9
View File
@@ -65,15 +65,6 @@ EQ::Net::EQStream::~EQStream()
}
void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
LogPacketServerClient(
"[{}] [{:#06x}] Size [{}] {}",
OpcodeManager::EmuToName(p->GetOpcode()),
(*m_opcode_manager)->EmuToEQ(p->GetOpcode()),
p->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
);
if (m_opcode_manager && *m_opcode_manager) {
uint16 opcode = 0;
if (p->GetOpcodeBypass() != 0) {
-4
View File
@@ -57,10 +57,6 @@ namespace EQ
virtual void SetOpcodeManager(OpcodeManager **opm) {
m_opcode_manager = opm;
}
virtual OpcodeManager * GetOpcodeManager() const
{
return (*m_opcode_manager);
};
virtual Stats GetStats() const;
virtual void ResetStats();
+167 -16
View File
@@ -21,16 +21,32 @@ EQ::Net::ServertalkClient::~ServertalkClient()
void EQ::Net::ServertalkClient::Send(uint16_t opcode, EQ::Net::Packet &p)
{
// pad zero size packets
if (p.Length() == 0) {
p.PutUInt8(0, 0);
}
EQ::Net::DynamicPacket out;
#ifdef ENABLE_SECURITY
if (m_encrypted) {
if (p.Length() == 0) {
p.PutUInt8(0, 0);
}
out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES);
out.PutUInt16(4, opcode);
std::unique_ptr<unsigned char[]> cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]);
crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key);
(*(uint64_t*)&m_nonce_ours[0])++;
out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES);
}
else {
out.PutUInt32(0, p.Length());
out.PutUInt16(4, opcode);
out.PutPacket(6, p);
}
#else
out.PutUInt32(0, p.Length());
out.PutUInt16(4, opcode);
out.PutPacket(6, p);
#endif
InternalSend(ServertalkMessage, out);
}
@@ -71,18 +87,14 @@ void EQ::Net::ServertalkClient::Connect()
m_connection = connection;
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
LogF(Logs::General, Logs::TCPConnection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
m_encrypted = false;
m_connection.reset();
});
m_connection->OnRead(std::bind(&EQ::Net::ServertalkClient::ProcessData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection->Start();
SendHandshake();
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
SendHello();
m_connecting = false;
});
}
@@ -176,11 +188,67 @@ void EQ::Net::ServertalkClient::ProcessReadBuffer()
void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
{
#ifdef ENABLE_SECURITY
memset(m_public_key_ours, 0, crypto_box_PUBLICKEYBYTES);
memset(m_public_key_theirs, 0, crypto_box_PUBLICKEYBYTES);
memset(m_private_key_ours, 0, crypto_box_SECRETKEYBYTES);
memset(m_nonce_ours, 0, crypto_box_NONCEBYTES);
memset(m_nonce_theirs, 0, crypto_box_NONCEBYTES);
memset(m_shared_key, 0, crypto_box_BEFORENMBYTES);
m_encrypted = false;
try {
SendHandshake();
bool enc = p.GetInt8(0) == 1 ? true : false;
if (enc) {
if (p.Length() == (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES)) {
memcpy(m_public_key_theirs, (char*)p.Data() + 1, crypto_box_PUBLICKEYBYTES);
memcpy(m_nonce_theirs, (char*)p.Data() + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES);
m_encrypted = true;
SendHandshake();
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
else {
LogError("Could not process hello, size != {0}", 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
}
}
else {
SendHandshake();
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
}
catch (std::exception &ex) {
LogError("Error parsing hello from server: {0}", ex.what());
m_connection->Disconnect();
if (m_on_connect_cb) {
m_on_connect_cb(this);
m_on_connect_cb(nullptr);
}
}
#else
try {
bool enc = p.GetInt8(0) == 1 ? true : false;
if (enc) {
SendHandshake(true);
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
else {
SendHandshake();
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
}
catch (std::exception &ex) {
@@ -191,6 +259,7 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
m_on_connect_cb(nullptr);
}
}
#endif
}
void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
@@ -200,7 +269,45 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
auto opcode = p.GetUInt16(4);
if (length > 0) {
auto data = p.GetString(6, length);
#ifdef ENABLE_SECURITY
if (m_encrypted) {
size_t message_len = length - crypto_secretbox_MACBYTES;
std::unique_ptr<unsigned char[]> decrypted_text(new unsigned char[message_len]);
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key))
{
LogError("Error decrypting message from server");
(*(uint64_t*)&m_nonce_theirs[0])++;
return;
}
EQ::Net::StaticPacket decrypted_packet(&decrypted_text[0], message_len);
(*(uint64_t*)&m_nonce_theirs[0])++;
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, decrypted_packet);
}
if (m_message_callback) {
m_message_callback(opcode, decrypted_packet);
}
}
else {
size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len);
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
}
if (m_message_callback) {
m_message_callback(opcode, packet);
}
}
#else
size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len);
@@ -212,6 +319,7 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
if (m_message_callback) {
m_message_callback(opcode, packet);
}
#endif
}
}
catch (std::exception &ex) {
@@ -219,11 +327,54 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
}
}
void EQ::Net::ServertalkClient::SendHandshake()
void EQ::Net::ServertalkClient::SendHandshake(bool downgrade)
{
EQ::Net::DynamicPacket handshake;
#ifdef ENABLE_SECURITY
if (m_encrypted) {
crypto_box_keypair(m_public_key_ours, m_private_key_ours);
randombytes_buf(m_nonce_ours, crypto_box_NONCEBYTES);
crypto_box_beforenm(m_shared_key, m_public_key_theirs, m_private_key_ours);
handshake.PutData(0, m_public_key_ours, crypto_box_PUBLICKEYBYTES);
handshake.PutData(crypto_box_PUBLICKEYBYTES, m_nonce_ours, crypto_box_NONCEBYTES);
memset(m_public_key_ours, 0, crypto_box_PUBLICKEYBYTES);
memset(m_public_key_theirs, 0, crypto_box_PUBLICKEYBYTES);
memset(m_private_key_ours, 0, crypto_box_SECRETKEYBYTES);
size_t cipher_length = m_identifier.length() + 1 + m_credentials.length() + 1 + crypto_secretbox_MACBYTES;
size_t data_length = m_identifier.length() + 1 + m_credentials.length() + 1;
std::unique_ptr<unsigned char[]> signed_buffer(new unsigned char[cipher_length]);
std::unique_ptr<unsigned char[]> data_buffer(new unsigned char[data_length]);
memset(&data_buffer[0], 0, data_length);
memcpy(&data_buffer[0], m_identifier.c_str(), m_identifier.length());
memcpy(&data_buffer[1 + m_identifier.length()], m_credentials.c_str(), m_credentials.length());
crypto_box_easy_afternm(&signed_buffer[0], &data_buffer[0], data_length, m_nonce_ours, m_shared_key);
(*(uint64_t*)&m_nonce_ours[0])++;
handshake.PutData(crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, &signed_buffer[0], cipher_length);
}
else {
handshake.PutString(0, m_identifier);
handshake.PutString(m_identifier.length() + 1, m_credentials);
handshake.PutUInt8(m_identifier.length() + 1 + m_credentials.length(), 0);
}
#else
handshake.PutString(0, m_identifier);
handshake.PutString(m_identifier.length() + 1, m_credentials);
handshake.PutUInt8(m_identifier.length() + 1 + m_credentials.length(), 0);
InternalSend(ServertalkClientDowngradeSecurityHandshake, handshake);
#endif
if (downgrade) {
InternalSend(ServertalkClientDowngradeSecurityHandshake, handshake);
}
else {
InternalSend(ServertalkClientHandshake, handshake);
}
}
+17 -1
View File
@@ -4,6 +4,9 @@
#include "../event/timer.h"
#include "servertalk_common.h"
#include "packet.h"
#ifdef ENABLE_SECURITY
#include <sodium.h>
#endif
namespace EQ
{
@@ -31,7 +34,8 @@ namespace EQ
void ProcessReadBuffer();
void ProcessHello(EQ::Net::Packet &p);
void ProcessMessage(EQ::Net::Packet &p);
void SendHandshake();
void SendHandshake() { SendHandshake(false); }
void SendHandshake(bool downgrade);
std::unique_ptr<EQ::Timer> m_timer;
@@ -41,11 +45,23 @@ namespace EQ
bool m_connecting;
int m_port;
bool m_ipv6;
bool m_encrypted;
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
std::vector<char> m_buffer;
std::unordered_map<uint16_t, std::function<void(uint16_t, EQ::Net::Packet&)>> m_message_callbacks;
std::function<void(uint16_t, EQ::Net::Packet&)> m_message_callback;
std::function<void(ServertalkClient*)> m_on_connect_cb;
#ifdef ENABLE_SECURITY
unsigned char m_public_key_ours[crypto_box_PUBLICKEYBYTES];
unsigned char m_private_key_ours[crypto_box_SECRETKEYBYTES];
unsigned char m_nonce_ours[crypto_box_NONCEBYTES];
unsigned char m_public_key_theirs[crypto_box_PUBLICKEYBYTES];
unsigned char m_nonce_theirs[crypto_box_NONCEBYTES];
unsigned char m_shared_key[crypto_box_BEFORENMBYTES];
#endif
};
}
}
+1 -1
View File
@@ -15,4 +15,4 @@ namespace EQ
ServertalkMessage,
};
}
}
}
+3 -1
View File
@@ -10,10 +10,12 @@ EQ::Net::ServertalkServer::~ServertalkServer()
void EQ::Net::ServertalkServer::Listen(const ServertalkServerOptions& opts)
{
m_encrypted = opts.encrypted;
m_credentials = opts.credentials;
m_allow_downgrade = opts.allow_downgrade;
m_server = std::make_unique<EQ::Net::TCPServer>();
m_server->Listen(opts.port, opts.ipv6, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
m_unident_connections.push_back(std::make_shared<ServertalkServerConnection>(connection, this));
m_unident_connections.push_back(std::make_shared<ServertalkServerConnection>(connection, this, m_encrypted, m_allow_downgrade));
});
}
+13
View File
@@ -5,6 +5,10 @@
#include <vector>
#include <map>
#ifdef ENABLE_SECURITY
#include <sodium.h>
#endif
namespace EQ
{
namespace Net
@@ -13,9 +17,18 @@ namespace EQ
{
int port;
bool ipv6;
bool encrypted;
bool allow_downgrade;
std::string credentials;
ServertalkServerOptions() {
#ifdef ENABLE_SECURITY
encrypted = true;
allow_downgrade = true;
#else
encrypted = false;
allow_downgrade = true;
#endif
ipv6 = false;
}
};
+155 -169
View File
@@ -3,15 +3,16 @@
#include "../eqemu_logsys.h"
#include "../util/uuid.h"
EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, EQ::Net::ServertalkServer *parent)
EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, EQ::Net::ServertalkServer *parent, bool encrypted, bool allow_downgrade)
{
m_connection = c;
m_parent = parent;
m_encrypted = encrypted;
m_allow_downgrade = allow_downgrade;
m_uuid = EQ::Util::UUID::Generate().ToString();
m_connection->OnRead(std::bind(&ServertalkServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection->OnDisconnect(std::bind(&ServertalkServerConnection::OnDisconnect, this, std::placeholders::_1));
m_connection->Start();
m_legacy_mode = false;
}
EQ::Net::ServertalkServerConnection::~ServertalkServerConnection()
@@ -20,73 +21,32 @@ EQ::Net::ServertalkServerConnection::~ServertalkServerConnection()
void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet & p)
{
if (m_legacy_mode) {
if (!m_connection)
return;
if (opcode == ServerOP_UsertoWorldReq) {
auto req_in = (UsertoWorldRequest_Struct*)p.Data();
EQ::Net::DynamicPacket req;
size_t i = 0;
req.PutUInt32(i, req_in->lsaccountid); i += 4;
req.PutUInt32(i, req_in->worldid); i += 4;
req.PutUInt32(i, req_in->FromID); i += 4;
req.PutUInt32(i, req_in->ToID); i += 4;
req.PutData(i, req_in->IPAddr, 64); i += 64;
EQ::Net::DynamicPacket out;
out.PutUInt16(0, ServerOP_UsertoWorldReqLeg);
out.PutUInt16(2, req.Length() + 4);
out.PutPacket(4, req);
m_connection->Write((const char*)out.Data(), out.Length());
return;
}
if (opcode == ServerOP_LSClientAuth) {
auto req_in = (ClientAuth_Struct*)p.Data();
EQ::Net::DynamicPacket req;
size_t i = 0;
req.PutUInt32(i, req_in->loginserver_account_id); i += 4;
req.PutData(i, req_in->account_name, 30); i += 30;
req.PutData(i, req_in->key, 30); i += 30;
req.PutUInt8(i, req_in->lsadmin); i += 1;
req.PutUInt16(i, req_in->is_world_admin); i += 2;
req.PutUInt32(i, req_in->ip); i += 4;
req.PutUInt8(i, req_in->is_client_from_local_network); i += 1;
EQ::Net::DynamicPacket out;
out.PutUInt16(0, ServerOP_LSClientAuthLeg);
out.PutUInt16(2, req.Length() + 4);
out.PutPacket(4, req);
m_connection->Write((const char*)out.Data(), out.Length());
return;
}
EQ::Net::DynamicPacket out;
out.PutUInt16(0, opcode);
out.PutUInt16(2, p.Length() + 4);
out.PutPacket(4, p);
m_connection->Write((const char*)out.Data(), out.Length());
} else {
// pad zero size packets
// pad packets that would cause a collision with legacy identification code
// It's unlikely we'd send a 4MB msg for any reason but just incase.
if (p.Length() == 0 || p.Length() == 43061256) {
EQ::Net::DynamicPacket out;
#ifdef ENABLE_SECURITY
if (m_encrypted) {
if (p.Length() == 0) {
p.PutUInt8(0, 0);
}
EQ::Net::DynamicPacket out;
out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES);
out.PutUInt16(4, opcode);
std::unique_ptr<unsigned char[]> cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]);
crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key);
(*(uint64_t*)&m_nonce_ours[0])++;
out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES);
}
else {
out.PutUInt32(0, p.Length());
out.PutUInt16(4, opcode);
out.PutPacket(6, p);
InternalSend(ServertalkMessage, out);
}
#else
out.PutUInt32(0, p.Length());
out.PutUInt16(4, opcode);
out.PutPacket(6, p);
#endif
InternalSend(ServertalkMessage, out);
}
void EQ::Net::ServertalkServerConnection::SendPacket(ServerPacket *p)
@@ -111,41 +71,17 @@ void EQ::Net::ServertalkServerConnection::OnMessage(std::function<void(uint16_t,
void EQ::Net::ServertalkServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz)
{
m_buffer.insert(m_buffer.end(), (const char*)data, (const char*)data + sz);
if (m_legacy_mode) {
ProcessOldReadBuffer();
} else {
ProcessReadBuffer();
}
ProcessReadBuffer();
}
void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
{
size_t current = 0;
size_t total = m_buffer.size();
constexpr size_t ls_info_size = sizeof(ServerNewLSInfo_Struct);
while (current < total) {
auto left = total - current;
if (left < 4) {
break;
}
auto leg_opcode = *(uint16_t*)&m_buffer[current];
auto leg_size = *(uint16_t*)&m_buffer[current + 2] - 4;
//this creates a small edge case where the exact size of a
//packet from the modern protocol can't be "43061256"
//so in send we pad it one byte if that's the case
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) {
m_legacy_mode = true;
m_identifier = "World";
m_parent->ConnectionIdentified(this);
ProcessOldReadBuffer();
return;
}
/*
//header:
//uint32 length;
@@ -173,7 +109,6 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
}
break;
case ServertalkClientHandshake:
case ServertalkClientDowngradeSecurityHandshake:
ProcessHandshake(p);
break;
case ServertalkMessage:
@@ -190,9 +125,11 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
}
break;
case ServertalkClientHandshake:
case ServertalkClientDowngradeSecurityHandshake:
ProcessHandshake(p);
break;
case ServertalkClientDowngradeSecurityHandshake:
ProcessHandshake(p, true);
break;
case ServertalkMessage:
ProcessMessage(p);
break;
@@ -210,57 +147,6 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
}
}
void EQ::Net::ServertalkServerConnection::ProcessOldReadBuffer()
{
size_t current = 0;
size_t total = m_buffer.size();
while (current < total) {
auto left = total - current;
/*
//header:
//uint32 length;
//uint8 type;
*/
uint16_t length = 0;
uint16_t opcode = 0;
if (left < 4) {
break;
}
opcode = *(uint16_t*)&m_buffer[current];
length = *(uint16_t*)&m_buffer[current + 2];
if (length < 4) {
break;
}
length -= 4;
if (current + 4 + length > total) {
break;
}
if (length == 0) {
EQ::Net::DynamicPacket p;
ProcessMessageOld(opcode, p);
}
else {
EQ::Net::StaticPacket p(&m_buffer[current + 4], length);
ProcessMessageOld(opcode, p);
}
current += length + 4;
}
if (current == total) {
m_buffer.clear();
}
else {
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + current);
}
}
void EQ::Net::ServertalkServerConnection::OnDisconnect(TCPConnection *c)
{
m_parent->ConnectionDisconnected(this);
@@ -269,14 +155,36 @@ void EQ::Net::ServertalkServerConnection::OnDisconnect(TCPConnection *c)
void EQ::Net::ServertalkServerConnection::SendHello()
{
EQ::Net::DynamicPacket hello;
#ifdef ENABLE_SECURITY
memset(m_public_key_ours, 0, crypto_box_PUBLICKEYBYTES);
memset(m_public_key_theirs, 0, crypto_box_PUBLICKEYBYTES);
memset(m_private_key_ours, 0, crypto_box_SECRETKEYBYTES);
memset(m_nonce_ours, 0, crypto_box_NONCEBYTES);
memset(m_nonce_theirs, 0, crypto_box_NONCEBYTES);
if (m_encrypted) {
hello.PutInt8(0, 1);
crypto_box_keypair(m_public_key_ours, m_private_key_ours);
randombytes_buf(m_nonce_ours, crypto_box_NONCEBYTES);
hello.PutData(1, m_public_key_ours, crypto_box_PUBLICKEYBYTES);
hello.PutData(1 + crypto_box_PUBLICKEYBYTES, m_nonce_ours, crypto_box_NONCEBYTES);
}
else {
hello.PutInt8(0, 0);
}
#else
hello.PutInt8(0, 0);
#endif
InternalSend(ServertalkServerHello, hello);
}
void EQ::Net::ServertalkServerConnection::InternalSend(ServertalkPacketType type, EQ::Net::Packet &p)
{
if (!m_connection || m_legacy_mode)
if (!m_connection)
return;
EQ::Net::DynamicPacket out;
@@ -289,8 +197,71 @@ void EQ::Net::ServertalkServerConnection::InternalSend(ServertalkPacketType type
m_connection->Write((const char*)out.Data(), out.Length());
}
void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p)
void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, bool downgrade_security)
{
#ifdef ENABLE_SECURITY
if (downgrade_security && m_allow_downgrade && m_encrypted) {
LogF(Logs::General, Logs::TCPConnection, "Downgraded encrypted connection to plaintext because otherside didn't support encryption {0}:{1}",
m_connection->RemoteIP(), m_connection->RemotePort());
m_encrypted = false;
}
if (m_encrypted) {
try {
if (p.Length() > (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES)) {
memcpy(m_public_key_theirs, (char*)p.Data(), crypto_box_PUBLICKEYBYTES);
memcpy(m_nonce_theirs, (char*)p.Data() + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES);
crypto_box_beforenm(m_shared_key, m_public_key_theirs, m_private_key_ours);
size_t cipher_len = p.Length() - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES;
size_t message_len = cipher_len - crypto_secretbox_MACBYTES;
std::unique_ptr<unsigned char[]> decrypted_text(new unsigned char[message_len]);
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)p.Data() + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, cipher_len, m_nonce_theirs, m_shared_key))
{
LogError("Error decrypting handshake from client, dropping connection.");
m_connection->Disconnect();
return;
}
m_identifier = (const char*)&decrypted_text[0];
std::string credentials = (const char*)&decrypted_text[0] + (m_identifier.length() + 1);
if (!m_parent->CheckCredentials(credentials)) {
LogError("Got incoming connection with invalid credentials during handshake, dropping connection.");
m_connection->Disconnect();
return;
}
m_parent->ConnectionIdentified(this);
(*(uint64_t*)&m_nonce_theirs[0])++;
}
}
catch (std::exception &ex) {
LogError("Error parsing handshake from client: {0}", ex.what());
m_connection->Disconnect();
}
}
else {
try {
m_identifier = p.GetCString(0);
auto credentials = p.GetCString(m_identifier.length() + 1);
if (!m_parent->CheckCredentials(credentials)) {
LogError("Got incoming connection with invalid credentials during handshake, dropping connection.");
m_connection->Disconnect();
return;
}
m_parent->ConnectionIdentified(this);
}
catch (std::exception &ex) {
LogError("Error parsing handshake from client: {0}", ex.what());
m_connection->Disconnect();
}
}
#else
try {
m_identifier = p.GetCString(0);
auto credentials = p.GetCString(m_identifier.length() + 1);
@@ -307,6 +278,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p)
LogError("Error parsing handshake from client: {0}", ex.what());
m_connection->Disconnect();
}
#endif
}
void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
@@ -316,19 +288,49 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
auto opcode = p.GetUInt16(4);
if (length > 0) {
auto data = p.GetString(6, length);
#ifdef ENABLE_SECURITY
if (m_encrypted) {
size_t message_len = length - crypto_secretbox_MACBYTES;
std::unique_ptr<unsigned char[]> decrypted_text(new unsigned char[message_len]);
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key))
{
LogError("Error decrypting message from client");
(*(uint64_t*)&m_nonce_theirs[0])++;
return;
}
EQ::Net::StaticPacket decrypted_packet(&decrypted_text[0], message_len);
(*(uint64_t*)&m_nonce_theirs[0])++;
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, decrypted_packet);
}
if (m_message_callback) {
m_message_callback(opcode, decrypted_packet);
}
}
else {
size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len);
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
}
if (m_message_callback) {
m_message_callback(opcode, packet);
}
}
#else
size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len);
const auto is_detail_enabled = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
if (opcode != ServerOP_KeepAlive || is_detail_enabled) {
LogPacketServerToServer(
"[{:#06x}] Size [{}] {}",
opcode,
packet.Length(),
(is_detail_enabled ? "\n" + packet.ToString() : "")
);
}
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
@@ -337,26 +339,10 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
if (m_message_callback) {
m_message_callback(opcode, packet);
}
#endif
}
}
catch (std::exception &ex) {
LogError("Error parsing message from client: {0}", ex.what());
}
}
void EQ::Net::ServertalkServerConnection::ProcessMessageOld(uint16_t opcode, EQ::Net::Packet &p)
{
try {
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, p);
}
if (m_message_callback) {
m_message_callback(opcode, p);
}
}
catch (std::exception &ex) {
LogError("Error parsing legacy message from client: {0}", ex.what());
}
}
+19 -5
View File
@@ -4,6 +4,9 @@
#include "servertalk_common.h"
#include "packet.h"
#include <vector>
#ifdef ENABLE_SECURITY
#include <sodium.h>
#endif
namespace EQ
{
@@ -13,7 +16,7 @@ namespace EQ
class ServertalkServerConnection
{
public:
ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, ServertalkServer *parent);
ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, ServertalkServer *parent, bool encrypted, bool allow_downgrade);
~ServertalkServerConnection();
void Send(uint16_t opcode, EQ::Net::Packet &p);
@@ -27,13 +30,12 @@ namespace EQ
private:
void OnRead(TCPConnection* c, const unsigned char* data, size_t sz);
void ProcessReadBuffer();
void ProcessOldReadBuffer();
void OnDisconnect(TCPConnection* c);
void SendHello();
void InternalSend(ServertalkPacketType type, EQ::Net::Packet &p);
void ProcessHandshake(EQ::Net::Packet &p);
void ProcessHandshake(EQ::Net::Packet &p) { ProcessHandshake(p, false); }
void ProcessHandshake(EQ::Net::Packet &p, bool security_downgrade);
void ProcessMessage(EQ::Net::Packet &p);
void ProcessMessageOld(uint16_t opcode, EQ::Net::Packet &p);
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
ServertalkServer *m_parent;
@@ -43,7 +45,19 @@ namespace EQ
std::function<void(uint16_t, EQ::Net::Packet&)> m_message_callback;
std::string m_identifier;
std::string m_uuid;
bool m_legacy_mode;
bool m_encrypted;
bool m_allow_downgrade;
#ifdef ENABLE_SECURITY
unsigned char m_public_key_ours[crypto_box_PUBLICKEYBYTES];
unsigned char m_private_key_ours[crypto_box_SECRETKEYBYTES];
unsigned char m_nonce_ours[crypto_box_NONCEBYTES];
unsigned char m_public_key_theirs[crypto_box_PUBLICKEYBYTES];
unsigned char m_nonce_theirs[crypto_box_NONCEBYTES];
unsigned char m_shared_key[crypto_box_BEFORENMBYTES];
#endif
};
}
}
+2 -3
View File
@@ -5,7 +5,6 @@
#include <map>
#include <unordered_set>
#include <array>
#include "../emu_constants.h"
struct MethodHandlerEntry
{
@@ -175,13 +174,13 @@ Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connectio
auto r = _impl->login_handler(connection, user, pass);
if (r.logged_in) {
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max);
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
ret["status"] = "Ok";
}
else if (user == "admin" && (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::")) {
r.logged_in = true;
r.account_id = 0;
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max);
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
ret["status"] = "Ok";
}
else {
+2 -2
View File
@@ -115,8 +115,8 @@ IN(OP_GMTraining, GMTrainee_Struct);
IN(OP_GMEndTraining, GMTrainEnd_Struct);
IN(OP_GMTrainSkill, GMSkillChange_Struct);
IN(OP_RequestDuel, Duel_Struct);
IN(OP_DuelDecline, DuelResponse_Struct);
IN(OP_DuelAccept, Duel_Struct);
IN(OP_DuelResponse, DuelResponse_Struct);
IN(OP_DuelResponse2, Duel_Struct);
IN(OP_SpawnAppearance, SpawnAppearance_Struct);
IN(OP_BazaarInspect, BazaarInspect_Struct);
IN(OP_Death, Death_Struct);
+2 -2
View File
@@ -240,8 +240,8 @@ void load_opcode_names()
opcode_map[0x00a1] = "LiveOP_SaveOnZoneReq";
opcode_map[0x0185] = "LiveOP_Logout";
opcode_map[0x0298] = "LiveOP_RequestDuel";
opcode_map[0x0a5d] = "LiveOP_DuelDecline";
opcode_map[0x016e] = "LiveOP_DuelAccept";
opcode_map[0x0a5d] = "LiveOP_DuelResponse";
opcode_map[0x016e] = "LiveOP_DuelResponse2";
opcode_map[0x007c] = "LiveOP_InstillDoubt";
opcode_map[0x00ac] = "LiveOP_SafeFallSuccess";
opcode_map[0x02fb] = "LiveOP_DisciplineUpdate";
-3
View File
@@ -184,9 +184,6 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
MOpcodes.lock();
res = emu_to_eq[emu_op];
MOpcodes.unlock();
LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res);
#ifdef DEBUG_TRANSLATE
fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
#endif
+70 -29
View File
@@ -11,7 +11,7 @@
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -28,12 +28,10 @@
#include "../eq_packet_structs.h"
#include "../misc_functions.h"
#include "../strings.h"
#include "../string_util.h"
#include "../inventory_profile.h"
#include "rof_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include <iostream>
#include <sstream>
@@ -54,13 +52,13 @@ namespace RoF
static inline structs::InventorySlot_Struct ServerToRoFCorpseSlot(uint32 server_corpse_slot);
static inline uint32 ServerToRoFCorpseMainSlot(uint32 server_corpse_slot);
static inline structs::TypelessInventorySlot_Struct ServerToRoFTypelessSlot(uint32 server_slot, int16 server_type);
// client to server inventory location converters
static inline uint32 RoFToServerSlot(structs::InventorySlot_Struct rof_slot);
static inline uint32 RoFToServerCorpseSlot(structs::InventorySlot_Struct rof_corpse_slot);
static inline uint32 RoFToServerCorpseMainSlot(uint32 rof_corpse_slot);
static inline uint32 RoFToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof_slot, int16 rof_type);
// server to client say link converter
static inline void ServerToRoFSayLink(std::string& rofSayLink, const std::string& serverSayLink);
@@ -77,8 +75,12 @@ namespace RoF
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -116,7 +118,12 @@ namespace RoF
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -729,6 +736,30 @@ namespace RoF
FINISH_ENCODE();
}
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning)
{
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1527,7 +1558,7 @@ namespace RoF
in->size = ob.size();
in->pBuffer = ob.detach();
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
@@ -1603,6 +1634,20 @@ namespace RoF
FINISH_ENCODE();
}
ENCODE(OP_ManaChange)
{
ENCODE_LENGTH_EXACT(ManaChange_Struct);
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
OUT(new_mana);
OUT(stamina);
OUT(spell_id);
OUT(keepcasting);
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
FINISH_ENCODE();
}
ENCODE(OP_MercenaryDataResponse)
{
//consume the packet
@@ -1807,10 +1852,10 @@ namespace RoF
OUT_str(zone_short_name2);
OUT(zone_id);
OUT(zone_instance);
OUT(suspend_buffs);
OUT(fast_regen_hp);
OUT(fast_regen_mana);
OUT(fast_regen_endurance);
OUT(SuspendBuffs);
OUT(FastRegenHP);
OUT(FastRegenMana);
OUT(FastRegenEndurance);
OUT(underworld_teleport_index);
eq->FogDensity = emu->fog_density;
@@ -1818,8 +1863,8 @@ namespace RoF
/*fill in some unknowns with observed values, hopefully it will help */
eq->unknown800 = -1;
eq->unknown844 = 600;
OUT(lava_damage);
OUT(min_lava_damage);
eq->unknown880 = 50;
eq->unknown884 = 10;
eq->unknown888 = 1;
eq->unknown889 = 0;
eq->unknown890 = 1;
@@ -3831,9 +3876,7 @@ namespace RoF
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
{
PacketSize += 60;
@@ -3965,9 +4008,7 @@ namespace RoF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{
@@ -5161,7 +5202,7 @@ namespace RoF
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type)
{
const EQ::ItemData *item = inst->GetUnscaledItem();
RoF::structs::ItemSerializationHeader hdr;
//sprintf(hdr.unknown000, "06e0002Y1W00");
@@ -5180,7 +5221,7 @@ namespace RoF
slot_id = ServerToRoFSlot(slot_id_in);
break;
}
hdr.slot_type = (inst->GetMerchantSlot() ? invtype::typeMerchant : slot_id.Type);
hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot);
hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex);
@@ -5268,7 +5309,7 @@ namespace RoF
ob.write("\0", 1);
ob.write("\0", 1);
RoF::structs::ItemBodyStruct ibs;
memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct));
@@ -5581,7 +5622,7 @@ namespace RoF
iqbs.unknown28 = 0;
iqbs.unknown30 = 0;
iqbs.unknown39 = 1;
ob.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct));
EQ::OutBuffer::pos_type count_pos = ob.tellp();
@@ -5749,7 +5790,7 @@ namespace RoF
static inline uint32 ServerToRoFCorpseMainSlot(uint32 server_corpse_slot)
{
uint32 RoFSlot = invslot::SLOT_INVALID;
if (server_corpse_slot <= EQ::invslot::CORPSE_END && server_corpse_slot >= EQ::invslot::CORPSE_BEGIN) {
RoFSlot = server_corpse_slot;
}
@@ -6096,7 +6137,7 @@ namespace RoF
return;
}
auto segments = Strings::Split(serverSayLink, '\x12');
auto segments = SplitString(serverSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
@@ -6135,7 +6176,7 @@ namespace RoF
return;
}
auto segments = Strings::Split(rofSayLink, '\x12');
auto segments = SplitString(rofSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
+100 -63
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -28,13 +28,10 @@
#include "../eq_packet_structs.h"
#include "../misc_functions.h"
#include "../strings.h"
#include "../string_util.h"
#include "../inventory_profile.h"
#include "rof2_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../classes.h"
#include "../races.h"
#include <iostream>
#include <sstream>
@@ -56,13 +53,13 @@ namespace RoF2
static inline structs::InventorySlot_Struct ServerToRoF2CorpseSlot(uint32 server_corpse_slot);
static inline uint32 ServerToRoF2CorpseMainSlot(uint32 server_corpse_slot);
static inline structs::TypelessInventorySlot_Struct ServerToRoF2TypelessSlot(uint32 server_slot, int16 server_type);
// client to server inventory location converters
static inline uint32 RoF2ToServerSlot(structs::InventorySlot_Struct rof2_slot);
static inline uint32 RoF2ToServerCorpseSlot(structs::InventorySlot_Struct rof2_corpse_slot);
static inline uint32 RoF2ToServerCorpseMainSlot(uint32 rof2_corpse_slot);
static inline uint32 RoF2ToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof2_slot, int16 rof2_type);
// server to client say link converter
static inline void ServerToRoF2SayLink(std::string &rof2_saylink, const std::string &server_saylink);
@@ -79,9 +76,12 @@ namespace RoF2
{
//create our opcode manager if we havent already
if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
//load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager();
@@ -122,7 +122,12 @@ namespace RoF2
//we need to go to every stream and replace it's manager.
if (opcodes != nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name);
//TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return;
@@ -780,6 +785,30 @@ namespace RoF2
FINISH_ENCODE();
}
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning)
{
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1654,6 +1683,20 @@ namespace RoF2
FINISH_ENCODE();
}
ENCODE(OP_ManaChange)
{
ENCODE_LENGTH_EXACT(ManaChange_Struct);
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
OUT(new_mana);
OUT(stamina);
OUT(spell_id);
OUT(keepcasting);
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
FINISH_ENCODE();
}
ENCODE(OP_MercenaryDataResponse)
{
//consume the packet
@@ -1858,13 +1901,13 @@ namespace RoF2
OUT_str(zone_short_name2);
OUT(zone_id);
OUT(zone_instance);
OUT(suspend_buffs);
OUT(fast_regen_hp);
OUT(fast_regen_mana);
OUT(fast_regen_endurance);
OUT(SuspendBuffs);
OUT(FastRegenHP);
OUT(FastRegenMana);
OUT(FastRegenEndurance);
OUT(underworld_teleport_index);
eq->fog_density = emu->fog_density;
eq->FogDensity = emu->fog_density;
/*fill in some unknowns with observed values, hopefully it will help */
eq->ZoneTimeZone = 0;
@@ -1876,22 +1919,22 @@ namespace RoF2
eq->SkyRelated2 = -1;
eq->NPCAggroMaxDist = 600;
eq->FilterID = 2008; // Guild Lobby observed value
OUT(lava_damage);
OUT(min_lava_damage);
eq->bDisallowManaStone = 1;
eq->bNoBind = 0;
eq->bNoAttack = 0;
eq->bNoCallOfHero = 0;
eq->bNoFlux = 0;
eq->bNoFear = 0;
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0;
eq->can_place_campsite = 2;
eq->can_place_guild_banner = 2;
eq->fishing_related = -1; // Set from PoK Example
eq->forage_related = -1; // Set from PoK Example
eq->b_no_levitate = 0;
eq->blooming = 1.0; // Set from PoK Example
eq->LavaDamage = 50;
eq->MinLavaDamage = 10;
eq->bDisallowManaStone = 1;
eq->bNoBind = 0;
eq->bNoAttack = 0;
eq->bNoCallOfHero = 0;
eq->bNoFlux = 0;
eq->bNoFear = 0;
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0;
eq->CanPlaceCampsite = 2;
eq->CanPlaceGuildBanner = 2;
eq->FishingRelated = -1; // Set from PoK Example
eq->ForageRelated = -1; // Set from PoK Example
eq->bNoLevitate = 0;
eq->Blooming = 1.0; // Set from PoK Example
FINISH_ENCODE();
}
@@ -2865,12 +2908,12 @@ namespace RoF2
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs
auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0;
auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size);
inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct));
std::vector<int32> skill;
std::vector<int32> points;
@@ -2933,7 +2976,7 @@ namespace RoF2
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
outapp->WriteUInt32(inapp->ReadUInt32()); // slot
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
@@ -3946,7 +3989,7 @@ namespace RoF2
if (strlen(emu->suffix))
PacketSize += strlen(emu->suffix) + 1;
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
if (emu->DestructibleObject || emu->class_ == 62)
{
if (emu->DestructibleObject)
PacketSize = PacketSize - 4; // No bodytype
@@ -3967,9 +4010,7 @@ namespace RoF2
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
{
PacketSize += 60;
@@ -4036,19 +4077,17 @@ namespace RoF2
// actually part of bitfields
uint8 OtherData = 0;
if (emu->class_ == LDON_TREASURE) //LDoN Chest
{
if (emu->class_ == 62) //LDoN Chest
OtherData = OtherData | 0x04;
}
if (strlen(emu->title)) {
if (strlen(emu->title))
OtherData = OtherData | 16;
}
if (strlen(emu->suffix)) {
if (strlen(emu->suffix))
OtherData = OtherData | 32;
}
if (emu->DestructibleObject) {
if (emu->DestructibleObject)
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
// float EmitterScalingRadius
@@ -4064,7 +4103,7 @@ namespace RoF2
// int DefaultEmitterID
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE)
if (emu->DestructibleObject || emu->class_ == 62)
{
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel);
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2);
@@ -4172,9 +4211,7 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{
@@ -5039,11 +5076,11 @@ namespace RoF2
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)");
emu->from_slot = RoF2ToServerSlot(eq->from_slot);
emu->to_slot = RoF2ToServerSlot(eq->to_slot);
IN(number_in_stack);
//LogNetcode("[RoF2] MoveItem Slot from [{}] to [{}], Number [{}]", emu->from_slot, emu->to_slot, emu->number_in_stack);
FINISH_DIRECT_DECODE();
@@ -5420,7 +5457,7 @@ namespace RoF2
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type)
{
const EQ::ItemData *item = inst->GetUnscaledItem();
RoF2::structs::ItemSerializationHeader hdr;
//sprintf(hdr.unknown000, "06e0002Y1W00");
@@ -5439,7 +5476,7 @@ namespace RoF2
slot_id = ServerToRoF2Slot(slot_id_in);
break;
}
hdr.slot_type = (inst->GetMerchantSlot() ? invtype::typeMerchant : slot_id.Type);
hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot);
hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex);
@@ -5527,7 +5564,7 @@ namespace RoF2
ob.write("\0", 1);
ob.write("\0", 1);
RoF2::structs::ItemBodyStruct ibs;
memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct));
@@ -5850,7 +5887,7 @@ namespace RoF2
iqbs.unknown37a = 0; // (guessed position) New to RoF2
iqbs.unknown38 = 0;
iqbs.unknown39 = 1;
ob.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct));
EQ::OutBuffer::pos_type count_pos = ob.tellp();
@@ -6050,7 +6087,7 @@ namespace RoF2
uint32 server_slot = EQ::invslot::SLOT_INVALID;
uint32 temp_slot = invslot::SLOT_INVALID;
switch (rof2_slot.Type) {
case invtype::typePossessions: {
if (rof2_slot.Slot >= invslot::POSSESSIONS_BEGIN && rof2_slot.Slot <= invslot::POSSESSIONS_END) {
@@ -6165,11 +6202,11 @@ namespace RoF2
static inline uint32 RoF2ToServerCorpseSlot(structs::InventorySlot_Struct rof2_corpse_slot)
{
uint32 ServerSlot = EQ::invslot::SLOT_INVALID;
if (rof2_corpse_slot.Type != invtype::typeCorpse || rof2_corpse_slot.SubIndex != invbag::SLOT_INVALID || rof2_corpse_slot.AugIndex != invaug::SOCKET_INVALID) {
ServerSlot = EQ::invslot::SLOT_INVALID;
}
else {
ServerSlot = RoF2ToServerCorpseMainSlot(rof2_corpse_slot.Slot);
}
@@ -6323,7 +6360,7 @@ namespace RoF2
return;
}
auto segments = Strings::Split(server_saylink, '\x12');
auto segments = SplitString(server_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
@@ -6355,7 +6392,7 @@ namespace RoF2
return;
}
auto segments = Strings::Split(rof2_saylink, '\x12');
auto segments = SplitString(rof2_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
+2 -2
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -19,7 +19,7 @@
#include "rof2_limits.h"
#include "../strings.h"
#include "../string_util.h"
int16 RoF2::invtype::GetInvTypeSize(int16 inv_type)

Some files were not shown because too many files have changed in this diff Show More