mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 04:52:29 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3259c98a9e | |||
| 02518cdae1 | |||
| a00ab6867c | |||
| f71a6bcb60 | |||
| 2e409f3898 | |||
| e29d7f4b27 | |||
| 4e548a588d | |||
| 5ed47b5e50 | |||
| e1e93a9a48 | |||
| 9c9d195ff6 |
+2
-13
@@ -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))
|
||||
@@ -54,5 +54,3 @@ bin/
|
||||
/Win32
|
||||
/x64
|
||||
/client_files/**/CMakeFiles/
|
||||
|
||||
.idea
|
||||
|
||||
+19
@@ -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
|
||||
+12
-75
@@ -1,4 +1,4 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.7)
|
||||
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 17)
|
||||
SET(CMAKE_CXX_STANDARD 14)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
@@ -20,7 +20,6 @@ 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)
|
||||
@@ -56,7 +55,6 @@ FIND_PACKAGE(MariaDB)
|
||||
FIND_PACKAGE(ZLIB)
|
||||
FIND_PACKAGE(OpenSSL)
|
||||
FIND_PACKAGE(Lua51)
|
||||
FIND_PACKAGE(LuaJit)
|
||||
FIND_PACKAGE(PerlLibs)
|
||||
FIND_PACKAGE(Sodium)
|
||||
FIND_PACKAGE(mbedTLS)
|
||||
@@ -89,12 +87,6 @@ ELSE()
|
||||
MESSAGE(STATUS "* Lua: MISSING *")
|
||||
ENDIF()
|
||||
|
||||
IF(LuaJit_FOUND)
|
||||
MESSAGE(STATUS "* LuaJIT: FOUND *")
|
||||
ELSE()
|
||||
MESSAGE(STATUS "* LuaJIT: MISSING *")
|
||||
ENDIF()
|
||||
|
||||
IF(PerlLibs_FOUND)
|
||||
MESSAGE(STATUS "* Perl: FOUND *")
|
||||
ELSE()
|
||||
@@ -122,6 +114,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)
|
||||
@@ -129,48 +122,6 @@ OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
|
||||
OPTION(EQEMU_BUILD_HC "Build the headless client." OFF)
|
||||
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)
|
||||
@@ -186,7 +137,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 +168,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 +190,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)
|
||||
@@ -267,12 +212,7 @@ ELSE()
|
||||
SET(SODIUM_LIBRARY_ENABLED OFF)
|
||||
ENDIF()
|
||||
|
||||
IF(LUAJIT_FOUND AND NOT (EQEMU_PREFER_LUA AND Lua51_FOUND))
|
||||
SET(LUA_LIBRARY_TYPE " LuaJIT")
|
||||
SET(LUA_LIBRARY_ENABLED ON)
|
||||
SET(LUA_LIBRARY_LIBS ${LUAJIT_LIBRARY} luabind)
|
||||
SET(LUA_LIBRARY_INCLUDE ${LUAJIT_INCLUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind")
|
||||
ELSEIF(Lua51_FOUND )
|
||||
IF(Lua51_FOUND)
|
||||
SET(LUA_LIBRARY_TYPE " Lua 5.1")
|
||||
SET(LUA_LIBRARY_ENABLED ON)
|
||||
SET(LUA_LIBRARY_LIBS ${LUA_LIBRARY} luabind)
|
||||
@@ -299,7 +239,6 @@ IF(ZLIB_FOUND)
|
||||
SET(ZLIB_LIBRARY_TYPE "zlib-ng")
|
||||
SET(ZLIB_LIBRARY_LIBS "zlibstatic")
|
||||
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng")
|
||||
ELSE()
|
||||
SET(ZLIB_LIBRARY_TYPE " zlib")
|
||||
SET(ZLIB_LIBRARY_LIBS ${ZLIB_LIBRARY})
|
||||
@@ -357,12 +296,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})
|
||||
SET(SERVER_LIBS ${SERVER_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)
|
||||
@@ -373,7 +312,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)
|
||||
@@ -395,8 +334,6 @@ IF(UNIX)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
SET(ZONE_LIBS ${ZONE_LIBS} ${SERVER_LIBS})
|
||||
|
||||
IF(EQEMU_BUILD_LOGIN AND NOT TLS_LIBRARY_ENABLED)
|
||||
MESSAGE(FATAL_ERROR "Login server requires a TLS Library to build.")
|
||||
ENDIF()
|
||||
@@ -410,13 +347,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")
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
We expect contributors and community members to act professionally and respectfully, and we expect our forums and Discord channels to be dignified environments that expand the community and enhance the learning experience for new members.
|
||||
|
||||
Specifically:
|
||||
|
||||
* Respect people, their ideas, and their work.
|
||||
* Be kind. Be courteous. Be welcoming.
|
||||
* Listen. Consider and acknowledge people's points before responding.
|
||||
* Be respectful of differing viewpoints and experience levels.
|
||||
* Accept constructive criticism and work together toward decisions.
|
||||
* Focus on what is best for the community and users.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of violent threats, trolling, insulting/derogatory comments, abusive or discriminatory language, or personal attacks.
|
||||
* Public or private harassment.
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission.
|
||||
* Conduct which could reasonably be considered inappropriate in a professional setting.
|
||||
* Advocating for or encouraging any of the above behaviors.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, forum posts, Discord messages, and other contributions that are not aligned with this code of conduct.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project.
|
||||
@@ -18,16 +18,16 @@
|
||||
|**Install 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)
|
||||
|
||||
+2
-2
@@ -16,6 +16,6 @@ build:
|
||||
verbosity: minimal
|
||||
after_build:
|
||||
- cmd: >-
|
||||
7z a build_x64-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll
|
||||
7z a build_x64-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb
|
||||
|
||||
appveyor PushArtifact build_x64-bots.zip
|
||||
appveyor PushArtifact build_x64-bots.zip
|
||||
@@ -16,6 +16,6 @@ build:
|
||||
verbosity: minimal
|
||||
after_build:
|
||||
- cmd: >-
|
||||
7z a build_x64-no-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll
|
||||
7z a build_x64-no-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb
|
||||
|
||||
appveyor PushArtifact build_x64-no-bots.zip
|
||||
appveyor PushArtifact build_x64-no-bots.zip
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
############################################
|
||||
#
|
||||
# New changelog can be found here
|
||||
# https://docs.eqemu.io/server/changelog/server
|
||||
# https://eqemu.gitbook.io/changelog/
|
||||
#
|
||||
############################################
|
||||
# Deprecated
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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')",
|
||||
|
||||
@@ -38,7 +38,7 @@ locations other than lua/
|
||||
find_path(LUA_INCLUDE_DIR lua.h
|
||||
HINTS
|
||||
ENV LUA_DIR
|
||||
PATH_SUFFIXES include/lua51 include/lua5.1 include/lua-5.1 include/lua include
|
||||
PATH_SUFFIXES include/lua51 include/lua5.1 include/lua-5.1 include/lua include/luajit include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
@@ -49,7 +49,7 @@ find_path(LUA_INCLUDE_DIR lua.h
|
||||
)
|
||||
|
||||
find_library(LUA_LIBRARY
|
||||
NAMES lua51 lua5.1 lua-5.1 lua
|
||||
NAMES lua51 lua5.1 lua-5.1 lua luajit
|
||||
HINTS
|
||||
ENV LUA_DIR
|
||||
PATH_SUFFIXES lib
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
# Modified from the FindLua51 that comes with CMake
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindLuaJit
|
||||
---------
|
||||
|
||||
|
||||
|
||||
Locate LuaJit library This module defines
|
||||
|
||||
::
|
||||
|
||||
LUAJIT_FOUND, if false, do not try to link to Lua
|
||||
LUAJIT_LIBRARIES
|
||||
LUAJIT_INCLUDE_DIR, where to find lua.h
|
||||
LUAJIT_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
|
||||
|
||||
|
||||
|
||||
Note that the expected include convention is
|
||||
|
||||
::
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
and not
|
||||
|
||||
::
|
||||
|
||||
#include <lua/lua.h>
|
||||
|
||||
This is because, the lua location is not standardized and may exist in
|
||||
locations other than lua/
|
||||
#]=======================================================================]
|
||||
|
||||
find_path(LUAJIT_INCLUDE_DIR lua.h
|
||||
HINTS
|
||||
ENV LUA_DIR
|
||||
PATH_SUFFIXES include/luajit include/luajit-2.0 include/luajit-2.1 include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
)
|
||||
|
||||
find_library(LUAJIT_LIBRARY
|
||||
NAMES luajit51 luajit5.1 luajit-5.1 luajit lua51
|
||||
HINTS
|
||||
ENV LUA_DIR
|
||||
PATH_SUFFIXES lib
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
|
||||
if(LUAJIT_LIBRARY)
|
||||
# include the math library for Unix
|
||||
if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU)
|
||||
find_library(LUAJIT_MATH_LIBRARY m)
|
||||
set( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY};${LUAJIT_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
|
||||
# For Windows and Mac, don't need to explicitly include the math library
|
||||
else()
|
||||
set( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}" CACHE STRING "Lua Libraries")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LUAJIT_INCLUDE_DIR AND EXISTS "${LUAJIT_INCLUDE_DIR}/lua.h")
|
||||
file(STRINGS "${LUAJIT_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"")
|
||||
|
||||
string(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUAJIT_VERSION_STRING "${lua_version_str}")
|
||||
unset(lua_version_str)
|
||||
endif()
|
||||
|
||||
include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJit
|
||||
REQUIRED_VARS LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR
|
||||
VERSION_VAR LUAJIT_VERSION_STRING)
|
||||
|
||||
mark_as_advanced(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARIES LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY)
|
||||
|
||||
+687
-745
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include "../database.h"
|
||||
#include "../rulesys.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include "../loottable.h"
|
||||
#include "../repositories/content_flags_repository.h"
|
||||
|
||||
|
||||
WorldContentService::WorldContentService()
|
||||
@@ -36,12 +34,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 +46,6 @@ WorldContentService *WorldContentService::SetExpansionContext()
|
||||
GetCurrentExpansion(),
|
||||
GetCurrentExpansionName()
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
std::string WorldContentService::GetCurrentExpansionName()
|
||||
@@ -80,47 +72,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,113 +89,13 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content_flag
|
||||
* @return
|
||||
*/
|
||||
bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
|
||||
{
|
||||
for (auto &f: GetContentFlags()) {
|
||||
if (f.flag_name == content_flag && f.enabled == false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../loottable.h"
|
||||
#include "../repositories/content_flags_repository.h"
|
||||
|
||||
class Database;
|
||||
|
||||
namespace Expansion {
|
||||
static const int EXPANSION_ALL = -1;
|
||||
@@ -54,7 +50,7 @@ namespace Expansion {
|
||||
VeilOfAlaris,
|
||||
RainOfFear,
|
||||
CallOfTheForsaken,
|
||||
TheDarkenedSea,
|
||||
TheDarkendSea,
|
||||
TheBrokenMirror,
|
||||
EmpiresOfKunark,
|
||||
RingOfScale,
|
||||
@@ -127,7 +123,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 +151,21 @@ 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 SetExpansionContext();
|
||||
};
|
||||
|
||||
extern WorldContentService content_service;
|
||||
|
||||
+2
-61
@@ -2,48 +2,6 @@
|
||||
#include "eqemu_logsys.h"
|
||||
#include "crash.h"
|
||||
|
||||
inline std::string random_string(size_t length)
|
||||
{
|
||||
auto randchar = []() -> char {
|
||||
const char charset[] = "0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
const size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[static_cast<size_t>(std::rand()) % max_index];
|
||||
};
|
||||
std::string str(length, 0);
|
||||
std::generate_n(str.begin(), length, randchar);
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string execute(const std::string &cmd, bool return_result = true)
|
||||
{
|
||||
std::string random = "/tmp/" + random_string(25);
|
||||
const char *file_name = random.c_str();
|
||||
|
||||
if (return_result) {
|
||||
#ifdef _WINDOWS
|
||||
std::system((cmd + " > " + file_name + " 2>&1").c_str());
|
||||
#else
|
||||
std::system((cmd + " > " + file_name + " 2>&1").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;
|
||||
}
|
||||
|
||||
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
|
||||
#include "StackWalker.h"
|
||||
|
||||
@@ -167,28 +125,10 @@ void set_exception_handler() {
|
||||
|
||||
void print_trace()
|
||||
{
|
||||
bool does_gdb_exist = execute("gdb -v").find("GNU") != std::string::npos;
|
||||
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 = "/tmp/dump-output";
|
||||
|
||||
// check for passwordless sudo if not root
|
||||
if (uid != 0) {
|
||||
bool has_passwordless_sudo = execute("sudo -n true").find("a password is required") == std::string::npos;
|
||||
if (!has_passwordless_sudo) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
char pid_buf[30];
|
||||
sprintf(pid_buf, "%d", getpid());
|
||||
char name_buf[512];
|
||||
@@ -196,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) {
|
||||
|
||||
@@ -1,876 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
#include <cctype>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
#include <string_view>
|
||||
#define CRONCPP_IS_CPP17
|
||||
#endif
|
||||
|
||||
namespace cron
|
||||
{
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
#define HAS_STRING_VIEW
|
||||
#define STRING_VIEW std::string_view
|
||||
#define STRING_VIEW_NPOS std::string_view::npos
|
||||
#define CONSTEXPTR constexpr
|
||||
#else
|
||||
#define STRING_VIEW std::string const &
|
||||
#define STRING_VIEW_NPOS std::string::npos
|
||||
#define CONSTEXPTR
|
||||
#endif
|
||||
|
||||
using cron_int = uint8_t;
|
||||
|
||||
constexpr std::time_t INVALID_TIME = static_cast<std::time_t>(-1);
|
||||
|
||||
constexpr size_t INVALID_CRON_INDEX = static_cast<size_t>(-1);
|
||||
|
||||
class cronexpr;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
enum class cron_field
|
||||
{
|
||||
second,
|
||||
minute,
|
||||
hour_of_day,
|
||||
day_of_week,
|
||||
day_of_month,
|
||||
month,
|
||||
year
|
||||
};
|
||||
|
||||
template <typename Traits>
|
||||
static bool find_next(cronexpr const & cex,
|
||||
std::tm& date,
|
||||
size_t const dot);
|
||||
}
|
||||
|
||||
struct bad_cronexpr : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit bad_cronexpr(STRING_VIEW message) :
|
||||
std::runtime_error(message.data())
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct cron_standard_traits
|
||||
{
|
||||
static const cron_int CRON_MIN_SECONDS = 0;
|
||||
static const cron_int CRON_MAX_SECONDS = 59;
|
||||
|
||||
static const cron_int CRON_MIN_MINUTES = 0;
|
||||
static const cron_int CRON_MAX_MINUTES = 59;
|
||||
|
||||
static const cron_int CRON_MIN_HOURS = 0;
|
||||
static const cron_int CRON_MAX_HOURS = 23;
|
||||
|
||||
static const cron_int CRON_MIN_DAYS_OF_WEEK = 0;
|
||||
static const cron_int CRON_MAX_DAYS_OF_WEEK = 6;
|
||||
|
||||
static const cron_int CRON_MIN_DAYS_OF_MONTH = 1;
|
||||
static const cron_int CRON_MAX_DAYS_OF_MONTH = 31;
|
||||
|
||||
static const cron_int CRON_MIN_MONTHS = 1;
|
||||
static const cron_int CRON_MAX_MONTHS = 12;
|
||||
|
||||
static const cron_int CRON_MAX_YEARS_DIFF = 4;
|
||||
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
static const inline std::vector<std::string> DAYS = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
|
||||
static const inline std::vector<std::string> MONTHS = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
|
||||
#else
|
||||
static std::vector<std::string>& DAYS()
|
||||
{
|
||||
static std::vector<std::string> days = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
|
||||
return days;
|
||||
}
|
||||
|
||||
static std::vector<std::string>& MONTHS()
|
||||
{
|
||||
static std::vector<std::string> months = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
|
||||
return months;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct cron_oracle_traits
|
||||
{
|
||||
static const cron_int CRON_MIN_SECONDS = 0;
|
||||
static const cron_int CRON_MAX_SECONDS = 59;
|
||||
|
||||
static const cron_int CRON_MIN_MINUTES = 0;
|
||||
static const cron_int CRON_MAX_MINUTES = 59;
|
||||
|
||||
static const cron_int CRON_MIN_HOURS = 0;
|
||||
static const cron_int CRON_MAX_HOURS = 23;
|
||||
|
||||
static const cron_int CRON_MIN_DAYS_OF_WEEK = 1;
|
||||
static const cron_int CRON_MAX_DAYS_OF_WEEK = 7;
|
||||
|
||||
static const cron_int CRON_MIN_DAYS_OF_MONTH = 1;
|
||||
static const cron_int CRON_MAX_DAYS_OF_MONTH = 31;
|
||||
|
||||
static const cron_int CRON_MIN_MONTHS = 0;
|
||||
static const cron_int CRON_MAX_MONTHS = 11;
|
||||
|
||||
static const cron_int CRON_MAX_YEARS_DIFF = 4;
|
||||
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
static const inline std::vector<std::string> DAYS = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
|
||||
static const inline std::vector<std::string> MONTHS = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
|
||||
#else
|
||||
|
||||
static std::vector<std::string>& DAYS()
|
||||
{
|
||||
static std::vector<std::string> days = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
|
||||
return days;
|
||||
}
|
||||
|
||||
static std::vector<std::string>& MONTHS()
|
||||
{
|
||||
static std::vector<std::string> months = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
|
||||
return months;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct cron_quartz_traits
|
||||
{
|
||||
static const cron_int CRON_MIN_SECONDS = 0;
|
||||
static const cron_int CRON_MAX_SECONDS = 59;
|
||||
|
||||
static const cron_int CRON_MIN_MINUTES = 0;
|
||||
static const cron_int CRON_MAX_MINUTES = 59;
|
||||
|
||||
static const cron_int CRON_MIN_HOURS = 0;
|
||||
static const cron_int CRON_MAX_HOURS = 23;
|
||||
|
||||
static const cron_int CRON_MIN_DAYS_OF_WEEK = 1;
|
||||
static const cron_int CRON_MAX_DAYS_OF_WEEK = 7;
|
||||
|
||||
static const cron_int CRON_MIN_DAYS_OF_MONTH = 1;
|
||||
static const cron_int CRON_MAX_DAYS_OF_MONTH = 31;
|
||||
|
||||
static const cron_int CRON_MIN_MONTHS = 1;
|
||||
static const cron_int CRON_MAX_MONTHS = 12;
|
||||
|
||||
static const cron_int CRON_MAX_YEARS_DIFF = 4;
|
||||
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
static const inline std::vector<std::string> DAYS = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
|
||||
static const inline std::vector<std::string> MONTHS = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
|
||||
#else
|
||||
static std::vector<std::string>& DAYS()
|
||||
{
|
||||
static std::vector<std::string> days = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
|
||||
return days;
|
||||
}
|
||||
|
||||
static std::vector<std::string>& MONTHS()
|
||||
{
|
||||
static std::vector<std::string> months = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
|
||||
return months;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class cronexpr;
|
||||
|
||||
template <typename Traits = cron_standard_traits>
|
||||
static cronexpr make_cron(STRING_VIEW expr);
|
||||
|
||||
class cronexpr
|
||||
{
|
||||
std::bitset<60> seconds;
|
||||
std::bitset<60> minutes;
|
||||
std::bitset<24> hours;
|
||||
std::bitset<7> days_of_week;
|
||||
std::bitset<31> days_of_month;
|
||||
std::bitset<12> months;
|
||||
|
||||
friend bool operator==(cronexpr const & e1, cronexpr const & e2);
|
||||
friend bool operator!=(cronexpr const & e1, cronexpr const & e2);
|
||||
|
||||
template <typename Traits>
|
||||
friend bool detail::find_next(cronexpr const & cex,
|
||||
std::tm& date,
|
||||
size_t const dot);
|
||||
|
||||
friend std::string to_string(cronexpr const & cex);
|
||||
|
||||
template <typename Traits>
|
||||
friend cronexpr make_cron(STRING_VIEW expr);
|
||||
};
|
||||
|
||||
inline bool operator==(cronexpr const & e1, cronexpr const & e2)
|
||||
{
|
||||
return
|
||||
e1.seconds == e2.seconds &&
|
||||
e1.minutes == e2.minutes &&
|
||||
e1.hours == e2.hours &&
|
||||
e1.days_of_week == e2.days_of_week &&
|
||||
e1.days_of_month == e2.days_of_month &&
|
||||
e1.months == e2.months;
|
||||
}
|
||||
|
||||
inline bool operator!=(cronexpr const & e1, cronexpr const & e2)
|
||||
{
|
||||
return !(e1 == e2);
|
||||
}
|
||||
|
||||
inline std::string to_string(cronexpr const & cex)
|
||||
{
|
||||
return
|
||||
cex.seconds.to_string() + " " +
|
||||
cex.minutes.to_string() + " " +
|
||||
cex.hours.to_string() + " " +
|
||||
cex.days_of_month.to_string() + " " +
|
||||
cex.months.to_string() + " " +
|
||||
cex.days_of_week.to_string();
|
||||
}
|
||||
|
||||
namespace utils
|
||||
{
|
||||
inline std::time_t tm_to_time(std::tm& date)
|
||||
{
|
||||
return std::mktime(&date);
|
||||
}
|
||||
|
||||
inline std::tm* time_to_tm(std::time_t const * date, std::tm* const out)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
errno_t err = localtime_s(out, date);
|
||||
return 0 == err ? out : nullptr;
|
||||
#else
|
||||
return localtime_r(date, out);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline std::tm to_tm(STRING_VIEW time)
|
||||
{
|
||||
std::istringstream str(time.data());
|
||||
str.imbue(std::locale(setlocale(LC_ALL, nullptr)));
|
||||
|
||||
std::tm result;
|
||||
str >> std::get_time(&result, "%Y-%m-%d %H:%M:%S");
|
||||
if (str.fail()) throw std::runtime_error("Parsing date failed!");
|
||||
|
||||
result.tm_isdst = -1; // DST info not available
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string to_string(std::tm const & tm)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str.imbue(std::locale(setlocale(LC_ALL, nullptr)));
|
||||
str << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
|
||||
if (str.fail()) throw std::runtime_error("Writing date failed!");
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
inline std::string to_upper(std::string text)
|
||||
{
|
||||
std::transform(std::begin(text), std::end(text),
|
||||
std::begin(text), static_cast<int(*)(int)>(std::toupper));
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static std::vector<std::string> split(STRING_VIEW text, char const delimiter)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
std::string token;
|
||||
std::istringstream tokenStream(text.data());
|
||||
while (std::getline(tokenStream, token, delimiter))
|
||||
{
|
||||
tokens.push_back(token);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
CONSTEXPTR inline bool contains(STRING_VIEW text, char const ch) noexcept
|
||||
{
|
||||
return STRING_VIEW_NPOS != text.find_first_of(ch);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline cron_int to_cron_int(STRING_VIEW text)
|
||||
{
|
||||
try
|
||||
{
|
||||
return static_cast<cron_int>(std::stoul(text.data()));
|
||||
}
|
||||
catch (std::exception const & ex)
|
||||
{
|
||||
throw bad_cronexpr(ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
static std::string replace_ordinals(
|
||||
std::string text,
|
||||
std::vector<std::string> const & replacement)
|
||||
{
|
||||
for (size_t i = 0; i < replacement.size(); ++i)
|
||||
{
|
||||
auto pos = text.find(replacement[i]);
|
||||
if (std::string::npos != pos)
|
||||
text.replace(pos, 3 ,std::to_string(i));
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static std::pair<cron_int, cron_int> make_range(
|
||||
STRING_VIEW field,
|
||||
cron_int const minval,
|
||||
cron_int const maxval)
|
||||
{
|
||||
cron_int first = 0;
|
||||
cron_int last = 0;
|
||||
if (field.size() == 1 && field[0] == '*')
|
||||
{
|
||||
first = minval;
|
||||
last = maxval;
|
||||
}
|
||||
else if (!utils::contains(field, '-'))
|
||||
{
|
||||
first = to_cron_int(field);
|
||||
last = first;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto parts = utils::split(field, '-');
|
||||
if (parts.size() != 2)
|
||||
throw bad_cronexpr("Specified range requires two fields");
|
||||
|
||||
first = to_cron_int(parts[0]);
|
||||
last = to_cron_int(parts[1]);
|
||||
}
|
||||
|
||||
if (first > maxval || last > maxval)
|
||||
{
|
||||
throw bad_cronexpr("Specified range exceeds maximum");
|
||||
}
|
||||
if (first < minval || last < minval)
|
||||
{
|
||||
throw bad_cronexpr("Specified range is less than minimum");
|
||||
}
|
||||
if (first > last)
|
||||
{
|
||||
throw bad_cronexpr("Specified range start exceeds range end");
|
||||
}
|
||||
|
||||
return { first, last };
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static void set_cron_field(
|
||||
STRING_VIEW value,
|
||||
std::bitset<N>& target,
|
||||
cron_int const minval,
|
||||
cron_int const maxval)
|
||||
{
|
||||
if(value.length() > 0 && value[value.length()-1] == ',')
|
||||
throw bad_cronexpr("Value cannot end with comma");
|
||||
|
||||
auto fields = utils::split(value, ',');
|
||||
if (fields.empty())
|
||||
throw bad_cronexpr("Expression parsing error");
|
||||
|
||||
for (auto const & field : fields)
|
||||
{
|
||||
if (!utils::contains(field, '/'))
|
||||
{
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
auto[first, last] = detail::make_range(field, minval, maxval);
|
||||
#else
|
||||
auto range = detail::make_range(field, minval, maxval);
|
||||
auto first = range.first;
|
||||
auto last = range.second;
|
||||
#endif
|
||||
for (cron_int i = first - minval; i <= last - minval; ++i)
|
||||
{
|
||||
target.set(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto parts = utils::split(field, '/');
|
||||
if (parts.size() != 2)
|
||||
throw bad_cronexpr("Incrementer must have two fields");
|
||||
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
auto[first, last] = detail::make_range(parts[0], minval, maxval);
|
||||
#else
|
||||
auto range = detail::make_range(parts[0], minval, maxval);
|
||||
auto first = range.first;
|
||||
auto last = range.second;
|
||||
#endif
|
||||
|
||||
if (!utils::contains(parts[0], '-'))
|
||||
{
|
||||
last = maxval;
|
||||
}
|
||||
|
||||
auto delta = detail::to_cron_int(parts[1]);
|
||||
if(delta <= 0)
|
||||
throw bad_cronexpr("Incrementer must be a positive value");
|
||||
|
||||
for (cron_int i = first - minval; i <= last - minval; i += delta)
|
||||
{
|
||||
target.set(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
static void set_cron_days_of_week(
|
||||
std::string value,
|
||||
std::bitset<7>& target)
|
||||
{
|
||||
auto days = utils::to_upper(value);
|
||||
auto days_replaced = detail::replace_ordinals(
|
||||
days,
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
Traits::DAYS
|
||||
#else
|
||||
Traits::DAYS()
|
||||
#endif
|
||||
);
|
||||
|
||||
if (days_replaced.size() == 1 && days_replaced[0] == '?')
|
||||
days_replaced[0] = '*';
|
||||
|
||||
set_cron_field(
|
||||
days_replaced,
|
||||
target,
|
||||
Traits::CRON_MIN_DAYS_OF_WEEK,
|
||||
Traits::CRON_MAX_DAYS_OF_WEEK);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
static void set_cron_days_of_month(
|
||||
std::string value,
|
||||
std::bitset<31>& target)
|
||||
{
|
||||
if (value.size() == 1 && value[0] == '?')
|
||||
value[0] = '*';
|
||||
|
||||
set_cron_field(
|
||||
value,
|
||||
target,
|
||||
Traits::CRON_MIN_DAYS_OF_MONTH,
|
||||
Traits::CRON_MAX_DAYS_OF_MONTH);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
static void set_cron_month(
|
||||
std::string value,
|
||||
std::bitset<12>& target)
|
||||
{
|
||||
auto month = utils::to_upper(value);
|
||||
auto month_replaced = replace_ordinals(
|
||||
month,
|
||||
#ifdef CRONCPP_IS_CPP17
|
||||
Traits::MONTHS
|
||||
#else
|
||||
Traits::MONTHS()
|
||||
#endif
|
||||
);
|
||||
|
||||
set_cron_field(
|
||||
month_replaced,
|
||||
target,
|
||||
Traits::CRON_MIN_MONTHS,
|
||||
Traits::CRON_MAX_MONTHS);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
inline size_t next_set_bit(
|
||||
std::bitset<N> const & target,
|
||||
size_t /*minimum*/,
|
||||
size_t /*maximum*/,
|
||||
size_t offset)
|
||||
{
|
||||
for (auto i = offset; i < N; ++i)
|
||||
{
|
||||
if (target.test(i)) return i;
|
||||
}
|
||||
|
||||
return INVALID_CRON_INDEX;
|
||||
}
|
||||
|
||||
inline void add_to_field(
|
||||
std::tm& date,
|
||||
cron_field const field,
|
||||
int const val)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case cron_field::second:
|
||||
date.tm_sec += val;
|
||||
break;
|
||||
case cron_field::minute:
|
||||
date.tm_min += val;
|
||||
break;
|
||||
case cron_field::hour_of_day:
|
||||
date.tm_hour += val;
|
||||
break;
|
||||
case cron_field::day_of_week:
|
||||
case cron_field::day_of_month:
|
||||
date.tm_mday += val;
|
||||
break;
|
||||
case cron_field::month:
|
||||
date.tm_mon += val;
|
||||
break;
|
||||
case cron_field::year:
|
||||
date.tm_year += val;
|
||||
break;
|
||||
}
|
||||
|
||||
if (INVALID_TIME == utils::tm_to_time(date))
|
||||
throw bad_cronexpr("Invalid time expression");
|
||||
}
|
||||
|
||||
inline void set_field(
|
||||
std::tm& date,
|
||||
cron_field const field,
|
||||
int const val)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case cron_field::second:
|
||||
date.tm_sec = val;
|
||||
break;
|
||||
case cron_field::minute:
|
||||
date.tm_min = val;
|
||||
break;
|
||||
case cron_field::hour_of_day:
|
||||
date.tm_hour = val;
|
||||
break;
|
||||
case cron_field::day_of_week:
|
||||
date.tm_wday = val;
|
||||
break;
|
||||
case cron_field::day_of_month:
|
||||
date.tm_mday = val;
|
||||
break;
|
||||
case cron_field::month:
|
||||
date.tm_mon = val;
|
||||
break;
|
||||
case cron_field::year:
|
||||
date.tm_year = val;
|
||||
break;
|
||||
}
|
||||
|
||||
if (INVALID_TIME == utils::tm_to_time(date))
|
||||
throw bad_cronexpr("Invalid time expression");
|
||||
}
|
||||
|
||||
inline void reset_field(
|
||||
std::tm& date,
|
||||
cron_field const field)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case cron_field::second:
|
||||
date.tm_sec = 0;
|
||||
break;
|
||||
case cron_field::minute:
|
||||
date.tm_min = 0;
|
||||
break;
|
||||
case cron_field::hour_of_day:
|
||||
date.tm_hour = 0;
|
||||
break;
|
||||
case cron_field::day_of_week:
|
||||
date.tm_wday = 0;
|
||||
break;
|
||||
case cron_field::day_of_month:
|
||||
date.tm_mday = 1;
|
||||
break;
|
||||
case cron_field::month:
|
||||
date.tm_mon = 0;
|
||||
break;
|
||||
case cron_field::year:
|
||||
date.tm_year = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (INVALID_TIME == utils::tm_to_time(date))
|
||||
throw bad_cronexpr("Invalid time expression");
|
||||
}
|
||||
|
||||
inline void reset_all_fields(
|
||||
std::tm& date,
|
||||
std::bitset<7> const & marked_fields)
|
||||
{
|
||||
for (size_t i = 0; i < marked_fields.size(); ++i)
|
||||
{
|
||||
if (marked_fields.test(i))
|
||||
reset_field(date, static_cast<cron_field>(i));
|
||||
}
|
||||
}
|
||||
|
||||
inline void mark_field(
|
||||
std::bitset<7> & orders,
|
||||
cron_field const field)
|
||||
{
|
||||
if (!orders.test(static_cast<size_t>(field)))
|
||||
orders.set(static_cast<size_t>(field));
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static size_t find_next(
|
||||
std::bitset<N> const & target,
|
||||
std::tm& date,
|
||||
unsigned int const minimum,
|
||||
unsigned int const maximum,
|
||||
unsigned int const value,
|
||||
cron_field const field,
|
||||
cron_field const next_field,
|
||||
std::bitset<7> const & marked_fields)
|
||||
{
|
||||
auto next_value = next_set_bit(target, minimum, maximum, value);
|
||||
if (INVALID_CRON_INDEX == next_value)
|
||||
{
|
||||
add_to_field(date, next_field, 1);
|
||||
reset_field(date, field);
|
||||
next_value = next_set_bit(target, minimum, maximum, 0);
|
||||
}
|
||||
|
||||
if (INVALID_CRON_INDEX == next_value || next_value != value)
|
||||
{
|
||||
set_field(date, field, static_cast<int>(next_value));
|
||||
reset_all_fields(date, marked_fields);
|
||||
}
|
||||
|
||||
return next_value;
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
static size_t find_next_day(
|
||||
std::tm& date,
|
||||
std::bitset<31> const & days_of_month,
|
||||
size_t day_of_month,
|
||||
std::bitset<7> const & days_of_week,
|
||||
size_t day_of_week,
|
||||
std::bitset<7> const & marked_fields)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned int maximum = 366;
|
||||
while (
|
||||
(!days_of_month.test(day_of_month - Traits::CRON_MIN_DAYS_OF_MONTH) ||
|
||||
!days_of_week.test(day_of_week - Traits::CRON_MIN_DAYS_OF_WEEK))
|
||||
&& count++ < maximum)
|
||||
{
|
||||
add_to_field(date, cron_field::day_of_month, 1);
|
||||
|
||||
day_of_month = date.tm_mday;
|
||||
day_of_week = date.tm_wday;
|
||||
|
||||
reset_all_fields(date, marked_fields);
|
||||
}
|
||||
|
||||
return day_of_month;
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
static bool find_next(cronexpr const & cex,
|
||||
std::tm& date,
|
||||
size_t const dot)
|
||||
{
|
||||
bool res = true;
|
||||
|
||||
std::bitset<7> marked_fields{ 0 };
|
||||
std::bitset<7> empty_list{ 0 };
|
||||
|
||||
unsigned int second = date.tm_sec;
|
||||
auto updated_second = find_next(
|
||||
cex.seconds,
|
||||
date,
|
||||
Traits::CRON_MIN_SECONDS,
|
||||
Traits::CRON_MAX_SECONDS,
|
||||
second,
|
||||
cron_field::second,
|
||||
cron_field::minute,
|
||||
empty_list);
|
||||
|
||||
if (second == updated_second)
|
||||
{
|
||||
mark_field(marked_fields, cron_field::second);
|
||||
}
|
||||
|
||||
unsigned int minute = date.tm_min;
|
||||
auto update_minute = find_next(
|
||||
cex.minutes,
|
||||
date,
|
||||
Traits::CRON_MIN_MINUTES,
|
||||
Traits::CRON_MAX_MINUTES,
|
||||
minute,
|
||||
cron_field::minute,
|
||||
cron_field::hour_of_day,
|
||||
marked_fields);
|
||||
if (minute == update_minute)
|
||||
{
|
||||
mark_field(marked_fields, cron_field::minute);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = find_next<Traits>(cex, date, dot);
|
||||
if (!res) return res;
|
||||
}
|
||||
|
||||
unsigned int hour = date.tm_hour;
|
||||
auto updated_hour = find_next(
|
||||
cex.hours,
|
||||
date,
|
||||
Traits::CRON_MIN_HOURS,
|
||||
Traits::CRON_MAX_HOURS,
|
||||
hour,
|
||||
cron_field::hour_of_day,
|
||||
cron_field::day_of_week,
|
||||
marked_fields);
|
||||
if (hour == updated_hour)
|
||||
{
|
||||
mark_field(marked_fields, cron_field::hour_of_day);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = find_next<Traits>(cex, date, dot);
|
||||
if (!res) return res;
|
||||
}
|
||||
|
||||
unsigned int day_of_week = date.tm_wday;
|
||||
unsigned int day_of_month = date.tm_mday;
|
||||
auto updated_day_of_month = find_next_day<Traits>(
|
||||
date,
|
||||
cex.days_of_month,
|
||||
day_of_month,
|
||||
cex.days_of_week,
|
||||
day_of_week,
|
||||
marked_fields);
|
||||
if (day_of_month == updated_day_of_month)
|
||||
{
|
||||
mark_field(marked_fields, cron_field::day_of_month);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = find_next<Traits>(cex, date, dot);
|
||||
if (!res) return res;
|
||||
}
|
||||
|
||||
unsigned int month = date.tm_mon;
|
||||
auto updated_month = find_next(
|
||||
cex.months,
|
||||
date,
|
||||
Traits::CRON_MIN_MONTHS,
|
||||
Traits::CRON_MAX_MONTHS,
|
||||
month,
|
||||
cron_field::month,
|
||||
cron_field::year,
|
||||
marked_fields);
|
||||
if (month != updated_month)
|
||||
{
|
||||
if (date.tm_year - dot > Traits::CRON_MAX_YEARS_DIFF)
|
||||
return false;
|
||||
|
||||
res = find_next<Traits>(cex, date, dot);
|
||||
if (!res) return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
static cronexpr make_cron(STRING_VIEW expr)
|
||||
{
|
||||
cronexpr cex;
|
||||
|
||||
if (expr.empty())
|
||||
throw bad_cronexpr("Invalid empty cron expression");
|
||||
|
||||
auto fields = utils::split(expr, ' ');
|
||||
fields.erase(
|
||||
std::remove_if(std::begin(fields), std::end(fields),
|
||||
[](STRING_VIEW s) {return s.empty(); }),
|
||||
std::end(fields));
|
||||
if (fields.size() != 6)
|
||||
throw bad_cronexpr("cron expression must have six fields");
|
||||
|
||||
detail::set_cron_field(fields[0], cex.seconds, Traits::CRON_MIN_SECONDS, Traits::CRON_MAX_SECONDS);
|
||||
detail::set_cron_field(fields[1], cex.minutes, Traits::CRON_MIN_MINUTES, Traits::CRON_MAX_MINUTES);
|
||||
detail::set_cron_field(fields[2], cex.hours, Traits::CRON_MIN_HOURS, Traits::CRON_MAX_HOURS);
|
||||
|
||||
detail::set_cron_days_of_week<Traits>(fields[5], cex.days_of_week);
|
||||
|
||||
detail::set_cron_days_of_month<Traits>(fields[3], cex.days_of_month);
|
||||
|
||||
detail::set_cron_month<Traits>(fields[4], cex.months);
|
||||
|
||||
return cex;
|
||||
}
|
||||
|
||||
template <typename Traits = cron_standard_traits>
|
||||
static std::tm cron_next(cronexpr const & cex, std::tm date)
|
||||
{
|
||||
time_t original = utils::tm_to_time(date);
|
||||
if (INVALID_TIME == original) return {};
|
||||
|
||||
if (!detail::find_next<Traits>(cex, date, date.tm_year))
|
||||
return {};
|
||||
|
||||
time_t calculated = utils::tm_to_time(date);
|
||||
if (INVALID_TIME == calculated) return {};
|
||||
|
||||
if (calculated == original)
|
||||
{
|
||||
add_to_field(date, detail::cron_field::second, 1);
|
||||
if (!detail::find_next<Traits>(cex, date, date.tm_year))
|
||||
return {};
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
template <typename Traits = cron_standard_traits>
|
||||
static std::time_t cron_next(cronexpr const & cex, std::time_t const & date)
|
||||
{
|
||||
std::tm val;
|
||||
std::tm* dt = utils::time_to_tm(&date, &val);
|
||||
if (dt == nullptr) return INVALID_TIME;
|
||||
|
||||
time_t original = utils::tm_to_time(*dt);
|
||||
if (INVALID_TIME == original) return INVALID_TIME;
|
||||
|
||||
if(!detail::find_next<Traits>(cex, *dt, dt->tm_year))
|
||||
return INVALID_TIME;
|
||||
|
||||
time_t calculated = utils::tm_to_time(*dt);
|
||||
if (INVALID_TIME == calculated) return calculated;
|
||||
|
||||
if (calculated == original)
|
||||
{
|
||||
add_to_field(*dt, detail::cron_field::second, 1);
|
||||
if(!detail::find_next<Traits>(cex, *dt, dt->tm_year))
|
||||
return INVALID_TIME;
|
||||
}
|
||||
|
||||
return utils::tm_to_time(*dt);
|
||||
}
|
||||
}
|
||||
+448
-426
File diff suppressed because it is too large
Load Diff
+44
-28
@@ -45,6 +45,24 @@ namespace EQ
|
||||
class InventoryProfile;
|
||||
}
|
||||
|
||||
struct EventLogDetails_Struct {
|
||||
uint32 id;
|
||||
char accountname[64];
|
||||
uint32 account_id;
|
||||
int16 status;
|
||||
char charactername[64];
|
||||
char targetname[64];
|
||||
char timestamp[64];
|
||||
char descriptiontype[64];
|
||||
char details[128];
|
||||
};
|
||||
|
||||
struct CharacterEventLog_Struct {
|
||||
uint32 count;
|
||||
uint8 eventid;
|
||||
EventLogDetails_Struct eld[255];
|
||||
};
|
||||
|
||||
struct npcDecayTimes_Struct {
|
||||
uint16 minlvl;
|
||||
uint16 maxlvl;
|
||||
@@ -78,7 +96,6 @@ class PTimerList;
|
||||
|
||||
#define SQL(...) #__VA_ARGS__
|
||||
|
||||
class LogSettings;
|
||||
class Database : public DBcore {
|
||||
public:
|
||||
Database();
|
||||
@@ -88,6 +105,7 @@ public:
|
||||
|
||||
/* Character Creation */
|
||||
|
||||
bool AddToNameFilter(const char *name);
|
||||
bool CreateCharacter(
|
||||
uint32 account_id,
|
||||
char *name,
|
||||
@@ -110,38 +128,36 @@ public:
|
||||
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp);
|
||||
bool SetHackerFlag(const char *accountname, const char *charactername, const char *hacked);
|
||||
bool SetMQDetectionFlag(const char *accountname, const char *charactername, const char *hacked, const char *zone);
|
||||
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);
|
||||
|
||||
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
|
||||
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);
|
||||
const char *GetCharNameByID(uint32 char_id);
|
||||
const char *GetNPCNameByID(uint32 npc_id);
|
||||
void LoginIP(uint32 AccountID, const char* LoginIP);
|
||||
|
||||
/* Instancing */
|
||||
|
||||
@@ -175,7 +191,7 @@ public:
|
||||
|
||||
/* 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 GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
|
||||
|
||||
/* Account Related */
|
||||
@@ -189,8 +205,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);
|
||||
@@ -199,16 +213,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);
|
||||
|
||||
@@ -246,11 +259,14 @@ public:
|
||||
|
||||
/* General Queries */
|
||||
|
||||
bool GetSafePoints(const char* short_name, uint32 version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 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);
|
||||
@@ -268,8 +284,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:
|
||||
|
||||
|
||||
@@ -23,10 +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 "../file_util.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@@ -119,7 +119,7 @@ std::string DatabaseDumpService::GetMySQLVersion()
|
||||
{
|
||||
std::string version_output = execute("mysql --version");
|
||||
|
||||
return Strings::Trim(version_output);
|
||||
return trim(version_output);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +174,7 @@ std::string DatabaseDumpService::GetLoginTableList()
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Trim(tables_list);
|
||||
return trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,7 +188,7 @@ std::string DatabaseDumpService::GetQueryServTables()
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Trim(tables_list);
|
||||
return trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +208,7 @@ std::string DatabaseDumpService::GetSystemTablesList()
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Trim(tables_list);
|
||||
return trim(tables_list);
|
||||
}
|
||||
/**
|
||||
* @return
|
||||
@@ -236,7 +222,7 @@ std::string DatabaseDumpService::GetStateTablesList()
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Trim(tables_list);
|
||||
return trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,7 +237,7 @@ std::string DatabaseDumpService::GetContentTablesList()
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Trim(tables_list);
|
||||
return trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +300,8 @@ void DatabaseDumpService::Dump()
|
||||
config->DatabaseUsername
|
||||
);
|
||||
|
||||
std::string options = "--allow-keywords --extended-insert --max-allowed-packet=1G --net-buffer-length=32704";
|
||||
std::string options = "--allow-keywords --extended-insert";
|
||||
|
||||
if (IsDumpWithNoData()) {
|
||||
options += " --no-data";
|
||||
}
|
||||
@@ -332,11 +319,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";
|
||||
@@ -383,12 +365,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;
|
||||
@@ -455,7 +437,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
|
||||
@@ -597,13 +578,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;
|
||||
}
|
||||
|
||||
@@ -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,7 +67,6 @@ 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;
|
||||
|
||||
@@ -78,7 +75,6 @@ private:
|
||||
std::string GetMySQLVersion();
|
||||
std::string GetBaseMySQLDumpCommand();
|
||||
std::string GetPlayerTablesList();
|
||||
std::string GetBotTablesList();
|
||||
std::string GetSystemTablesList();
|
||||
std::string GetStateTablesList();
|
||||
std::string GetContentTablesList();
|
||||
|
||||
+102
-105
@@ -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>
|
||||
@@ -49,7 +48,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
namespace Convert {
|
||||
struct BindStruct {
|
||||
/*000*/ uint32 zone_id;
|
||||
/*000*/ uint32 zoneId;
|
||||
/*004*/ float x;
|
||||
/*008*/ float y;
|
||||
/*012*/ float z;
|
||||
@@ -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,
|
||||
@@ -1323,18 +1320,18 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
|
||||
/* Run Bind Home Convert */
|
||||
if (pp->binds[4].zone_id < 999 && !_ISNAN_(pp->binds[4].x) && !_ISNAN_(pp->binds[4].y) && !_ISNAN_(pp->binds[4].z) && !_ISNAN_(pp->binds[4].heading)) {
|
||||
if (pp->binds[4].zoneId < 999 && !_ISNAN_(pp->binds[4].x) && !_ISNAN_(pp->binds[4].y) && !_ISNAN_(pp->binds[4].z) && !_ISNAN_(pp->binds[4].heading)) {
|
||||
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, 1)",
|
||||
character_id, pp->binds[4].zone_id, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading);
|
||||
character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading);
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
}
|
||||
|
||||
/* Run Bind Convert */
|
||||
if (pp->binds[0].zone_id < 999 && !_ISNAN_(pp->binds[0].x) && !_ISNAN_(pp->binds[0].y) && !_ISNAN_(pp->binds[0].z) && !_ISNAN_(pp->binds[0].heading)) {
|
||||
if (pp->binds[0].zoneId < 999 && !_ISNAN_(pp->binds[0].x) && !_ISNAN_(pp->binds[0].y) && !_ISNAN_(pp->binds[0].z) && !_ISNAN_(pp->binds[0].heading)) {
|
||||
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, 0)",
|
||||
character_id, pp->binds[0].zone_id, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading);
|
||||
character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading);
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
}
|
||||
/* Run Language Convert */
|
||||
@@ -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]);
|
||||
|
||||
@@ -18,10 +18,8 @@ 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/dynamic_zone_members_repository.h"
|
||||
#include "../common/repositories/dynamic_zones_repository.h"
|
||||
|
||||
#include "database.h"
|
||||
|
||||
@@ -485,7 +483,7 @@ void Database::BuryCorpsesInInstance(uint16 instance_id) {
|
||||
void Database::DeleteInstance(uint16 instance_id)
|
||||
{
|
||||
std::string query;
|
||||
|
||||
|
||||
query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id);
|
||||
QueryDatabase(query);
|
||||
|
||||
@@ -495,8 +493,8 @@ void Database::DeleteInstance(uint16 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));
|
||||
query = fmt::format("DELETE FROM dynamic_zones WHERE instance_id={}", instance_id);
|
||||
QueryDatabase(query);
|
||||
|
||||
BuryCorpsesInInstance(instance_id);
|
||||
}
|
||||
@@ -509,7 +507,7 @@ void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 char
|
||||
|
||||
char ln[128];
|
||||
memset(ln, 0, 128);
|
||||
GetGroupLeadershipInfo(gid, ln);
|
||||
strcpy(ln, GetGroupLeadershipInfo(gid, ln));
|
||||
uint32 l_charid = GetCharacterID((const char*)ln);
|
||||
uint16 l_id = GetInstanceID(zone, l_charid, version);
|
||||
|
||||
@@ -580,15 +578,14 @@ void Database::PurgeExpiredInstances()
|
||||
instance_ids.emplace_back(row[0]);
|
||||
}
|
||||
|
||||
std::string imploded_instance_ids = Strings::Implode(",", instance_ids);
|
||||
std::string imploded_instance_ids = implode(",", 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));
|
||||
QueryDatabase(fmt::format("DELETE FROM dynamic_zones WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
}
|
||||
|
||||
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||
|
||||
@@ -51,9 +51,7 @@ namespace DatabaseSchema {
|
||||
{"character_disciplines", "id"},
|
||||
{"character_enabledtasks", "charid"},
|
||||
{"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 +60,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 +79,7 @@ namespace DatabaseSchema {
|
||||
{"player_titlesets", "char_id"},
|
||||
{"quest_globals", "charid"},
|
||||
{"timers", "char_id"},
|
||||
{"titles", "char_id"},
|
||||
{"trader", "char_id"},
|
||||
{"zone_flags", "charID"}
|
||||
};
|
||||
@@ -119,9 +116,7 @@ namespace DatabaseSchema {
|
||||
"character_disciplines",
|
||||
"character_enabledtasks",
|
||||
"character_expedition_lockouts",
|
||||
"character_exp_modifiers",
|
||||
"character_inspect_messages",
|
||||
"character_instance_safereturns",
|
||||
"character_item_recast",
|
||||
"character_languages",
|
||||
"character_leadership_abilities",
|
||||
@@ -130,11 +125,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 +152,7 @@ namespace DatabaseSchema {
|
||||
"spell_buckets",
|
||||
"spell_globals",
|
||||
"timers",
|
||||
"titles",
|
||||
"trader",
|
||||
"trader_audit",
|
||||
"zone_flags"
|
||||
@@ -189,14 +183,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 +215,9 @@ namespace DatabaseSchema {
|
||||
"npc_types_tint",
|
||||
"object",
|
||||
"pets",
|
||||
"pets_beastlord_data",
|
||||
"pets_equipmentset",
|
||||
"pets_equipmentset_entries",
|
||||
"proximities",
|
||||
"skill_caps",
|
||||
"spawn2",
|
||||
"spawn_conditions",
|
||||
@@ -270,7 +263,6 @@ namespace DatabaseSchema {
|
||||
"perl_event_export_settings",
|
||||
"profanity_list",
|
||||
"rule_sets",
|
||||
"titles",
|
||||
"rule_values",
|
||||
"variables",
|
||||
};
|
||||
@@ -315,21 +307,17 @@ 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",
|
||||
"expedition_lockouts",
|
||||
"expedition_members",
|
||||
"expeditions",
|
||||
"gm_ips",
|
||||
"group_id",
|
||||
"group_leaders",
|
||||
"hackers",
|
||||
"instance_list",
|
||||
"ip_exemptions",
|
||||
"instance_list",
|
||||
"item_tick",
|
||||
"lfguild",
|
||||
"merchantlist_temp",
|
||||
@@ -340,11 +328,7 @@ namespace DatabaseSchema {
|
||||
"reports",
|
||||
"respawn_times",
|
||||
"saylink",
|
||||
"server_scheduled_events",
|
||||
"shared_task_activity_state",
|
||||
"shared_task_dynamic_zones",
|
||||
"shared_task_members",
|
||||
"shared_tasks",
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -377,40 +361,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_spells_entries",
|
||||
"bot_stances",
|
||||
"bot_timers",
|
||||
"vw_bot_character_mobs",
|
||||
"vw_bot_groups"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //EQEMU_DATABASE_SCHEMA_H
|
||||
|
||||
+6
-6
@@ -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",
|
||||
@@ -223,10 +223,10 @@ bool DBcore::Open(
|
||||
)
|
||||
{
|
||||
LockMutex lock(&MDatabase);
|
||||
safe_delete_array(pHost);
|
||||
safe_delete_array(pUser);
|
||||
safe_delete_array(pPassword);
|
||||
safe_delete_array(pDatabase);
|
||||
safe_delete(pHost);
|
||||
safe_delete(pUser);
|
||||
safe_delete(pPassword);
|
||||
safe_delete(pDatabase);
|
||||
pHost = strcpy(new char[strlen(iHost) + 1], iHost);
|
||||
pUser = strcpy(new char[strlen(iUser) + 1], iUser);
|
||||
pPassword = strcpy(new char[strlen(iPassword) + 1], iPassword);
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,649 +0,0 @@
|
||||
#include "dynamic_zone_base.h"
|
||||
#include "database.h"
|
||||
#include "eqemu_logsys.h"
|
||||
#include "repositories/instance_list_repository.h"
|
||||
#include "repositories/instance_list_player_repository.h"
|
||||
#include "rulesys.h"
|
||||
#include "servertalk.h"
|
||||
#include "util/uuid.h"
|
||||
|
||||
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
|
||||
{
|
||||
LoadRepositoryResult(std::move(entry));
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::Create()
|
||||
{
|
||||
if (GetInstanceID() == 0)
|
||||
{
|
||||
CreateInstance();
|
||||
}
|
||||
|
||||
m_uuid = EQ::Util::UUID::Generate().ToString();
|
||||
m_id = SaveToDatabase();
|
||||
|
||||
return m_id;
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::CreateInstance()
|
||||
{
|
||||
if (m_instance_id)
|
||||
{
|
||||
LogDynamicZones("CreateInstance failed, instance id [{}] already created", m_instance_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!m_zone_id)
|
||||
{
|
||||
LogDynamicZones("CreateInstance failed, invalid zone id [{}]", m_zone_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t unused_instance_id = 0;
|
||||
if (!GetDatabase().GetUnusedInstanceID(unused_instance_id)) // todo: doesn't this race with insert?
|
||||
{
|
||||
LogDynamicZones("Failed to find unused instance id");
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_start_time = std::chrono::system_clock::now();
|
||||
m_expire_time = m_start_time + m_duration;
|
||||
|
||||
auto insert_instance = InstanceListRepository::NewEntity();
|
||||
insert_instance.id = unused_instance_id;
|
||||
insert_instance.zone = m_zone_id;
|
||||
insert_instance.version = m_zone_version;
|
||||
insert_instance.start_time = static_cast<int>(std::chrono::system_clock::to_time_t(m_start_time));
|
||||
insert_instance.duration = static_cast<int>(m_duration.count());
|
||||
insert_instance.never_expires = m_never_expires;
|
||||
|
||||
auto instance = InstanceListRepository::InsertOne(GetDatabase(), insert_instance);
|
||||
if (instance.id == 0)
|
||||
{
|
||||
LogDynamicZones("Failed to create instance [{}] for zone [{}]", unused_instance_id, m_zone_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_instance_id = instance.id;
|
||||
|
||||
return m_instance_id;
|
||||
}
|
||||
|
||||
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;
|
||||
m_compass.z = dz_entry.compass_z;
|
||||
m_safereturn.zone_id = dz_entry.safe_return_zone_id;
|
||||
m_safereturn.x = dz_entry.safe_return_x;
|
||||
m_safereturn.y = dz_entry.safe_return_y;
|
||||
m_safereturn.z = dz_entry.safe_return_z;
|
||||
m_safereturn.heading = dz_entry.safe_return_heading;
|
||||
m_zonein.x = dz_entry.zone_in_x;
|
||||
m_zonein.y = dz_entry.zone_in_y;
|
||||
m_zonein.z = dz_entry.zone_in_z;
|
||||
m_zonein.heading = dz_entry.zone_in_heading;
|
||||
m_has_zonein = (dz_entry.has_zone_in != 0);
|
||||
// instance_list portion
|
||||
m_zone_id = dz_entry.zone;
|
||||
m_zone_version = dz_entry.version;
|
||||
m_start_time = std::chrono::system_clock::from_time_t(dz_entry.start_time);
|
||||
m_duration = std::chrono::seconds(dz_entry.duration);
|
||||
m_never_expires = (dz_entry.never_expires != 0);
|
||||
m_expire_time = m_start_time + m_duration;
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::SaveToDatabase()
|
||||
{
|
||||
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
|
||||
|
||||
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;
|
||||
insert_dz.compass_z = m_compass.z;
|
||||
insert_dz.safe_return_zone_id = m_safereturn.zone_id;
|
||||
insert_dz.safe_return_x = m_safereturn.x;
|
||||
insert_dz.safe_return_y = m_safereturn.y;
|
||||
insert_dz.safe_return_z = m_safereturn.z;
|
||||
insert_dz.safe_return_heading = m_safereturn.heading;
|
||||
insert_dz.zone_in_x = m_zonein.x;
|
||||
insert_dz.zone_in_y = m_zonein.y;
|
||||
insert_dz.zone_in_z = m_zonein.z;
|
||||
insert_dz.zone_in_heading = m_zonein.heading;
|
||||
insert_dz.has_zone_in = m_has_zonein;
|
||||
|
||||
auto inserted_dz = DynamicZonesRepository::InsertOne(GetDatabase(), insert_dz);
|
||||
return inserted_dz.id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::AddMember(const DynamicZoneMember& add_member)
|
||||
{
|
||||
if (HasMember(add_member.id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id);
|
||||
|
||||
m_members = members;
|
||||
|
||||
// the lower level instance_list_players needs to be kept updated as well
|
||||
std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members;
|
||||
std::vector<InstanceListPlayerRepository::InstanceListPlayer> insert_players;
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
|
||||
member_entry.dynamic_zone_id = m_id;
|
||||
member_entry.character_id = member.id;
|
||||
insert_members.emplace_back(member_entry);
|
||||
|
||||
InstanceListPlayerRepository::InstanceListPlayer player_entry;
|
||||
player_entry.id = static_cast<int>(m_instance_id);
|
||||
player_entry.charid = static_cast<int>(member.id);
|
||||
insert_players.emplace_back(player_entry);
|
||||
}
|
||||
|
||||
DynamicZoneMembersRepository::InsertOrUpdateMany(GetDatabase(), insert_members);
|
||||
InstanceListPlayerRepository::InsertOrUpdateMany(GetDatabase(), insert_players);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetCompass(const DynamicZoneLocation& location, bool update_db)
|
||||
{
|
||||
ProcessCompassChange(location);
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] compass zone: [{}] xyz: ([{}], [{}], [{}])",
|
||||
m_id, m_compass.zone_id, m_compass.x, m_compass.y, m_compass.z);
|
||||
|
||||
DynamicZonesRepository::UpdateCompass(GetDatabase(),
|
||||
m_id, m_compass.zone_id, m_compass.x, m_compass.y, m_compass.z);
|
||||
|
||||
SendServerPacket(CreateServerDzLocationPacket(ServerOP_DzSetCompass, location).get());
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetCompass(uint32_t zone_id, float x, float y, float z, bool update_db)
|
||||
{
|
||||
SetCompass({ zone_id, x, y, z, 0.0f }, update_db);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetSafeReturn(const DynamicZoneLocation& location, bool update_db)
|
||||
{
|
||||
m_safereturn = location;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] safereturn zone: [{}] xyzh: ([{}], [{}], [{}], [{}])",
|
||||
m_id, m_safereturn.zone_id, m_safereturn.x, m_safereturn.y, m_safereturn.z, m_safereturn.heading);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db)
|
||||
{
|
||||
SetSafeReturn({ zone_id, x, y, z, heading }, update_db);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetZoneInLocation(const DynamicZoneLocation& location, bool update_db)
|
||||
{
|
||||
m_zonein = location;
|
||||
m_has_zonein = true;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] zonein zone: [{}] xyzh: ([{}], [{}], [{}], [{}])",
|
||||
m_id, m_zone_id, m_zonein.x, m_zonein.y, m_zonein.z, m_zonein.heading);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetZoneInLocation(float x, float y, float z, float heading, bool update_db)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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));
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberSwapPacket(
|
||||
const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member)
|
||||
{
|
||||
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();
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzLocationPacket(
|
||||
uint16_t server_opcode, const DynamicZoneLocation& location)
|
||||
{
|
||||
constexpr uint32_t pack_size = sizeof(ServerDzLocation_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(server_opcode, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzLocation_Struct*>(pack->pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->zone_id = location.zone_id;
|
||||
buf->x = location.x;
|
||||
buf->y = location.y;
|
||||
buf->z = location.z;
|
||||
buf->heading = location.heading;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasDatabaseMember(uint32_t character_id)
|
||||
{
|
||||
if (character_id == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto entries = DynamicZoneMembersRepository::GetWhere(GetDatabase(), fmt::format(
|
||||
"dynamic_zone_id = {} AND character_id = {}",
|
||||
m_id, character_id
|
||||
));
|
||||
|
||||
return entries.size() != 0;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddInternalMember(const DynamicZoneMember& member)
|
||||
{
|
||||
if (!HasMember(member.id))
|
||||
{
|
||||
m_members.emplace_back(member);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::RemoveInternalMember(uint32_t character_id)
|
||||
{
|
||||
m_members.erase(std::remove_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; }
|
||||
), m_members.end());
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(uint32_t character_id)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(const std::string& character_name)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) {
|
||||
return strcasecmp(member.name.c_str(), character_name.c_str()) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
DynamicZoneMember DynamicZoneBase::GetMemberData(uint32_t character_id)
|
||||
{
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||
|
||||
DynamicZoneMember member_data;
|
||||
if (it != m_members.end())
|
||||
{
|
||||
member_data = *it;
|
||||
}
|
||||
return member_data;
|
||||
}
|
||||
|
||||
DynamicZoneMember DynamicZoneBase::GetMemberData(const std::string& character_name)
|
||||
{
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) {
|
||||
return strcasecmp(member.name.c_str(), character_name.c_str()) == 0;
|
||||
});
|
||||
|
||||
DynamicZoneMember member_data;
|
||||
if (it != m_members.end())
|
||||
{
|
||||
member_data = *it;
|
||||
}
|
||||
return member_data;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status)
|
||||
{
|
||||
if (status == DynamicZoneMemberStatus::InDynamicZone && !RuleB(DynamicZone, EnableInDynamicZoneStatus))
|
||||
{
|
||||
status = DynamicZoneMemberStatus::Online;
|
||||
}
|
||||
|
||||
if (character_id == m_leader.id)
|
||||
{
|
||||
m_leader.status = status;
|
||||
}
|
||||
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||
|
||||
if (it != m_members.end() && it->status != status)
|
||||
{
|
||||
it->status = status;
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
case DynamicZoneType::Expedition:
|
||||
return "Expedition";
|
||||
case DynamicZoneType::Tutorial:
|
||||
return "Tutorial";
|
||||
case DynamicZoneType::Task:
|
||||
return "Task";
|
||||
case DynamicZoneType::Mission:
|
||||
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;
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
#ifndef COMMON_DYNAMIC_ZONE_BASE_H
|
||||
#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>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Database;
|
||||
class ServerPacket;
|
||||
|
||||
struct DynamicZoneMember
|
||||
{
|
||||
uint32_t id = 0;
|
||||
std::string name;
|
||||
DynamicZoneMemberStatus status = DynamicZoneMemberStatus::Unknown;
|
||||
|
||||
DynamicZoneMember() = default;
|
||||
DynamicZoneMember(uint32_t id, std::string name_)
|
||||
: id(id), name{std::move(name_)} {}
|
||||
DynamicZoneMember(uint32_t id, std::string name_, DynamicZoneMemberStatus status_)
|
||||
: id(id), name{std::move(name_)}, status(status_) {}
|
||||
|
||||
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
|
||||
{
|
||||
uint32_t zone_id = 0;
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
float heading = 0.0f;
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
virtual ~DynamicZoneBase() = default;
|
||||
DynamicZoneBase(const DynamicZoneBase&) = default;
|
||||
DynamicZoneBase(DynamicZoneBase&&) = default;
|
||||
DynamicZoneBase& operator=(const DynamicZoneBase&) = default;
|
||||
DynamicZoneBase& operator=(DynamicZoneBase&&) = default;
|
||||
DynamicZoneBase() = default;
|
||||
DynamicZoneBase(uint32_t dz_id) : m_id(dz_id) {}
|
||||
DynamicZoneBase(DynamicZoneType type) : m_type(type) {}
|
||||
DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry);
|
||||
|
||||
static std::string GetDynamicZoneTypeName(DynamicZoneType dz_type);
|
||||
|
||||
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; }
|
||||
uint32_t GetSecondsRemaining() const;
|
||||
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; }
|
||||
const DynamicZoneLocation& GetSafeReturnLocation() const { return m_safereturn; }
|
||||
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 AddMemberFromRepositoryResult(DynamicZoneMembersRepository::MemberWithName&& entry);
|
||||
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);
|
||||
bool HasMembers() const { return !m_members.empty(); }
|
||||
bool HasZoneInLocation() const { return m_has_zonein; }
|
||||
bool IsExpired() const { return m_expire_time < std::chrono::system_clock::now(); }
|
||||
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 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);
|
||||
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;
|
||||
|
||||
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> 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;
|
||||
uint32_t m_instance_id = 0;
|
||||
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;
|
||||
DynamicZoneLocation m_safereturn;
|
||||
DynamicZoneLocation m_zonein;
|
||||
std::chrono::seconds m_duration;
|
||||
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
@@ -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
-260
@@ -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,85 +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 MerchantBucketComparison : uint8 {
|
||||
BucketEqualTo = 0,
|
||||
BucketNotEqualTo,
|
||||
BucketGreaterThanOrEqualTo,
|
||||
BucketLesserThanOrEqualTo,
|
||||
BucketGreaterThan,
|
||||
BucketLesserThan,
|
||||
BucketIsAny,
|
||||
BucketIsNotAny,
|
||||
BucketIsBetween,
|
||||
BucketIsNotBetween
|
||||
};
|
||||
|
||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||
|
||||
/* hack list to prevent circular references
|
||||
|
||||
eq_limits.h:EQ::inventory::LookupEntry::InventoryTypeSize[n];
|
||||
|
||||
*/
|
||||
|
||||
+4
-24
@@ -1,8 +1,6 @@
|
||||
// system use
|
||||
N(OP_ExploreUnknown),
|
||||
// start (please add new opcodes in descending order and re-order any name changes where applicable)
|
||||
N(OP_0x0193),
|
||||
N(OP_0x0347),
|
||||
N(OP_AAAction),
|
||||
N(OP_AAExpUpdate),
|
||||
N(OP_AcceptNewTask),
|
||||
@@ -71,7 +69,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 +127,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 +301,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 +353,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 +454,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 +462,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 +497,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 +543,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 +565,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
|
||||
|
||||
+1
-553
@@ -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,492 +197,6 @@ 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
|
||||
@@ -718,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,
|
||||
@@ -925,10 +438,6 @@ 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;
|
||||
|
||||
enum ChatChannelNames : uint16
|
||||
{
|
||||
ChatChannel_Guild = 0,
|
||||
@@ -955,65 +464,4 @@ namespace ZoneBlockedSpellTypes {
|
||||
const uint8 Region = 2;
|
||||
};
|
||||
|
||||
enum class DynamicZoneType
|
||||
{
|
||||
None = 0,
|
||||
Expedition,
|
||||
Tutorial,
|
||||
Task,
|
||||
Mission, // Shared Task
|
||||
Quest
|
||||
};
|
||||
|
||||
enum class DynamicZoneMemberStatus : uint8_t
|
||||
{
|
||||
Unknown = 0,
|
||||
Online,
|
||||
Offline,
|
||||
InDynamicZone,
|
||||
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
|
||||
};
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
+18
-18
@@ -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 |
|
||||
@@ -794,7 +794,7 @@ void EQ::inventory::InitializeDynamicLookups() {
|
||||
continue;
|
||||
|
||||
// direct manipulation of lookup indices is safe so long as (int)ClientVersion::<mob> == (int)MobVersion::<mob>
|
||||
inventory_dynamic_nongm_lookup_entries[iter] = std::make_unique<LookupEntry>(inventory_static_lookup_entries[iter]);
|
||||
inventory_dynamic_nongm_lookup_entries[iter] = std::unique_ptr<LookupEntry>(new LookupEntry(inventory_static_lookup_entries[iter]));
|
||||
|
||||
// clamp affected fields to the lowest standard
|
||||
inventory_dynamic_nongm_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE; // bank size
|
||||
@@ -864,7 +864,7 @@ void EQ::inventory::InitializeDynamicLookups() {
|
||||
}
|
||||
|
||||
// direct manipulation of lookup indices is safe so long as (int)ClientVersion::<client> == (int)MobVersion::<client>
|
||||
inventory_dynamic_gm_lookup_entries[iter] = std::make_unique<LookupEntry>(inventory_static_lookup_entries[iter]);
|
||||
inventory_dynamic_gm_lookup_entries[iter] = std::unique_ptr<LookupEntry>(new LookupEntry(inventory_static_lookup_entries[iter]));
|
||||
|
||||
inventory_dynamic_gm_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later
|
||||
inventory_dynamic_gm_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later
|
||||
@@ -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)];
|
||||
}
|
||||
|
||||
|
||||
+73
-162
@@ -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
|
||||
@@ -832,7 +829,7 @@ struct LeadershipAA_Struct {
|
||||
* Size: 20 Octets
|
||||
*/
|
||||
struct BindStruct {
|
||||
/*000*/ uint32 zone_id;
|
||||
/*000*/ uint32 zoneId;
|
||||
/*004*/ float x;
|
||||
/*008*/ float y;
|
||||
/*012*/ float z;
|
||||
@@ -1775,7 +1772,7 @@ struct GMZoneRequest_Struct {
|
||||
/*0068*/ float x;
|
||||
/*0072*/ float y;
|
||||
/*0076*/ float z;
|
||||
/*0080*/ float heading;
|
||||
/*0080*/ char unknown0080[4];
|
||||
/*0084*/ uint32 success; // 0 if command failed, 1 if succeeded?
|
||||
/*0088*/
|
||||
// /*072*/ int8 success; // =0 client->server, =1 server->client, -X=specific error
|
||||
@@ -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;
|
||||
@@ -3261,7 +3247,7 @@ struct TraderClick_Struct{
|
||||
};
|
||||
|
||||
struct FormattedMessage_Struct{
|
||||
uint32 unknown0; // 1 means from world server
|
||||
uint32 unknown0;
|
||||
uint32 string_id;
|
||||
uint32 type;
|
||||
char message[0];
|
||||
@@ -3269,7 +3255,7 @@ struct FormattedMessage_Struct{
|
||||
struct SimpleMessage_Struct{
|
||||
uint32 string_id;
|
||||
uint32 color;
|
||||
uint32 unknown8; // 1 means from world server
|
||||
uint32 unknown8;
|
||||
};
|
||||
|
||||
struct GuildMemberUpdate_Struct {
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -4927,31 +4861,30 @@ struct ExpeditionInviteResponse_Struct
|
||||
/*079*/ uint8 unknown079; // padding garbage?
|
||||
};
|
||||
|
||||
struct DynamicZoneInfo_Struct
|
||||
struct ExpeditionInfo_Struct
|
||||
{
|
||||
/*000*/ uint32 client_id;
|
||||
/*004*/ uint32 unknown004; // added after titanium
|
||||
/*008*/ uint32 assigned; // padded bool, 0: clear info, 1: fill window info
|
||||
/*008*/ uint32 assigned; // padded bool, 0: not in expedition (clear data), 1: in expedition
|
||||
/*012*/ uint32 max_players;
|
||||
/*016*/ char dz_name[128];
|
||||
/*016*/ char expedition_name[128];
|
||||
/*144*/ char leader_name[64];
|
||||
//*208*/ uint32 dz_type; // only in newer clients, if not 1 (expedition type) window does not auto show when dz info assigned
|
||||
};
|
||||
|
||||
struct DynamicZoneMemberEntry_Struct
|
||||
struct ExpeditionMemberEntry_Struct
|
||||
{
|
||||
/*000*/ char name[64]; // variable length, null terminated, max 0x40 (64)
|
||||
/*064*/ uint8 online_status; // 0: unknown, 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||
/*000*/ char name[64]; // variable length, null terminated, max 0x40 (64)
|
||||
/*064*/ uint8 expedition_status; // 0: unknown, 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||
};
|
||||
|
||||
struct DynamicZoneMemberList_Struct
|
||||
struct ExpeditionMemberList_Struct
|
||||
{
|
||||
/*000*/ uint32 client_id;
|
||||
/*004*/ uint32 member_count;
|
||||
/*008*/ DynamicZoneMemberEntry_Struct members[0]; // variable length
|
||||
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||
};
|
||||
|
||||
struct DynamicZoneMemberListName_Struct
|
||||
struct ExpeditionMemberListName_Struct
|
||||
{
|
||||
/*000*/ uint32 client_id;
|
||||
/*004*/ uint32 unknown004;
|
||||
@@ -4974,7 +4907,7 @@ struct ExpeditionLockoutTimers_Struct
|
||||
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||
};
|
||||
|
||||
struct DynamicZoneLeaderName_Struct
|
||||
struct ExpeditionSetLeaderName_Struct
|
||||
{
|
||||
/*000*/ uint32 client_id;
|
||||
/*004*/ uint32 unknown004;
|
||||
@@ -5006,7 +4939,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;
|
||||
@@ -5596,28 +5529,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()
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
-23
@@ -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,25 +62,17 @@ 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; }
|
||||
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
||||
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
|
||||
WorldUDPPort = atoi(_root["server"]["world"]["udp"].get("port", "9000").asString().c_str());
|
||||
|
||||
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
||||
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
|
||||
@@ -101,10 +87,6 @@ void EQEmuConfig::parse_config()
|
||||
WorldHTTPEnabled = true;
|
||||
}
|
||||
|
||||
if (_root["server"].get("disable_config_checks", "false").asString() == "true") {
|
||||
DisableConfigChecks = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* UCS
|
||||
*/
|
||||
@@ -218,9 +200,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
||||
if (var_name == "WorldTCPPort") {
|
||||
return (itoa(WorldTCPPort));
|
||||
}
|
||||
if (var_name == "WorldUDPPort") {
|
||||
return (itoa(WorldUDPPort));
|
||||
}
|
||||
if (var_name == "WorldIP") {
|
||||
return (WorldIP);
|
||||
}
|
||||
@@ -352,7 +331,6 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "LoginLegacy = " << LoginLegacy << std::endl;
|
||||
std::cout << "Locked = " << Locked << std::endl;
|
||||
std::cout << "WorldTCPPort = " << WorldTCPPort << std::endl;
|
||||
std::cout << "WorldUDPPort = " << WorldUDPPort << std::endl;
|
||||
std::cout << "WorldIP = " << WorldIP << std::endl;
|
||||
std::cout << "TelnetTCPPort = " << TelnetTCPPort << std::endl;
|
||||
std::cout << "TelnetIP = " << TelnetIP << std::endl;
|
||||
|
||||
+7
-19
@@ -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;
|
||||
@@ -51,7 +49,6 @@ class EQEmuConfig
|
||||
LinkedList<LoginConfig*> loginlist;
|
||||
bool Locked;
|
||||
uint16 WorldTCPPort;
|
||||
uint16 WorldUDPPort;
|
||||
std::string WorldIP;
|
||||
uint16 TelnetTCPPort;
|
||||
std::string TelnetIP;
|
||||
@@ -61,7 +58,6 @@ class EQEmuConfig
|
||||
uint16 WorldHTTPPort;
|
||||
std::string WorldHTTPMimeFile;
|
||||
std::string SharedKey;
|
||||
bool DisableConfigChecks;
|
||||
|
||||
// From <chatserver/>
|
||||
std::string ChatHost;
|
||||
@@ -134,7 +130,7 @@ class EQEmuConfig
|
||||
void parse_config();
|
||||
|
||||
EQEmuConfig()
|
||||
{
|
||||
{
|
||||
|
||||
}
|
||||
virtual ~EQEmuConfig() {}
|
||||
@@ -155,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;
|
||||
}
|
||||
|
||||
|
||||
+137
-294
@@ -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,46 +96,37 @@ 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::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);
|
||||
|
||||
/**
|
||||
* RFC 5424
|
||||
@@ -159,8 +146,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;
|
||||
}
|
||||
@@ -169,29 +155,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,12 +196,58 @@ 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;
|
||||
|
||||
if (IsRfc5424LogCategory(log_category)) {
|
||||
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
|
||||
)
|
||||
@@ -228,16 +258,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;
|
||||
}
|
||||
}
|
||||
@@ -333,7 +364,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;
|
||||
@@ -351,7 +382,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,52 +439,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,7 +492,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -505,45 +531,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
|
||||
);
|
||||
}
|
||||
@@ -570,194 +604,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;
|
||||
}
|
||||
|
||||
|
||||
+95
-115
@@ -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,
|
||||
@@ -121,33 +120,20 @@ namespace Logs {
|
||||
Loot,
|
||||
Expeditions,
|
||||
DynamicZones,
|
||||
Scheduler,
|
||||
Cheat,
|
||||
ClientList,
|
||||
DiaWind,
|
||||
HTTP,
|
||||
Saylink,
|
||||
ChecksumVerification,
|
||||
CombatRecord,
|
||||
Hate,
|
||||
Discord,
|
||||
Faction,
|
||||
PacketServerClient,
|
||||
PacketClientServer,
|
||||
PacketServerToServer,
|
||||
Group,
|
||||
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",
|
||||
@@ -181,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",
|
||||
@@ -214,29 +200,12 @@ namespace Logs {
|
||||
"Loot",
|
||||
"Expeditions",
|
||||
"DynamicZones",
|
||||
"Scheduler",
|
||||
"Cheat",
|
||||
"ClientList",
|
||||
"DialogueWindow",
|
||||
"HTTP",
|
||||
"Saylink",
|
||||
"ChecksumVerification",
|
||||
"CombatRecord",
|
||||
"Hate",
|
||||
"Discord",
|
||||
"Faction",
|
||||
"Packet-S->C",
|
||||
"Packet-C->S",
|
||||
"Packet-S->S"
|
||||
"Group",
|
||||
};
|
||||
}
|
||||
|
||||
#include "eqemu_logsys_log_aliases.h"
|
||||
|
||||
class Database;
|
||||
|
||||
constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300;
|
||||
|
||||
class EQEmuLogSys {
|
||||
public:
|
||||
EQEmuLogSys();
|
||||
@@ -247,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
|
||||
@@ -278,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
|
||||
@@ -299,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;
|
||||
|
||||
+175
-453
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -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;
|
||||
|
||||
@@ -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)...)
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace EQ {
|
||||
void Stop() {
|
||||
if (m_timer) {
|
||||
uv_close((uv_handle_t*)m_timer, [](uv_handle_t* handle) {
|
||||
delete (uv_timer_t *)handle;
|
||||
delete handle;
|
||||
});
|
||||
m_timer = nullptr;
|
||||
}
|
||||
|
||||
+22
-22
@@ -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;
|
||||
}
|
||||
|
||||
+10
-27
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
};
|
||||
@@ -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,6 +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;
|
||||
}
|
||||
|
||||
@@ -132,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);
|
||||
@@ -140,18 +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);
|
||||
|
||||
// Check whether there is space for the specified number of the specified item.
|
||||
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
|
||||
|
||||
@@ -202,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 int GetItemStatValue(uint32 item_id, const char* identifier);
|
||||
protected:
|
||||
///////////////////////////////
|
||||
// Protected Methods
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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();
|
||||
|
||||
+10
-10
@@ -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;
|
||||
|
||||
+19
-58
@@ -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
|
||||
@@ -381,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;
|
||||
}
|
||||
|
||||
@@ -476,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; }
|
||||
@@ -526,7 +526,7 @@ EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugty
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return GetAugment(i);
|
||||
return this->GetAugment(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,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);
|
||||
@@ -642,7 +642,7 @@ void EQ::ItemInstance::PutAugment(uint8 slot, const ItemInstance& augment)
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return;
|
||||
|
||||
|
||||
PutItem(slot, augment);
|
||||
}
|
||||
|
||||
@@ -655,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
|
||||
@@ -663,7 +663,7 @@ void EQ::ItemInstance::DeleteAugment(uint8 index)
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return;
|
||||
|
||||
|
||||
DeleteItem(index);
|
||||
}
|
||||
|
||||
@@ -672,7 +672,7 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return nullptr;
|
||||
|
||||
|
||||
return PopItem(index);
|
||||
}
|
||||
|
||||
@@ -680,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;
|
||||
@@ -689,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
|
||||
{
|
||||
@@ -873,7 +834,7 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1097,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;
|
||||
@@ -1162,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;
|
||||
@@ -1178,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;
|
||||
@@ -1236,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)
|
||||
@@ -1253,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)
|
||||
|
||||
@@ -132,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);
|
||||
|
||||
+5
-14
@@ -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
@@ -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);
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace EQ {
|
||||
|
||||
struct MemoryMappedFile::Implementation {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#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)
|
||||
{
|
||||
m_server = std::make_unique<EQ::Net::TCPServer>();
|
||||
m_server.reset(new EQ::Net::TCPServer());
|
||||
m_server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
ConsoleServerConnection *c = new ConsoleServerConnection(this, connection);
|
||||
m_connections.insert(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleServerConnection>(c)));
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "../eqemu_logsys.h"
|
||||
|
||||
EQ::Net::ServertalkClient::ServertalkClient(const std::string &addr, int port, bool ipv6, const std::string &identifier, const std::string &credentials)
|
||||
: m_timer(std::make_unique<EQ::Timer>(100, true, std::bind(&EQ::Net::ServertalkClient::Connect, this)))
|
||||
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkClient::Connect, this))))
|
||||
{
|
||||
m_port = port;
|
||||
m_ipv6 = ipv6;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,4 +15,4 @@ namespace EQ
|
||||
ServertalkMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "../eqemu_logsys.h"
|
||||
|
||||
EQ::Net::ServertalkLegacyClient::ServertalkLegacyClient(const std::string &addr, int port, bool ipv6)
|
||||
: m_timer(std::make_unique<EQ::Timer>(100, true, std::bind(&EQ::Net::ServertalkLegacyClient::Connect, this)))
|
||||
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkLegacyClient::Connect, this))))
|
||||
{
|
||||
m_port = port;
|
||||
m_ipv6 = ipv6;
|
||||
|
||||
@@ -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_server = std::make_unique<EQ::Net::TCPServer>();
|
||||
m_allow_downgrade = opts.allow_downgrade;
|
||||
m_server.reset(new 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));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,7 +2,7 @@
|
||||
#include "../event/event_loop.h"
|
||||
|
||||
void on_close_handle(uv_handle_t* handle) {
|
||||
delete (uv_tcp_t *)handle;
|
||||
delete handle;
|
||||
}
|
||||
|
||||
EQ::Net::TCPConnection::TCPConnection(uv_tcp_t *socket)
|
||||
@@ -115,7 +115,7 @@ void EQ::Net::TCPConnection::Disconnect()
|
||||
connection->m_on_disconnect_cb(connection);
|
||||
}
|
||||
|
||||
delete (uv_tcp_t *)handle;
|
||||
delete handle;
|
||||
});
|
||||
m_socket = nullptr;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "../event/event_loop.h"
|
||||
|
||||
void on_close_tcp_server_handle(uv_handle_t* handle) {
|
||||
delete (uv_tcp_t *)handle;
|
||||
delete handle;
|
||||
}
|
||||
|
||||
EQ::Net::TCPServer::TCPServer()
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
#include "../emu_constants.h"
|
||||
|
||||
struct MethodHandlerEntry
|
||||
{
|
||||
@@ -35,8 +34,8 @@ struct EQ::Net::WebsocketServer::Impl
|
||||
|
||||
EQ::Net::WebsocketServer::WebsocketServer(const std::string &addr, int port)
|
||||
{
|
||||
_impl = std::make_unique<Impl>();
|
||||
_impl->server = std::make_unique<EQ::Net::TCPServer>();
|
||||
_impl.reset(new Impl());
|
||||
_impl->server.reset(new EQ::Net::TCPServer());
|
||||
_impl->server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
auto wsc = _impl->ws_server.get_connection();
|
||||
WebsocketServerConnection *c = new WebsocketServerConnection(this, connection, wsc);
|
||||
@@ -54,7 +53,7 @@ EQ::Net::WebsocketServer::WebsocketServer(const std::string &addr, int port)
|
||||
return websocketpp::lib::error_code();
|
||||
});
|
||||
|
||||
_impl->ping_timer = std::make_unique<EQ::Timer>(5000, true, [this](EQ::Timer *t) {
|
||||
_impl->ping_timer.reset(new EQ::Timer(5000, true, [this](EQ::Timer *t) {
|
||||
auto iter = _impl->connections.begin();
|
||||
|
||||
while (iter != _impl->connections.end()) {
|
||||
@@ -68,7 +67,7 @@ EQ::Net::WebsocketServer::WebsocketServer(const std::string &addr, int port)
|
||||
|
||||
iter++;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
_impl->methods.insert(std::make_pair("login", MethodHandlerEntry(std::bind(&WebsocketServer::Login, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||
_impl->methods.insert(std::make_pair("subscribe", MethodHandlerEntry(std::bind(&WebsocketServer::Subscribe, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||
@@ -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 {
|
||||
|
||||
@@ -20,7 +20,7 @@ EQ::Net::WebsocketServerConnection::WebsocketServerConnection(WebsocketServer *p
|
||||
std::shared_ptr<TCPConnection> connection,
|
||||
std::shared_ptr<websocket_connection> ws_connection)
|
||||
{
|
||||
_impl = std::make_unique<Impl>();
|
||||
_impl.reset(new Impl());
|
||||
_impl->parent = parent;
|
||||
_impl->connection = connection;
|
||||
_impl->id = EQ::Util::UUID::Generate().ToString();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user