Compare commits

..

6 Commits

Author SHA1 Message Date
Xackery cd01ed87df Added missed pet summons 2021-11-23 18:16:22 -08:00
Xackery 8a79994b4e Added more elixir error constants 2021-11-18 09:51:55 -08:00
Xackery 93a661a434 Removed debug line 2021-11-16 17:19:37 -08:00
Xackery 3e8796bb4c Added ElixirSpellCache, #elixircheck 2021-11-16 17:03:42 -08:00
Xackery c23fc4ade7 Added Elixir 2021-11-15 20:55:40 -08:00
Xackery 3b628c1ace Added tweaks to dev containers 2021-11-15 20:54:28 -08:00
1649 changed files with 212380 additions and 255037 deletions
+21
View File
@@ -0,0 +1,21 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.101.1/containers/ubuntu-18.04-git
{
"name": "Ubuntu 18.04 EQEMU",
// Moved from dockerfile to image so it builds faster
"image": "eqemu/devcontainer:0.0.2",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
// Add the IDs of extensions you want installed when the container is created.
"extensions": ["ms-vscode.cpptools", "ms-azuretools.vscode-docker"],
"mounts": ["source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"],
"remoteEnv": {
"HOST_PROJECT_PATH": "${localWorkspaceFolder}"
}
}
+6 -88
View File
@@ -1,98 +1,16 @@
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: Build Linux name: EQEmulator Server Linux CI
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores # Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency: concurrency:
limit: 1 limit: 1
volumes:
- name: cache
host:
path: /var/lib/cache-release
steps: steps:
- name: Build Linux X64 - name: server-build
image: akkadius/eqemu-server:v13 # Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20
environment: image: akkadius/eqemu-server:latest
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
commands: commands:
- ./utils/scripts/build/linux-build.sh - sudo chown eqemu:eqemu /drone/src/ * -R
volumes: - git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
- name: cache
path: /home/eqemu/.ccache/
---
kind: pipeline
type: exec
name: Build Windows
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency:
limit: 1
platform:
os: windows
arch: amd64
steps:
- name: Build Windows X64
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- .\utils\scripts\build\windows-build.ps1
---
kind: pipeline
type: docker
name: Publish Artifacts to Github
steps:
- name: Upload Artifacts
image: akkadius/eqemu-build-releaser:v3
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GH_RELEASE_GITHUB_API_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- ./utils/scripts/build/should-release/should-release
- rclone config create remote ftp env_auth true > /dev/null
- |
rclone copy remote: --include "eqemu-server*.zip" .
- gh-release --assets=eqemu-server-linux-x64.zip,eqemu-server-windows-x64.zip -y
- |
rclone delete remote: --include "eqemu-server*.zip"
trigger:
branch:
- master
event:
- push
depends_on:
- Build Windows
- Build Linux
-17
View File
@@ -54,20 +54,3 @@ bin/
/Win32 /Win32
/x64 /x64
/client_files/**/CMakeFiles/ /client_files/**/CMakeFiles/
.idea
# Clangd Generated Files.
compile_flags.txt
.cache/
# vscode generated settings
.vscode/
# Build pipeline
!utils/scripts/build/
!utils/scripts/build/should-release/should-release
!utils/scripts/build/should-release/should-release.exe
# CMake Files
cmake-build-relwithdebinfo/*
+19
View File
@@ -0,0 +1,19 @@
language: cpp
compiler: gcc
dist: bionic
addons:
apt:
packages:
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
- uuid-dev
- libssl-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
- make -j2
- ./bin/tests
+17
View File
@@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/mysql"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++17",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
+8
View File
@@ -0,0 +1,8 @@
{
"files.associations": {
"chrono": "cpp",
"xutility": "cpp",
"iterator": "cpp",
"*.ipp": "cpp"
}
}
+164
View File
@@ -0,0 +1,164 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "make",
"type": "shell",
"command": "mkdir -p build && cd build && make",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "make clean",
"type": "shell",
"command": "mkdir -p build && cd build && make clean",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "cmake",
"type": "shell",
"command": "mkdir -p build && cd build && rm CMakeCache.txt && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' ..",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher":{
"owner": "cpp",
"fileLocation": "relative",
"pattern":[
{
"regexp": "([\\w+|\\\\]*\\.\\w+)\\((\\d+)\\)\\: (warning|error) (.*)$",
"file": 1,
"location": 2,
"severity": 3,
"message": 4
}
]
}
},
{
"label": "download maps",
"type": "shell",
"command": "mkdir -p build && cd build/bin && wget https://codeload.github.com/Akkadius/EQEmuMaps/zip/master -O maps.zip && unzip -o maps.zip && rm ./maps -rf && mv EQEmuMaps-master maps && rm maps.zip",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "download quests",
"type": "shell",
"command": "mkdir -p build && cd build/bin && cd server && git -C ./quests pull 2> /dev/null || git clone https://github.com/ProjectEQ/projecteqquests.git quests",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "download eqemu_config",
"type": "shell",
"command": "mkdir -p build && cd build/bin && wget --no-check-certificate https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/eqemu_config_docker.json -O eqemu_config.json",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "rebuild database (mariadb must be started)",
"type": "shell",
"command": "mkdir -p build && cd build/bin && docker run -i --rm --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --network=eqemu -it eqemu/server:0.0.3 bash -c './eqemu_server.pl source_peq_db && ./eqemu_server.pl check_db_updates && ./eqemu_server.pl assets && ./eqemu_server.pl lua_modules && ./eqemu_server.pl opcodes && ./eqemu_server.pl linux_login_server_setup'",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "zone 7000",
"type": "shell",
"command": "docker stop zone7000 | true && docker network create eqemu | true && docker run -i --rm --name zone7000 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu -p 7000:7000/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7000:7000",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "zone 7001",
"type": "shell",
"command": "docker stop zone7001 | true && docker network create eqemu | true && docker run -i --rm --name zone7001 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu -p 7001:7001/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7001:7001",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "loginserver",
"type": "shell",
"command": "docker stop loginserver | true && docker network create eqemu | true && docker run -i --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu --name loginserver -p 5999:5999/udp -p 5998:5998/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./loginserver",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "shared_memory, world",
"type": "shell",
"command": "docker stop sharedmemory | true && docker stop world | true && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --network=eqemu --name sharedmemory eqemu/server:0.0.3 ./shared_memory && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name world -p 9000:9000 -p 9000:9000/udp -p 9001:9001 -p 9080:9080 eqemu/server:0.0.3 gdb -ex run ./world",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "queryserv",
"type": "shell",
"command": "docker stop queryserv | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name queryserv eqemu/server:0.0.3 gdb -ex run ./queryserv",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "mariadb",
"type": "shell",
"command": "docker stop mariadb | true && cd bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin/db:/bitnami/mariadb -p 3306:3306 -e MARIADB_DATABASE=peq -e MARIADB_USER=eqemu -e MARIADB_PASSWORD=eqemupass -e ALLOW_EMPTY_PASSWORD=yes --name mariadb --network=eqemu bitnami/mariadb:latest",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "ucs",
"type": "shell",
"command": "docker stop ucs | true && cd bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src -p 7778:7778 --name ucs --network=eqemu eqemu/server:0.0.3 gdb -ex run ./ucs",
"group": {
"kind": "test",
"isDefault": true
}
}
]
}
+2 -2
View File
@@ -40,14 +40,14 @@ Assuming it is starting in c:/projects/eqemu and the x64 dependencies were extra
mkdir build mkdir build
cd build cd build
cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" .. cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DEQEMU_ENABLE_BOTS=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" ..
##### Linux ##### Linux
Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator. Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator.
mkdir build mkdir build
cd build cd build
cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON .. cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON ..
### Building ### Building
-2375
View File
File diff suppressed because it is too large Load Diff
+13 -40
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.7)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
@@ -12,36 +12,16 @@ IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_CXX_STANDARD 20) SET(CMAKE_CXX_STANDARD 14)
SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF) SET(CMAKE_CXX_EXTENSIONS OFF)
OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF)
IF (EQEMU_BUILD_STATIC)
SET(BUILD_SHARED_LIBS OFF)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
MESSAGE(STATUS "Building with static linking")
SET(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
IF (UNIX)
SET(PERL_LIBRARY "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/libperl.so")
SET(PERL_INCLUDE_PATH "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/")
SET(PERL_EXECUTABLE "/opt/eqemu-perl/bin/perl")
ENDIF ()
ENDIF (EQEMU_BUILD_STATIC)
IF(MSVC) IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-DNOMINMAX) ADD_DEFINITIONS(-DNOMINMAX)
ADD_DEFINITIONS(-DCRASH_LOGGING) ADD_DEFINITIONS(-DCRASH_LOGGING)
ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
OPTION(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON)
IF(EQEMU_DISABLE_MSVC_WARNINGS)
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
ENDIF(EQEMU_DISABLE_MSVC_WARNINGS)
ELSE(MSVC) ELSE(MSVC)
ADD_DEFINITIONS(-DHAS_UNION_SEMUN) ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC) ENDIF(MSVC)
@@ -138,16 +118,11 @@ ELSE()
MESSAGE(STATUS "* mbedTLS: MISSING *") MESSAGE(STATUS "* mbedTLS: MISSING *")
ENDIF() ENDIF()
MESSAGE(STATUS "PERL_INCLUDE_PATH: ${PERL_INCLUDE_PATH}")
MESSAGE(STATUS "PERL_LIBRARY: ${PERL_LIBRARY}")
MESSAGE(STATUS "PERL_INCLUDE_DIR: ${PERL_INCLUDE_DIR}")
MESSAGE(STATUS "PERL_INCLUDE_DIRS: ${PERL_INCLUDE_DIRS}")
MESSAGE(STATUS "PERL_LIBRARIES: ${PERL_LIBRARIES}")
MESSAGE(STATUS "PERL_VERSION: ${PERL_VERSION}")
MESSAGE(STATUS "**************************************************") MESSAGE(STATUS "**************************************************")
#options #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_COMMANDS_LOGGING "Enable GM Command logs" ON)
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON) OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON) OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
@@ -201,6 +176,10 @@ IF(EQEMU_COMMANDS_LOGGING)
ADD_DEFINITIONS(-DCOMMANDS_LOGGING) ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
ENDIF(EQEMU_COMMANDS_LOGGING) ENDIF(EQEMU_COMMANDS_LOGGING)
IF(EQEMU_ENABLE_BOTS)
ADD_DEFINITIONS(-DBOTS)
ENDIF(EQEMU_ENABLE_BOTS)
#database #database
IF(MySQL_FOUND AND MariaDB_FOUND) IF(MySQL_FOUND AND MariaDB_FOUND)
SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use: SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use:
@@ -332,10 +311,6 @@ ELSE()
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
ENDIF() ENDIF()
IF (EQEMU_BUILD_STATIC)
SET(ZLIB_LIBRARY_LIBS libz.a)
ENDIF(EQEMU_BUILD_STATIC)
MESSAGE(STATUS "") MESSAGE(STATUS "")
MESSAGE(STATUS "**************************************************") MESSAGE(STATUS "**************************************************")
MESSAGE(STATUS "* Library Usage *") MESSAGE(STATUS "* Library Usage *")
@@ -365,8 +340,10 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
# silence obnoxious deprecation message OPTION(EQEMU_BUILD_LOGGING "Build Logging (To speed up compilation)" ON)
ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS) IF(EQEMU_BUILD_LOGGING)
ADD_DEFINITIONS(-DBUILD_LOGGING)
ENDIF()
IF(TLS_LIBRARY_ENABLED) IF(TLS_LIBRARY_ENABLED)
SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS}) SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS})
@@ -396,14 +373,10 @@ ENDIF()
IF(PERL_LIBRARY_ENABLED) IF(PERL_LIBRARY_ENABLED)
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
IF(EQEMU_BUILD_PERL) 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}") INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
ADD_DEFINITIONS(-DEMBPERL) ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN) ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
ADD_DEFINITIONS(-DPERLBIND_NO_STRICT_SCALAR_TYPES)
IF (UNIX AND EQEMU_BUILD_STATIC)
SET(SERVER_LIBS ${SERVER_LIBS} libcrypt.a)
ENDIF ()
ENDIF() ENDIF()
ENDIF() ENDIF()
+6 -6
View File
@@ -1,7 +1,7 @@
# EQEmulator Core Server # EQEmulator Core Server
| Drone (Linux x64) | Drone (Windows x64) | |Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) |
|:---:|:---:| |:---:|:---:|:---:|
|[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) |[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) | |[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/v3utuu0dttm2cqd0?svg=true)](https://ci.appveyor.com/project/KimLS/server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp) |
*** ***
@@ -18,11 +18,11 @@
|**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)| |**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)|
### > Windows ### > 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 ### > 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) * 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 > curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh
@@ -56,7 +56,7 @@ forum, although pull requests will be much quicker and easier on all parties.
## Resources ## Resources
- [EQEmulator Forums](http://www.eqemulator.org/forums) - [EQEmulator Forums](http://www.eqemulator.org/forums)
- [EQEmulator Wiki](https://docs.eqemu.io/) - [EQEmulator Wiki](https://eqemu.gitbook.io/)
## Related Repositories ## Related Repositories
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests) * [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
+21
View File
@@ -0,0 +1,21 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
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
appveyor PushArtifact build_x64-bots.zip
+21
View File
@@ -0,0 +1,21 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=OFF -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
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
appveyor PushArtifact build_x64-no-bots.zip
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(export_sources SET(export_sources
main.cpp main.cpp
+8 -19
View File
@@ -25,15 +25,11 @@
#include "../../common/platform.h" #include "../../common/platform.h"
#include "../../common/crash.h" #include "../../common/crash.h"
#include "../../common/rulesys.h" #include "../../common/rulesys.h"
#include "../../common/strings.h" #include "../../common/string_util.h"
#include "../../common/content/world_content_service.h" #include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys; EQEmuLogSys LogSys;
WorldContentService content_service; WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ExportSpells(SharedDatabase *db); void ExportSpells(SharedDatabase *db);
void ExportSkillCaps(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db);
@@ -46,8 +42,6 @@ int main(int argc, char **argv)
LogSys.LoadLogSettingsDefaults(); LogSys.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Export Utility"); LogInfo("Client Files Export Utility");
if (!EQEmuConfig::LoadConfig()) { if (!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file"); LogError("Unable to load configuration file");
@@ -86,11 +80,10 @@ int main(int argc, char **argv)
return 1; return 1;
} }
} else { } else {
content_db.SetMySQL(database); content_db.SetMysql(database.getMySQL());
} }
LogSys.SetDatabase(&database) LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings() ->LoadLogDatabaseSettings()
->StartFileLogs(); ->StartFileLogs();
@@ -131,8 +124,7 @@ void ExportSpells(SharedDatabase *db)
{ {
LogInfo("Exporting Spells"); LogInfo("Exporting Spells");
std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath()); FILE *f = fopen("export/spells_us.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/spells_us.txt to write, skipping."); LogError("Unable to open export/spells_us.txt to write, skipping.");
return; return;
@@ -183,7 +175,7 @@ bool SkillUsable(SharedDatabase *db, int skill_id, int class_id)
} }
auto row = results.begin(); auto row = results.begin();
if (row[0] && Strings::ToInt(row[0]) > 0) { if (row[0] && atoi(row[0]) > 0) {
return true; return true;
} }
@@ -207,15 +199,14 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level)
} }
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
void ExportSkillCaps(SharedDatabase *db) void ExportSkillCaps(SharedDatabase *db)
{ {
LogInfo("Exporting Skill Caps"); LogInfo("Exporting Skill Caps");
std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()); FILE *f = fopen("export/SkillCaps.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/SkillCaps.txt to write, skipping."); LogError("Unable to open export/SkillCaps.txt to write, skipping.");
return; return;
@@ -245,8 +236,7 @@ void ExportBaseData(SharedDatabase *db)
{ {
LogInfo("Exporting Base Data"); LogInfo("Exporting Base Data");
std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath()); FILE *f = fopen("export/BaseData.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/BaseData.txt to write, skipping."); LogError("Unable to open export/BaseData.txt to write, skipping.");
return; return;
@@ -279,8 +269,7 @@ void ExportDBStrings(SharedDatabase *db)
{ {
LogInfo("Exporting DB Strings"); LogInfo("Exporting DB Strings");
std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()); FILE *f = fopen("export/dbstr_us.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/dbstr_us.txt to write, skipping."); LogError("Unable to open export/dbstr_us.txt to write, skipping.");
return; return;
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(import_sources SET(import_sources
main.cpp main.cpp
+32 -43
View File
@@ -23,15 +23,11 @@
#include "../../common/platform.h" #include "../../common/platform.h"
#include "../../common/crash.h" #include "../../common/crash.h"
#include "../../common/rulesys.h" #include "../../common/rulesys.h"
#include "../../common/strings.h" #include "../../common/string_util.h"
#include "../../common/content/world_content_service.h" #include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys; EQEmuLogSys LogSys;
WorldContentService content_service; WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ImportSpells(SharedDatabase *db); void ImportSpells(SharedDatabase *db);
void ImportSkillCaps(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db);
@@ -43,8 +39,6 @@ int main(int argc, char **argv) {
LogSys.LoadLogSettingsDefaults(); LogSys.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Import Utility"); LogInfo("Client Files Import Utility");
if(!EQEmuConfig::LoadConfig()) { if(!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file."); LogError("Unable to load configuration file.");
@@ -83,11 +77,10 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
} else { } else {
content_db.SetMySQL(database); content_db.SetMysql(database.getMySQL());
} }
LogSys.SetDatabase(&database) LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings() ->LoadLogDatabaseSettings()
->StartFileLogs(); ->StartFileLogs();
@@ -132,10 +125,9 @@ bool IsStringField(int i) {
void ImportSpells(SharedDatabase *db) { void ImportSpells(SharedDatabase *db) {
LogInfo("Importing Spells"); LogInfo("Importing Spells");
std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath()); FILE *f = fopen("import/spells_us.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/spells_us.txt to read, skipping.");
return; return;
} }
@@ -154,8 +146,8 @@ void ImportSpells(SharedDatabase *db) {
} }
} }
std::string escaped = ::Strings::Escape(buffer); std::string escaped = ::EscapeString(buffer);
auto split = Strings::Split(escaped, '^'); auto split = SplitString(escaped, '^');
int line_columns = (int)split.size(); int line_columns = (int)split.size();
std::string sql; std::string sql;
@@ -222,10 +214,9 @@ void ImportSpells(SharedDatabase *db) {
void ImportSkillCaps(SharedDatabase *db) { void ImportSkillCaps(SharedDatabase *db) {
LogInfo("Importing Skill Caps"); LogInfo("Importing Skill Caps");
std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath()); FILE *f = fopen("import/SkillCaps.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/SkillCaps.txt to read, skipping.");
return; return;
} }
@@ -234,17 +225,17 @@ void ImportSkillCaps(SharedDatabase *db) {
char buffer[2048]; char buffer[2048];
while(fgets(buffer, 2048, f)) { while(fgets(buffer, 2048, f)) {
auto split = Strings::Split(buffer, '^'); auto split = SplitString(buffer, '^');
if(split.size() < 4) { if(split.size() < 4) {
continue; continue;
} }
int class_id, skill_id, level, cap; int class_id, skill_id, level, cap;
class_id = Strings::ToInt(split[0].c_str()); class_id = atoi(split[0].c_str());
skill_id = Strings::ToInt(split[1].c_str()); skill_id = atoi(split[1].c_str());
level = Strings::ToInt(split[2].c_str()); level = atoi(split[2].c_str());
cap = Strings::ToInt(split[3].c_str()); cap = atoi(split[3].c_str());
std::string sql = StringFormat("INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)", std::string sql = StringFormat("INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)",
class_id, skill_id, level, cap); class_id, skill_id, level, cap);
@@ -258,10 +249,9 @@ void ImportSkillCaps(SharedDatabase *db) {
void ImportBaseData(SharedDatabase *db) { void ImportBaseData(SharedDatabase *db) {
LogInfo("Importing Base Data"); LogInfo("Importing Base Data");
std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath()); FILE *f = fopen("import/BaseData.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/BaseData.txt to read, skipping.");
return; return;
} }
@@ -270,7 +260,7 @@ void ImportBaseData(SharedDatabase *db) {
char buffer[2048]; char buffer[2048];
while(fgets(buffer, 2048, f)) { while(fgets(buffer, 2048, f)) {
auto split = Strings::Split(buffer, '^'); auto split = SplitString(buffer, '^');
if(split.size() < 10) { if(split.size() < 10) {
continue; continue;
@@ -280,16 +270,16 @@ void ImportBaseData(SharedDatabase *db) {
int level, class_id; int level, class_id;
double hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac; double hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac;
level = Strings::ToInt(split[0].c_str()); level = atoi(split[0].c_str());
class_id = Strings::ToInt(split[1].c_str()); class_id = atoi(split[1].c_str());
hp = Strings::ToFloat(split[2].c_str()); hp = atof(split[2].c_str());
mana = Strings::ToFloat(split[3].c_str()); mana = atof(split[3].c_str());
end = Strings::ToFloat(split[4].c_str()); end = atof(split[4].c_str());
unk1 = Strings::ToFloat(split[5].c_str()); unk1 = atof(split[5].c_str());
unk2 = Strings::ToFloat(split[6].c_str()); unk2 = atof(split[6].c_str());
hp_fac = Strings::ToFloat(split[7].c_str()); hp_fac = atof(split[7].c_str());
mana_fac = Strings::ToFloat(split[8].c_str()); mana_fac = atof(split[8].c_str());
end_fac = Strings::ToFloat(split[9].c_str()); end_fac = atof(split[9].c_str());
sql = StringFormat("INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, " sql = StringFormat("INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, "
"mana_fac, end_fac) VALUES(%d, %d, %f, %f, %f, %f, %f, %f, %f, %f)", "mana_fac, end_fac) VALUES(%d, %d, %f, %f, %f, %f, %f, %f, %f, %f)",
@@ -304,10 +294,9 @@ void ImportBaseData(SharedDatabase *db) {
void ImportDBStrings(SharedDatabase *db) { void ImportDBStrings(SharedDatabase *db) {
LogInfo("Importing DB Strings"); LogInfo("Importing DB Strings");
std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath()); FILE *f = fopen("import/dbstr_us.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/dbstr_us.txt to read, skipping.");
return; return;
} }
@@ -329,7 +318,7 @@ void ImportDBStrings(SharedDatabase *db) {
} }
} }
auto split = Strings::Split(buffer, '^'); auto split = SplitString(buffer, '^');
if(split.size() < 2) { if(split.size() < 2) {
continue; continue;
@@ -339,11 +328,11 @@ void ImportDBStrings(SharedDatabase *db) {
int id, type; int id, type;
std::string value; std::string value;
id = Strings::ToInt(split[0].c_str()); id = atoi(split[0].c_str());
type = Strings::ToInt(split[1].c_str()); type = atoi(split[1].c_str());
if(split.size() >= 3) { 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')", sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')",
+40 -75
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(common_sources SET(common_sources
base_packet.cpp base_packet.cpp
@@ -7,7 +7,6 @@ SET(common_sources
compression.cpp compression.cpp
condition.cpp condition.cpp
content/world_content_service.cpp content/world_content_service.cpp
discord/discord.cpp
crash.cpp crash.cpp
crc16.cpp crc16.cpp
crc32.cpp crc32.cpp
@@ -15,9 +14,6 @@ SET(common_sources
database.cpp database.cpp
database_conversions.cpp database_conversions.cpp
database_instances.cpp database_instances.cpp
database/database_update_manifest.cpp
database/database_update_manifest_bots.cpp
database/database_update.cpp
dbcore.cpp dbcore.cpp
deity.cpp deity.cpp
dynamic_zone_base.cpp dynamic_zone_base.cpp
@@ -36,13 +32,10 @@ SET(common_sources
eq_stream_proxy.cpp eq_stream_proxy.cpp
eqtime.cpp eqtime.cpp
event_sub.cpp event_sub.cpp
events/player_event_logs.cpp
events/player_event_discord_formatter.cpp
expedition_lockout_timer.cpp expedition_lockout_timer.cpp
extprofile.cpp extprofile.cpp
discord/discord_manager.cpp
faction.cpp faction.cpp
file.cpp file_util.cpp
guild_base.cpp guild_base.cpp
guilds.cpp guilds.cpp
inventory_profile.cpp inventory_profile.cpp
@@ -66,11 +59,8 @@ SET(common_sources
packet_dump.cpp packet_dump.cpp
packet_dump_file.cpp packet_dump_file.cpp
packet_functions.cpp packet_functions.cpp
path_manager.cpp
perl_eqdb.cpp perl_eqdb.cpp
perl_eqdb_res.cpp perl_eqdb_res.cpp
process/process.cpp
process.cpp
proc_launcher.cpp proc_launcher.cpp
profanity_manager.cpp profanity_manager.cpp
ptimer.cpp ptimer.cpp
@@ -85,15 +75,13 @@ SET(common_sources
shareddb.cpp shareddb.cpp
skills.cpp skills.cpp
spdat.cpp spdat.cpp
strings.cpp string_util.cpp
struct_strategy.cpp struct_strategy.cpp
textures.cpp textures.cpp
timer.cpp timer.cpp
unix.cpp unix.cpp
platform.cpp platform.cpp
json/json.hpp
json/jsoncpp.cpp json/jsoncpp.cpp
zone_store.cpp
net/console_server.cpp net/console_server.cpp
net/console_server_connection.cpp net/console_server_connection.cpp
net/crc32.cpp net/crc32.cpp
@@ -130,9 +118,6 @@ SET(repositories
# Criteria # Criteria
repositories/criteria/content_filter_criteria.h repositories/criteria/content_filter_criteria.h
repositories/base/base_grid_repository.h
repositories/base/base_grid_entries_repository.h
# Base Repositories # Base Repositories
repositories/base/base_aa_ability_repository.h repositories/base/base_aa_ability_repository.h
repositories/base/base_aa_ranks_repository.h repositories/base/base_aa_ranks_repository.h
@@ -152,7 +137,6 @@ SET(repositories
repositories/base/base_auras_repository.h repositories/base/base_auras_repository.h
repositories/base/base_base_data_repository.h repositories/base/base_base_data_repository.h
repositories/base/base_blocked_spells_repository.h repositories/base/base_blocked_spells_repository.h
repositories/base/base_books_repository.h
repositories/base/base_bugs_repository.h repositories/base/base_bugs_repository.h
repositories/base/base_bug_reports_repository.h repositories/base/base_bug_reports_repository.h
repositories/base/base_buyer_repository.h repositories/base/base_buyer_repository.h
@@ -169,7 +153,6 @@ SET(repositories
repositories/base/base_character_data_repository.h repositories/base/base_character_data_repository.h
repositories/base/base_character_disciplines_repository.h repositories/base/base_character_disciplines_repository.h
repositories/base/base_character_expedition_lockouts_repository.h repositories/base/base_character_expedition_lockouts_repository.h
repositories/base/base_character_exp_modifiers_repository.h
repositories/base/base_character_inspect_messages_repository.h repositories/base/base_character_inspect_messages_repository.h
repositories/base/base_character_instance_safereturns_repository.h repositories/base/base_character_instance_safereturns_repository.h
repositories/base/base_character_item_recast_repository.h repositories/base/base_character_item_recast_repository.h
@@ -177,37 +160,32 @@ SET(repositories
repositories/base/base_character_leadership_abilities_repository.h repositories/base/base_character_leadership_abilities_repository.h
repositories/base/base_character_material_repository.h repositories/base/base_character_material_repository.h
repositories/base/base_character_memmed_spells_repository.h repositories/base/base_character_memmed_spells_repository.h
repositories/base/base_character_peqzone_flags_repository.h
repositories/base/base_character_pet_buffs_repository.h repositories/base/base_character_pet_buffs_repository.h
repositories/base/base_character_pet_info_repository.h repositories/base/base_character_pet_info_repository.h
repositories/base/base_character_pet_inventory_repository.h repositories/base/base_character_pet_inventory_repository.h
repositories/base/base_character_potionbelt_repository.h repositories/base/base_character_potionbelt_repository.h
repositories/base/base_character_skills_repository.h repositories/base/base_character_skills_repository.h
repositories/base/base_character_spells_repository.h repositories/base/base_character_spells_repository.h
repositories/base/base_character_tasks_repository.h
repositories/base/base_character_task_timers_repository.h repositories/base/base_character_task_timers_repository.h
repositories/base/base_character_tasks_repository.h
repositories/base/base_char_create_combinations_repository.h repositories/base/base_char_create_combinations_repository.h
repositories/base/base_char_create_point_allocations_repository.h repositories/base/base_char_create_point_allocations_repository.h
repositories/base/base_char_recipe_list_repository.h repositories/base/base_char_recipe_list_repository.h
repositories/base/base_chatchannels_repository.h
repositories/base/base_chatchannel_reserved_names_repository.h
repositories/base/base_completed_shared_tasks_repository.h
repositories/base/base_completed_shared_task_activity_state_repository.h
repositories/base/base_completed_shared_task_members_repository.h
repositories/base/base_completed_tasks_repository.h repositories/base/base_completed_tasks_repository.h
repositories/base/base_completed_shared_tasks_repository.h
repositories/base/base_completed_shared_task_members_repository.h
repositories/base/base_completed_shared_task_activity_state_repository.h
repositories/base/base_content_flags_repository.h repositories/base/base_content_flags_repository.h
repositories/base/base_damageshieldtypes_repository.h repositories/base/base_damageshieldtypes_repository.h
repositories/base/base_data_buckets_repository.h repositories/base/base_data_buckets_repository.h
repositories/base/base_db_str_repository.h repositories/base/base_db_str_repository.h
repositories/base/base_discord_webhooks_repository.h
repositories/base/base_discovered_items_repository.h repositories/base/base_discovered_items_repository.h
repositories/base/base_doors_repository.h repositories/base/base_doors_repository.h
repositories/base/base_dynamic_zones_repository.h repositories/base/base_dynamic_zones_repository.h
repositories/base/base_dynamic_zone_members_repository.h repositories/base/base_dynamic_zone_members_repository.h
repositories/base/base_dynamic_zone_templates_repository.h repositories/base/base_eventlog_repository.h
repositories/base/base_expeditions_repository.h repositories/base/base_expeditions_repository.h
repositories/base/base_expedition_lockouts_repository.h repositories/base/base_expedition_lockouts_repository.h
repositories/base/base_faction_association_repository.h
repositories/base/base_faction_base_data_repository.h repositories/base/base_faction_base_data_repository.h
repositories/base/base_faction_list_repository.h repositories/base/base_faction_list_repository.h
repositories/base/base_faction_list_mod_repository.h repositories/base/base_faction_list_mod_repository.h
@@ -217,14 +195,18 @@ SET(repositories
repositories/base/base_friends_repository.h repositories/base/base_friends_repository.h
repositories/base/base_global_loot_repository.h repositories/base/base_global_loot_repository.h
repositories/base/base_gm_ips_repository.h repositories/base/base_gm_ips_repository.h
repositories/base/base_goallists_repository.h
repositories/base/base_graveyard_repository.h repositories/base/base_graveyard_repository.h
repositories/base/base_grid_repository.h
repositories/base/base_grid_entries_repository.h
repositories/base/base_ground_spawns_repository.h repositories/base/base_ground_spawns_repository.h
repositories/base/base_group_id_repository.h repositories/base/base_group_id_repository.h
repositories/base/base_group_leaders_repository.h repositories/base/base_group_leaders_repository.h
repositories/base/base_guilds_repository.h repositories/base/base_guilds_repository.h
repositories/base/base_guild_members_repository.h
repositories/base/base_guild_ranks_repository.h repositories/base/base_guild_ranks_repository.h
repositories/base/base_guild_relations_repository.h repositories/base/base_guild_relations_repository.h
repositories/base/base_horses_repository.h repositories/base/base_hackers_repository.h
repositories/base/base_instance_list_repository.h repositories/base/base_instance_list_repository.h
repositories/base/base_instance_list_player_repository.h repositories/base/base_instance_list_player_repository.h
repositories/base/base_inventory_repository.h repositories/base/base_inventory_repository.h
@@ -265,12 +247,10 @@ SET(repositories
repositories/base/base_perl_event_export_settings_repository.h repositories/base/base_perl_event_export_settings_repository.h
repositories/base/base_petitions_repository.h repositories/base/base_petitions_repository.h
repositories/base/base_pets_repository.h repositories/base/base_pets_repository.h
repositories/base/base_pets_beastlord_data_repository.h
repositories/base/base_pets_equipmentset_repository.h repositories/base/base_pets_equipmentset_repository.h
repositories/base/base_pets_equipmentset_entries_repository.h repositories/base/base_pets_equipmentset_entries_repository.h
repositories/base/base_player_titlesets_repository.h repositories/base/base_player_titlesets_repository.h
repositories/base/base_player_event_log_settings_repository.h repositories/base/base_proximities_repository.h
repositories/base/base_player_event_logs_repository.h
repositories/base/base_quest_globals_repository.h repositories/base/base_quest_globals_repository.h
repositories/base/base_raid_details_repository.h repositories/base/base_raid_details_repository.h
repositories/base/base_raid_members_repository.h repositories/base/base_raid_members_repository.h
@@ -330,7 +310,6 @@ SET(repositories
repositories/auras_repository.h repositories/auras_repository.h
repositories/base_data_repository.h repositories/base_data_repository.h
repositories/blocked_spells_repository.h repositories/blocked_spells_repository.h
repositories/books_repository.h
repositories/bugs_repository.h repositories/bugs_repository.h
repositories/bug_reports_repository.h repositories/bug_reports_repository.h
repositories/buyer_repository.h repositories/buyer_repository.h
@@ -347,7 +326,6 @@ SET(repositories
repositories/character_data_repository.h repositories/character_data_repository.h
repositories/character_disciplines_repository.h repositories/character_disciplines_repository.h
repositories/character_expedition_lockouts_repository.h repositories/character_expedition_lockouts_repository.h
repositories/character_exp_modifiers_repository.h
repositories/character_inspect_messages_repository.h repositories/character_inspect_messages_repository.h
repositories/character_instance_safereturns_repository.h repositories/character_instance_safereturns_repository.h
repositories/character_item_recast_repository.h repositories/character_item_recast_repository.h
@@ -355,37 +333,32 @@ SET(repositories
repositories/character_leadership_abilities_repository.h repositories/character_leadership_abilities_repository.h
repositories/character_material_repository.h repositories/character_material_repository.h
repositories/character_memmed_spells_repository.h repositories/character_memmed_spells_repository.h
repositories/character_peqzone_flags_repository.h
repositories/character_pet_buffs_repository.h repositories/character_pet_buffs_repository.h
repositories/character_pet_info_repository.h repositories/character_pet_info_repository.h
repositories/character_pet_inventory_repository.h repositories/character_pet_inventory_repository.h
repositories/character_potionbelt_repository.h repositories/character_potionbelt_repository.h
repositories/character_skills_repository.h repositories/character_skills_repository.h
repositories/character_spells_repository.h repositories/character_spells_repository.h
repositories/character_tasks_repository.h
repositories/character_task_timers_repository.h repositories/character_task_timers_repository.h
repositories/character_tasks_repository.h
repositories/char_create_combinations_repository.h repositories/char_create_combinations_repository.h
repositories/char_create_point_allocations_repository.h repositories/char_create_point_allocations_repository.h
repositories/char_recipe_list_repository.h repositories/char_recipe_list_repository.h
repositories/chatchannels_repository.h
repositories/chatchannel_reserved_names_repository.h
repositories/completed_shared_tasks_repository.h
repositories/completed_shared_task_activity_state_repository.h
repositories/completed_shared_task_members_repository.h
repositories/completed_tasks_repository.h repositories/completed_tasks_repository.h
repositories/completed_shared_tasks_repository.h
repositories/completed_shared_task_members_repository.h
repositories/completed_shared_task_activity_state_repository.h
repositories/content_flags_repository.h repositories/content_flags_repository.h
repositories/damageshieldtypes_repository.h repositories/damageshieldtypes_repository.h
repositories/data_buckets_repository.h repositories/data_buckets_repository.h
repositories/db_str_repository.h repositories/db_str_repository.h
repositories/discord_webhooks_repository.h
repositories/discovered_items_repository.h repositories/discovered_items_repository.h
repositories/doors_repository.h repositories/doors_repository.h
repositories/dynamic_zones_repository.h repositories/dynamic_zones_repository.h
repositories/dynamic_zone_members_repository.h repositories/dynamic_zone_members_repository.h
repositories/dynamic_zone_templates_repository.h repositories/eventlog_repository.h
repositories/expeditions_repository.h repositories/expeditions_repository.h
repositories/expedition_lockouts_repository.h repositories/expedition_lockouts_repository.h
repositories/faction_association_repository.h
repositories/faction_base_data_repository.h repositories/faction_base_data_repository.h
repositories/faction_list_repository.h repositories/faction_list_repository.h
repositories/faction_list_mod_repository.h repositories/faction_list_mod_repository.h
@@ -395,14 +368,18 @@ SET(repositories
repositories/friends_repository.h repositories/friends_repository.h
repositories/global_loot_repository.h repositories/global_loot_repository.h
repositories/gm_ips_repository.h repositories/gm_ips_repository.h
repositories/goallists_repository.h
repositories/graveyard_repository.h repositories/graveyard_repository.h
repositories/grid_repository.h
repositories/grid_entries_repository.h
repositories/ground_spawns_repository.h repositories/ground_spawns_repository.h
repositories/group_id_repository.h repositories/group_id_repository.h
repositories/group_leaders_repository.h repositories/group_leaders_repository.h
repositories/guilds_repository.h repositories/guilds_repository.h
repositories/guild_members_repository.h
repositories/guild_ranks_repository.h repositories/guild_ranks_repository.h
repositories/guild_relations_repository.h repositories/guild_relations_repository.h
repositories/horses_repository.h repositories/hackers_repository.h
repositories/instance_list_repository.h repositories/instance_list_repository.h
repositories/instance_list_player_repository.h repositories/instance_list_player_repository.h
repositories/inventory_repository.h repositories/inventory_repository.h
@@ -443,12 +420,10 @@ SET(repositories
repositories/perl_event_export_settings_repository.h repositories/perl_event_export_settings_repository.h
repositories/petitions_repository.h repositories/petitions_repository.h
repositories/pets_repository.h repositories/pets_repository.h
repositories/pets_beastlord_data_repository.h
repositories/pets_equipmentset_repository.h repositories/pets_equipmentset_repository.h
repositories/pets_equipmentset_entries_repository.h repositories/pets_equipmentset_entries_repository.h
repositories/player_titlesets_repository.h repositories/player_titlesets_repository.h
repositories/player_event_log_settings_repository.h repositories/proximities_repository.h
repositories/player_event_logs_repository.h
repositories/quest_globals_repository.h repositories/quest_globals_repository.h
repositories/raid_details_repository.h repositories/raid_details_repository.h
repositories/raid_members_repository.h repositories/raid_members_repository.h
@@ -489,10 +464,13 @@ SET(repositories
repositories/zone_repository.h repositories/zone_repository.h
repositories/zone_points_repository.h repositories/zone_points_repository.h
) # Non-Comformative
repositories/character_recipe_list_repository.h
)
SET(common_headers SET(common_headers
additive_lagged_fibonacci_engine.h additive_lagged_fibonacci_engine.h
any.h
base_packet.h base_packet.h
base_data.h base_data.h
bodytypes.h bodytypes.h
@@ -511,11 +489,8 @@ SET(common_headers
data_verification.h data_verification.h
database.h database.h
database_schema.h database_schema.h
database/database_update.h
dbcore.h dbcore.h
deity.h deity.h
discord/discord.h
discord/discord_manager.h
dynamic_zone_base.h dynamic_zone_base.h
emu_constants.h emu_constants.h
emu_limits.h emu_limits.h
@@ -538,15 +513,12 @@ SET(common_headers
eq_stream_locator.h eq_stream_locator.h
eq_stream_proxy.h eq_stream_proxy.h
eqtime.h eqtime.h
events/player_event_logs.h
events/player_event_discord_formatter.h
events/player_events.h
errmsg.h errmsg.h
event_sub.h event_sub.h
expedition_lockout_timer.h expedition_lockout_timer.h
extprofile.h extprofile.h
faction.h faction.h
file.h file_util.h
features.h features.h
fixed_memory_hash_set.h fixed_memory_hash_set.h
fixed_memory_variable_hash_set.h fixed_memory_variable_hash_set.h
@@ -582,17 +554,13 @@ SET(common_headers
packet_dump.h packet_dump.h
packet_dump_file.h packet_dump_file.h
packet_functions.h packet_functions.h
path_manager.cpp
platform.h platform.h
process/process.h
process.h
proc_launcher.h proc_launcher.h
profanity_manager.h profanity_manager.h
profiler.h profiler.h
ptimer.h ptimer.h
queue.h queue.h
races.h races.h
raid.h
random.h random.h
rdtsc.h rdtsc.h
rulesys.h rulesys.h
@@ -607,7 +575,7 @@ SET(common_headers
shareddb.h shareddb.h
skills.h skills.h
spdat.h spdat.h
strings.h string_util.h
struct_strategy.h struct_strategy.h
tasks.h tasks.h
textures.h textures.h
@@ -616,11 +584,10 @@ SET(common_headers
unix.h unix.h
useperl.h useperl.h
version.h version.h
zone_store.h zone_numbers.h
event/event_loop.h event/event_loop.h
event/task.h event/task.h
event/timer.h event/timer.h
json/json_archive_single_line.h
json/json.h json/json.h
json/json-forwards.h json/json-forwards.h
net/console_server.h net/console_server.h
@@ -669,8 +636,6 @@ SET(common_headers
patches/uf_limits.h patches/uf_limits.h
patches/uf_ops.h patches/uf_ops.h
patches/uf_structs.h patches/uf_structs.h
termcolor/rang.hpp
stacktrace/backward.hpp
StackWalker/StackWalker.h StackWalker/StackWalker.h
util/memory_stream.h util/memory_stream.h
util/directory.h util/directory.h
@@ -681,13 +646,13 @@ SOURCE_GROUP(Event FILES
event/event_loop.h event/event_loop.h
event/timer.h event/timer.h
event/task.h event/task.h
) )
SOURCE_GROUP(Json FILES SOURCE_GROUP(Json FILES
json/json.h json/json.h
json/jsoncpp.cpp json/jsoncpp.cpp
json/json-forwards.h json/json-forwards.h
) )
SOURCE_GROUP(Net FILES SOURCE_GROUP(Net FILES
net/console_server.cpp net/console_server.cpp
@@ -724,7 +689,7 @@ SOURCE_GROUP(Net FILES
net/websocket_server.h net/websocket_server.h
net/websocket_server_connection.cpp net/websocket_server_connection.cpp
net/websocket_server_connection.h net/websocket_server_connection.h
) )
SOURCE_GROUP(Patches FILES SOURCE_GROUP(Patches FILES
patches/patches.h patches/patches.h
@@ -768,12 +733,12 @@ SOURCE_GROUP(Patches FILES
patches/titanium_limits.cpp patches/titanium_limits.cpp
patches/uf.cpp patches/uf.cpp
patches/uf_limits.cpp patches/uf_limits.cpp
) )
SOURCE_GROUP(StackWalker FILES SOURCE_GROUP(StackWalker FILES
StackWalker/StackWalker.h StackWalker/StackWalker.h
StackWalker/StackWalker.cpp StackWalker/StackWalker.cpp
) )
SOURCE_GROUP(Util FILES SOURCE_GROUP(Util FILES
util/memory_stream.h util/memory_stream.h
@@ -781,16 +746,16 @@ SOURCE_GROUP(Util FILES
util/directory.h util/directory.h
util/uuid.cpp util/uuid.cpp
util/uuid.h util/uuid.h
) )
INCLUDE_DIRECTORIES(Patches SocketLib StackWalker) INCLUDE_DIRECTORIES(Patches SocketLib StackWalker)
ADD_LIBRARY(common ${common_sources} ${common_headers} ${repositories}) ADD_LIBRARY(common ${common_sources} ${common_headers} ${repositories})
IF (UNIX) IF(UNIX)
SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result)
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
ENDIF (UNIX) ENDIF(UNIX)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+190
View File
@@ -0,0 +1,190 @@
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
// EQ::Any is a modified version of Boost::Any and as such retains the Boost licensing.
#ifndef EQEMU_COMMON_ANY_H
#define EQEMU_COMMON_ANY_H
#include <algorithm>
#include <typeinfo>
namespace EQ
{
class Any
{
public:
Any()
: content(nullptr)
{
}
template<typename ValueType>
Any(const ValueType &value)
: content(new Holder<ValueType>(value))
{
}
Any(const Any &other)
: content(other.content ? other.content->clone() : 0)
{
}
~Any()
{
if(content)
delete content;
}
Any& swap(Any &rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
Any& operator=(const ValueType &rhs)
{
Any(rhs).swap(*this);
return *this;
}
Any& operator=(Any rhs)
{
rhs.swap(*this);
return *this;
}
bool empty() const
{
return !content;
}
const std::type_info& type() const
{
return content ? content->type() : typeid(void);
}
class Placeholder
{
public:
virtual ~Placeholder()
{
}
virtual const std::type_info& type() const = 0;
virtual Placeholder* clone() const = 0;
};
template<typename ValueType>
class Holder : public Placeholder
{
public:
Holder(const ValueType &value)
: held(value)
{
}
virtual const std::type_info& type() const
{
return typeid(ValueType);
}
virtual Placeholder* clone() const
{
return new Holder(held);
}
ValueType held;
private:
Holder& operator=(const Holder&);
};
private:
template<typename ValueType>
friend ValueType* any_cast(Any*);
template<typename ValueType>
friend ValueType* unsafe_any_cast(Any*);
Placeholder* content;
};
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{
return "DBI::bad_any_cast: failed conversion using DBI::any_cast";
}
};
template<typename ValueType>
ValueType* any_cast(Any* operand)
{
return operand &&
operand->type() == typeid(ValueType) ? &static_cast<Any::Holder<ValueType>*>(operand->content)->held : nullptr;
}
template<typename ValueType>
inline const ValueType* any_cast(const Any* operand)
{
return any_cast<ValueType>(const_cast<Any*>(operand));
}
template<typename ValueType>
ValueType any_cast(Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
nonref* result = any_cast<nonref>(&operand);
if(!result)
throw bad_any_cast();
return *result;
}
template<typename ValueType>
inline ValueType any_cast(const Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
return any_cast<const nonref&>(const_cast<Any&>(operand));
}
template<typename ValueType>
inline ValueType* unsafe_any_cast(Any* operand)
{
return &static_cast<Any::Holder<ValueType>*>(operand->content)->held;
}
template<typename ValueType>
inline const ValueType* unsafe_any_cast(const Any* operand)
{
return unsafe_any_cast<ValueType>(const_cast<Any*>(operand));
}
}
#endif
+8 -8
View File
@@ -23,18 +23,18 @@
BasePacket::BasePacket(const unsigned char *buf, uint32 len) BasePacket::BasePacket(const unsigned char *buf, uint32 len)
{ {
pBuffer=nullptr; this->pBuffer=nullptr;
size=0; this->size=0;
_wpos = 0; this->_wpos = 0;
_rpos = 0; this->_rpos = 0;
timestamp.tv_sec = 0; this->timestamp.tv_sec = 0;
if (len>0) { if (len>0) {
size=len; this->size=len;
pBuffer= new unsigned char[len]; pBuffer= new unsigned char[len];
if (buf) { if (buf) {
memcpy(pBuffer,buf,len); memcpy(this->pBuffer,buf,len);
} else { } else {
memset(pBuffer,0,len); memset(this->pBuffer,0,len);
} }
} }
} }
+5 -83
View File
@@ -17,7 +17,6 @@
*/ */
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/classes.h" #include "../common/classes.h"
#include "data_verification.h"
const char *GetClassIDName(uint8 class_id, uint8 level) const char *GetClassIDName(uint8 class_id, uint8 level)
{ {
@@ -381,12 +380,12 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Merchant"; return "Merchant";
case DISCORD_MERCHANT: case DISCORD_MERCHANT:
return "Discord Merchant"; return "Discord Merchant";
case ADVENTURE_RECRUITER: case ADVENTURERECRUITER:
return "Adventure Recruiter"; return "Adventure Recruiter";
case ADVENTURE_MERCHANT: case ADVENTUREMERCHANT:
return "Adventure Merchant"; return "Adventure Merchant";
case LDON_TREASURE: case CORPSE_CLASS:
return "LDoN Treasure"; return "Corpse Class";
case TRIBUTE_MASTER: case TRIBUTE_MASTER:
return "Tribute Master"; return "Tribute Master";
case GUILD_TRIBUTE_MASTER: case GUILD_TRIBUTE_MASTER:
@@ -401,7 +400,7 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Fellowship Master"; return "Fellowship Master";
case ALT_CURRENCY_MERCHANT: case ALT_CURRENCY_MERCHANT:
return "Alternate Currency Merchant"; return "Alternate Currency Merchant";
case MERCENARY_MASTER: case MERCERNARY_MASTER:
return "Mercenary Liaison"; return "Mercenary Liaison";
default: default:
return "Unknown"; return "Unknown";
@@ -631,20 +630,6 @@ bool IsINTCasterClass(uint8 class_id)
} }
} }
bool IsHeroicINTCasterClass(uint8 class_id)
{
switch (class_id) {
case NECROMANCER:
case WIZARD:
case MAGICIAN:
case ENCHANTER:
case SHADOWKNIGHT:
return true;
default:
return false;
}
}
bool IsWISCasterClass(uint8 class_id) bool IsWISCasterClass(uint8 class_id)
{ {
switch (class_id) { switch (class_id) {
@@ -657,21 +642,6 @@ bool IsWISCasterClass(uint8 class_id)
} }
} }
bool IsHeroicWISCasterClass(uint8 class_id)
{
switch (class_id) {
case CLERIC:
case DRUID:
case SHAMAN:
case PALADIN:
case BEASTLORD:
case RANGER:
return true;
default:
return false;
}
}
bool IsPlateClass(uint8 class_id) bool IsPlateClass(uint8 class_id)
{ {
switch (class_id) { switch (class_id) {
@@ -751,51 +721,3 @@ uint8 ClassArmorType(uint8 class_id)
return ARMOR_TYPE_UNKNOWN; return ARMOR_TYPE_UNKNOWN;
} }
} }
const std::string GetPlayerClassAbbreviation(uint8 class_id)
{
if (!EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) {
return std::string("UNK");
}
switch (class_id) {
case WARRIOR:
return "WAR";
case CLERIC:
return "CLR";
case PALADIN:
return "PAL";
case RANGER:
return "RNG";
case SHADOWKNIGHT:
return "SHD";
case DRUID:
return "DRU";
case MONK:
return "MNK";
case BARD:
return "BRD";
case ROGUE:
return "ROG";
case SHAMAN:
return "SHM";
case NECROMANCER:
return "NEC";
case WIZARD:
return "WIZ";
case MAGICIAN:
return "MAG";
case ENCHANTER:
return "ENC";
case BEASTLORD:
return "BST";
case BERSERKER:
return "BER";
}
return std::string("UNK");
}
bool IsPlayerClass(uint8 class_id) {
return EQ::ValueWithin(class_id, WARRIOR, BERSERKER);
}
+6 -11
View File
@@ -19,9 +19,7 @@
#define CLASSES_CH #define CLASSES_CH
#include "../common/types.h" #include "../common/types.h"
#include <string>
#define NO_CLASS 0
#define WARRIOR 1 #define WARRIOR 1
#define CLERIC 2 #define CLERIC 2
#define PALADIN 3 #define PALADIN 3
@@ -57,9 +55,10 @@
#define BANKER 40 #define BANKER 40
#define MERCHANT 41 #define MERCHANT 41
#define DISCORD_MERCHANT 59 #define DISCORD_MERCHANT 59
#define ADVENTURE_RECRUITER 60 #define ADVENTURERECRUITER 60
#define ADVENTURE_MERCHANT 61 #define ADVENTUREMERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva #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 TRIBUTE_MASTER 63
#define GUILD_TRIBUTE_MASTER 64 // not sure #define GUILD_TRIBUTE_MASTER 64 // not sure
#define GUILD_BANKER 66 #define GUILD_BANKER 66
@@ -67,7 +66,7 @@
#define DARK_REIGN_MERCHANT 68 #define DARK_REIGN_MERCHANT 68
#define FELLOWSHIP_MASTER 69 #define FELLOWSHIP_MASTER 69
#define ALT_CURRENCY_MERCHANT 70 #define ALT_CURRENCY_MERCHANT 70
#define MERCENARY_MASTER 71 #define MERCERNARY_MASTER 71
// player class values // player class values
@@ -128,9 +127,6 @@
const char* GetClassIDName(uint8 class_id, uint8 level = 0); const char* GetClassIDName(uint8 class_id, uint8 level = 0);
const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0); const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0);
bool IsPlayerClass(uint8 class_id);
const std::string GetPlayerClassAbbreviation(uint8 class_id);
uint32 GetPlayerClassValue(uint8 class_id); uint32 GetPlayerClassValue(uint8 class_id);
uint32 GetPlayerClassBit(uint8 class_id); uint32 GetPlayerClassBit(uint8 class_id);
@@ -144,8 +140,7 @@ bool IsHybridClass(uint8 class_id);
bool IsCasterClass(uint8 class_id); bool IsCasterClass(uint8 class_id);
bool IsINTCasterClass(uint8 class_id); bool IsINTCasterClass(uint8 class_id);
bool IsWISCasterClass(uint8 class_id); bool IsWISCasterClass(uint8 class_id);
bool IsHeroicINTCasterClass(uint8 class_id);
bool IsHeroicWISCasterClass(uint8 class_id);
bool IsPlateClass(uint8 class_id); bool IsPlateClass(uint8 class_id);
bool IsChainClass(uint8 class_id); bool IsChainClass(uint8 class_id);
bool IsLeatherClass(uint8 class_id); bool IsLeatherClass(uint8 class_id);
+28 -21
View File
@@ -39,15 +39,15 @@ namespace EQEmuCommand {
{ {
if (cmd[{"-d", "--debug"}]) { if (cmd[{"-d", "--debug"}]) {
std::cout << "Positional args:\n"; std::cout << "Positional args:\n";
for (auto &pos_arg: cmd.pos_args()) for (auto &pos_arg : cmd.pos_args())
std::cout << '\t' << pos_arg << std::endl; std::cout << '\t' << pos_arg << std::endl;
std::cout << "\nFlags:\n"; std::cout << "\nFlags:\n";
for (auto &flag: cmd.flags()) for (auto &flag : cmd.flags())
std::cout << '\t' << flag << std::endl; std::cout << '\t' << flag << std::endl;
std::cout << "\nParameters:\n"; std::cout << "\nParameters:\n";
for (auto &param: cmd.params()) for (auto &param : cmd.params())
std::cout << '\t' << param.first << " : " << param.second << std::endl; std::cout << '\t' << param.first << " : " << param.second << std::endl;
} }
} }
@@ -70,21 +70,21 @@ namespace EQEmuCommand {
bool arguments_filled = true; bool arguments_filled = true;
int index = 2; int index = 2;
for (auto &arg: arguments) { for (auto &arg : arguments) {
if (cmd(arg).str().empty() && cmd(index).str().empty()) { if (cmd(arg).str().empty() && cmd(index).str().empty()) {
arguments_filled = false; arguments_filled = false;
} }
index++; index++;
} }
if (!arguments_filled || (argc == 2 && !cmd[{"-h", "--help"}]) || (argc == 3 && cmd[{"-h", "--help"}])) { if (!arguments_filled || argc == 2 || cmd[{"-h", "--help"}]) {
std::string arguments_string; std::string arguments_string;
for (auto &arg: arguments) { for (auto &arg : arguments) {
arguments_string += " " + arg; arguments_string += " " + arg;
} }
std::string options_string; std::string options_string;
for (auto &opt: options) { for (auto &opt : options) {
options_string += " " + opt + "\n"; options_string += " " + opt + "\n";
} }
@@ -124,6 +124,14 @@ namespace EQEmuCommand {
) )
{ {
std::string description; std::string description;
bool ran_command = false;
for (auto &it: in_function_map) {
if (it.first == argv[1]) {
(it.second)(argc, argv, cmd, description);
ran_command = true;
}
}
if (cmd[{"-h", "--help"}]) { if (cmd[{"-h", "--help"}]) {
std::cout << std::endl; std::cout << std::endl;
std::cout << std::cout <<
@@ -134,7 +142,9 @@ namespace EQEmuCommand {
<< std::endl << std::endl
<< std::endl; << std::endl;
// Get max command length for padding length /**
* Get max command length for padding length
*/
int max_command_length = 0; int max_command_length = 0;
for (auto &it: in_function_map) { for (auto &it: in_function_map) {
@@ -145,14 +155,18 @@ namespace EQEmuCommand {
} }
} }
// Display command menu /**
* Display command menu
*/
std::string command_section; std::string command_section;
for (auto &it: in_function_map) { for (auto &it: in_function_map) {
description.clear(); description = "";
(it.second)(argc, argv, cmd, description); (it.second)(argc, argv, cmd, description);
// Print section header /**
* Print section header
*/
std::string command_prefix = it.first.substr(0, it.first.find(":")); std::string command_prefix = it.first.substr(0, it.first.find(":"));
if (command_prefix.find("test") != std::string::npos) { if (command_prefix.find("test") != std::string::npos) {
@@ -164,7 +178,9 @@ namespace EQEmuCommand {
std::cout << termcolor::reset << command_prefix << std::endl; std::cout << termcolor::reset << command_prefix << std::endl;
} }
// Print commands /**
* Print commands
*/
std::stringstream command; std::stringstream command;
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset; command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str()); printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str());
@@ -175,15 +191,6 @@ namespace EQEmuCommand {
std::exit(0); std::exit(0);
} }
bool ran_command = false;
for (auto &it: in_function_map) {
if (it.first == argv[1]) {
(it.second)(argc, argv, cmd, description);
ran_command = true;
}
}
if (ran_command) { if (ran_command) {
std::exit(0); std::exit(0);
} }
+14 -135
View File
@@ -22,7 +22,6 @@
#include "../database.h" #include "../database.h"
#include "../rulesys.h" #include "../rulesys.h"
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../loottable.h"
#include "../repositories/content_flags_repository.h" #include "../repositories/content_flags_repository.h"
@@ -36,12 +35,8 @@ int WorldContentService::GetCurrentExpansion() const
return current_expansion; 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); int expansion = RuleI(Expansion, CurrentExpansion);
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) { if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
content_service.SetCurrentExpansion(expansion); content_service.SetCurrentExpansion(expansion);
@@ -52,8 +47,6 @@ WorldContentService *WorldContentService::SetExpansionContext()
GetCurrentExpansion(), GetCurrentExpansion(),
GetCurrentExpansionName() GetCurrentExpansionName()
); );
return this;
} }
std::string WorldContentService::GetCurrentExpansionName() std::string WorldContentService::GetCurrentExpansionName()
@@ -80,47 +73,15 @@ void WorldContentService::SetCurrentExpansion(int current_expansion)
/** /**
* @return * @return
*/ */
const std::vector<ContentFlagsRepository::ContentFlags> &WorldContentService::GetContentFlags() const const std::vector<std::string> &WorldContentService::GetContentFlags() const
{ {
return content_flags; 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 * @param content_flags
*/ */
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags) void WorldContentService::SetContentFlags(std::vector<std::string> content_flags)
{ {
WorldContentService::content_flags = content_flags; WorldContentService::content_flags = content_flags;
} }
@@ -129,10 +90,10 @@ void WorldContentService::SetContentFlags(const std::vector<ContentFlagsReposito
* @param content_flag * @param content_flag
* @return * @return
*/ */
bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag) bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag)
{ {
for (auto &f: GetContentFlags()) { for (auto &flag : GetContentFlags()) {
if (f.flag_name == content_flag && f.enabled == true) { if (flag == content_flag) {
return true; return true;
} }
} }
@@ -140,102 +101,20 @@ bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
return false; return false;
} }
/** void WorldContentService::ReloadContentFlags(Database &db)
* @param content_flag
* @return
*/
bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
{ {
for (auto &f: GetContentFlags()) { std::vector<std::string> set_content_flags;
if (f.flag_name == content_flag && f.enabled == false) { auto content_flags = ContentFlagsRepository::GetWhere(db, "enabled = 1");
return true;
}
}
return false; set_content_flags.reserve(content_flags.size());
} for (auto &flags: content_flags) {
set_content_flags.push_back(flags.flag_name);
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( LogInfo(
"Loaded content flag [{}] [{}]", "Enabled content flags [{}]",
f.flag_name, implode(", ", set_content_flags)
(f.enabled ? "Enabled" : "Disabled")
); );
}
SetContentFlags(set_content_flags); SetContentFlags(set_content_flags);
} }
Database *WorldContentService::GetDatabase() const
{
return m_database;
}
WorldContentService *WorldContentService::SetDatabase(Database *database)
{
WorldContentService::m_database = database;
return this;
}
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
{
auto flags = ContentFlagsRepository::GetWhere(
*GetDatabase(),
fmt::format("flag_name = '{}'", content_flag_name)
);
auto f = ContentFlagsRepository::NewEntity();
if (!flags.empty()) {
f = flags.front();
}
f.enabled = enabled ? 1 : 0;
f.flag_name = content_flag_name;
if (!flags.empty()) {
ContentFlagsRepository::UpdateOne(*GetDatabase(), f);
}
else {
ContentFlagsRepository::InsertOne(*GetDatabase(), f);
}
ReloadContentFlags();
}
+10 -25
View File
@@ -23,8 +23,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "../loottable.h"
#include "../repositories/content_flags_repository.h"
class Database; class Database;
@@ -54,7 +52,7 @@ namespace Expansion {
VeilOfAlaris, VeilOfAlaris,
RainOfFear, RainOfFear,
CallOfTheForsaken, CallOfTheForsaken,
TheDarkenedSea, TheDarkendSea,
TheBrokenMirror, TheBrokenMirror,
EmpiresOfKunark, EmpiresOfKunark,
RingOfScale, RingOfScale,
@@ -127,7 +125,7 @@ public:
bool IsVeilOfAlarisEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::VeilOfAlaris || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsVeilOfAlarisEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::VeilOfAlaris || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsRainOfFearEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RainOfFear || 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 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 IsTheBrokenMirrorEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBrokenMirror || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsEmpiresOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::EmpiresOfKunark || 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; } bool IsRingOfScaleEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RingOfScale || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
@@ -155,35 +153,22 @@ public:
bool IsCurrentExpansionVeilOfAlaris() { return current_expansion == Expansion::ExpansionNumber::VeilOfAlaris; } bool IsCurrentExpansionVeilOfAlaris() { return current_expansion == Expansion::ExpansionNumber::VeilOfAlaris; }
bool IsCurrentExpansionRainOfFear() { return current_expansion == Expansion::ExpansionNumber::RainOfFear; } bool IsCurrentExpansionRainOfFear() { return current_expansion == Expansion::ExpansionNumber::RainOfFear; }
bool IsCurrentExpansionCallOfTheForsaken() { return current_expansion == Expansion::ExpansionNumber::CallOfTheForsaken; } 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 IsCurrentExpansionTheBrokenMirror() { return current_expansion == Expansion::ExpansionNumber::TheBrokenMirror; }
bool IsCurrentExpansionEmpiresOfKunark() { return current_expansion == Expansion::ExpansionNumber::EmpiresOfKunark; } bool IsCurrentExpansionEmpiresOfKunark() { return current_expansion == Expansion::ExpansionNumber::EmpiresOfKunark; }
bool IsCurrentExpansionRingOfScale() { return current_expansion == Expansion::ExpansionNumber::RingOfScale; } bool IsCurrentExpansionRingOfScale() { return current_expansion == Expansion::ExpansionNumber::RingOfScale; }
bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; } bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; }
bool IsCurrentExpansionTormentOfVelious() { return current_expansion == Expansion::ExpansionNumber::TormentOfVelious; } 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(const 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: private:
int current_expansion{}; int current_expansion{};
std::vector<ContentFlagsRepository::ContentFlags> content_flags; std::vector<std::string> content_flags;
public:
// reference to database const std::vector<std::string> &GetContentFlags() const;
Database *m_database; bool IsContentFlagEnabled(const std::string& content_flag);
void SetContentFlags(std::vector<std::string> content_flags);
void ReloadContentFlags(Database &db);
void SetExpansionContext();
}; };
extern WorldContentService content_service; extern WorldContentService content_service;
+8 -141
View File
@@ -1,95 +1,6 @@
#include "global_define.h" #include "global_define.h"
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "crash.h" #include "crash.h"
#include "strings.h"
#include "process/process.h"
#include "http/httplib.h"
#include "http/uri.h"
#include "json/json.h"
#include "version.h"
#include "eqemu_config.h"
#include "serverinfo.h"
#include "rulesys.h"
#include "platform.h"
#include <cstdio>
#include <vector>
#if WINDOWS
#define popen _popen
#endif
void SendCrashReport(const std::string &crash_report)
{
// can configure multiple endpoints if need be
std::vector<std::string> endpoints = {
"http://spire.akkadius.com/api/v1/analytics/server-crash-report",
// "http://localhost:3010/api/v1/analytics/server-crash-report", // development
};
auto config = EQEmuConfig::get();
for (auto &e: endpoints) {
uri u(e);
std::string base_url = fmt::format("{}://{}", u.get_scheme(), u.get_host());
if (u.get_port()) {
base_url += fmt::format(":{}", u.get_port());
}
// client
httplib::Client r(base_url);
r.set_connection_timeout(1, 0);
r.set_read_timeout(1, 0);
r.set_write_timeout(1, 0);
// os info
auto os = EQ::GetOS();
auto cpus = EQ::GetCPUs();
auto process_id = EQ::GetPID();
auto rss = EQ::GetRSS() / 1048576.0;
auto uptime = static_cast<uint32>(EQ::GetUptime());
// payload
Json::Value p;
p["platform_name"] = GetPlatformName();
p["crash_report"] = crash_report;
p["server_version"] = CURRENT_VERSION;
p["compile_date"] = COMPILE_DATE;
p["compile_time"] = COMPILE_TIME;
p["server_name"] = config->LongName;
p["server_short_name"] = config->ShortName;
p["uptime"] = uptime;
p["os_machine"] = os.machine;
p["os_release"] = os.release;
p["os_version"] = os.version;
p["os_sysname"] = os.sysname;
p["process_id"] = process_id;
p["rss_memory"] = rss;
p["cpus"] = cpus.size();
p["origination_info"] = "";
if (!LogSys.origination_info.zone_short_name.empty()) {
p["origination_info"] = fmt::format(
"{} ({}) instance_id [{}]",
LogSys.origination_info.zone_short_name,
LogSys.origination_info.zone_long_name,
LogSys.origination_info.instance_id
);
}
std::stringstream payload;
payload << p;
if (auto res = r.Post(e, payload.str(), "application/json")) {
if (res->status == 200) {
LogInfo("Sent crash report");
}
else {
LogError("Failed to send crash report to [{}]", e);
}
}
}
}
#if defined(_WINDOWS) && defined(CRASH_LOGGING) #if defined(_WINDOWS) && defined(CRASH_LOGGING)
#include "StackWalker.h" #include "StackWalker.h"
@@ -101,30 +12,22 @@ public:
EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { } EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { }
virtual void OnOutput(LPCSTR szText) { virtual void OnOutput(LPCSTR szText) {
char buffer[4096]; char buffer[4096];
for (int i = 0; i < 4096; ++i) { for(int i = 0; i < 4096; ++i) {
if (szText[i] == 0) { if(szText[i] == 0) {
buffer[i] = '\0'; buffer[i] = '\0';
break; break;
} }
if (szText[i] == '\n' || szText[i] == '\r') { if(szText[i] == '\n' || szText[i] == '\r') {
buffer[i] = ' '; buffer[i] = ' ';
} } else {
else {
buffer[i] = szText[i]; buffer[i] = szText[i];
} }
} }
std::string line = buffer;
_lines.push_back(line);
Log(Logs::General, Logs::Crash, buffer); Log(Logs::General, Logs::Crash, buffer);
StackWalker::OnOutput(szText); StackWalker::OnOutput(szText);
} }
const std::vector<std::string>& GetLines() { return _lines; }
private:
std::vector<std::string> _lines;
}; };
LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
@@ -198,20 +101,7 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
{ {
EQEmuStackWalker sw; EQEmuStackWalker sw; sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
if (RuleB(Analytics, CrashReporting)) {
std::string crash_report;
auto& lines = sw.GetLines();
for (auto& line : lines) {
crash_report += line;
crash_report += "\n";
}
SendCrashReport(crash_report);
}
} }
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
@@ -235,27 +125,9 @@ void set_exception_handler() {
void print_trace() void print_trace()
{ {
bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU");
if (!does_gdb_exist) {
LogCrash(
"[Error] GDB is not installed, if you want crash dumps on Linux to work properly you will need GDB installed"
);
std::exit(1);
}
auto uid = geteuid(); auto uid = geteuid();
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
// check for passwordless sudo if not root std::string temp_output_file = "/tmp/dump-output";
if (uid != 0) {
bool sudo_password_required = Strings::Contains(Process::execute("sudo -n true"), "a password is required");
if (sudo_password_required) {
LogCrash(
"[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root."
);
std::exit(1);
}
}
char pid_buf[30]; char pid_buf[30];
sprintf(pid_buf, "%d", getpid()); sprintf(pid_buf, "%d", getpid());
@@ -264,6 +136,7 @@ void print_trace()
int child_pid = fork(); int child_pid = fork();
if (!child_pid) { if (!child_pid) {
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
dup2(fd, 1); // redirect output to stderr dup2(fd, 1); // redirect output to stderr
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf); fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
if (uid == 0) { if (uid == 0) {
@@ -278,22 +151,16 @@ void print_trace()
abort(); /* If gdb failed to start */ abort(); /* If gdb failed to start */
} }
else { else {
waitpid(child_pid, nullptr, 0); waitpid(child_pid, NULL, 0);
} }
std::ifstream input(temp_output_file); std::ifstream input(temp_output_file);
std::string crash_report;
for (std::string line; getline(input, line);) { for (std::string line; getline(input, line);) {
LogCrash("{}", line); LogCrash("{}", line);
crash_report += fmt::format("{}\n", line);
} }
std::remove(temp_output_file.c_str()); std::remove(temp_output_file.c_str());
if (RuleB(Analytics, CrashReporting)) {
SendCrashReport(crash_report);
}
exit(1); exit(1);
} }
+1 -1
View File
@@ -313,7 +313,7 @@ namespace cron
{ {
try try
{ {
return static_cast<cron_int>(Strings::ToUnsignedInt(text.data())); return static_cast<cron_int>(std::stoul(text.data()));
} }
catch (std::exception const & ex) catch (std::exception const & ex)
{ {
+455 -399
View File
File diff suppressed because it is too large Load Diff
+37 -29
View File
@@ -34,6 +34,8 @@
#include <vector> #include <vector>
#include <map> #include <map>
//atoi is not uint32 or uint32 safe!!!!
#define atoul(str) strtoul(str, nullptr, 10)
class MySQLRequestResult; class MySQLRequestResult;
class Client; class Client;
@@ -86,6 +88,7 @@ public:
/* Character Creation */ /* Character Creation */
bool AddToNameFilter(const char *name);
bool CreateCharacter( bool CreateCharacter(
uint32 account_id, uint32 account_id,
char *name, char *name,
@@ -106,27 +109,30 @@ public:
bool MoveCharacterToZone(uint32 character_id, uint32 zone_id); bool MoveCharacterToZone(uint32 character_id, uint32 zone_id);
bool ReserveName(uint32 account_id, char *name); bool ReserveName(uint32 account_id, char *name);
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp); 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 UpdateName(const char *oldname, const char *newname);
bool CopyCharacter( bool CopyCharacter(
const std::string& source_character_name, std::string source_character_name,
const std::string& destination_character_name, std::string destination_character_name,
const std::string& destination_account_name std::string destination_account_name
); );
/* General Information Queries */ /* General Information Queries */
bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table. bool AddBannedIP(char* bannedIP, const char* notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(std::string name); bool AddGMIP(char* ip_address, char* name);
bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table. bool CheckBannedIPs(const char* loginIP); //Check incoming connection against banned IP table.
bool CheckGMIPs(std::string login_ip, uint32 account_id); bool CheckGMIPs(const char* loginIP, uint32 account_id);
bool CheckNameFilter(std::string name, bool surname = false); bool CheckNameFilter(const char* name, bool surname = false);
bool CheckUsedName(std::string name); bool CheckUsedName(const char* name);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id); 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 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 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id); uint32 GetGroupIDByCharID(uint32 char_id);
uint32 GetRaidIDByCharID(uint32 char_id); uint32 GetRaidIDByCharID(uint32 char_id);
@@ -136,34 +142,35 @@ public:
std::string GetCharNameByID(uint32 char_id); std::string GetCharNameByID(uint32 char_id);
std::string GetNPCNameByID(uint32 npc_id); std::string GetNPCNameByID(uint32 npc_id);
std::string GetCleanNPCNameByID(uint32 npc_id); std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 account_id, std::string login_ip); void LoginIP(uint32 AccountID, const char* LoginIP);
/* Instancing */ /* Instancing */
bool AddClientToInstance(uint16 instance_id, uint32 character_id); bool AddClientToInstance(uint16 instance_id, uint32 char_id);
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id); bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id);
bool CheckInstanceExists(uint16 instance_id); bool CheckInstanceExists(uint16 instance_id);
bool CheckInstanceExpired(uint16 instance_id); bool CheckInstanceExpired(uint16 instance_id);
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
bool GetUnusedInstanceID(uint16 &instance_id); bool GetUnusedInstanceID(uint16 &instance_id);
bool IsGlobalInstance(uint16 instance_id); bool GlobalInstance(uint16 instance_id);
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id); bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
bool RemoveClientsFromInstance(uint16 instance_id); bool RemoveClientsFromInstance(uint16 instance_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id); bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id);
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version); uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id); uint16 GetInstanceVersion(uint16 instance_id);
uint8_t GetInstanceVersion(uint16 instance_id);
uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma);
uint32 GetInstanceZoneID(uint16 instance_id); uint32 VersionFromInstanceID(uint16 instance_id);
uint32 ZoneIDFromInstanceID(uint16 instance_id);
void AssignGroupToInstance(uint32 gid, uint32 instance_id); void AssignGroupToInstance(uint32 gid, uint32 instance_id);
void AssignRaidToInstance(uint32 rid, uint32 instance_id); void AssignRaidToInstance(uint32 rid, uint32 instance_id);
void BuryCorpsesInInstance(uint16 instance_id);
void DeleteInstance(uint16 instance_id); void DeleteInstance(uint16 instance_id);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id); void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id); void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids); void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list);
void PurgeExpiredInstances(); void PurgeExpiredInstances();
void SetInstanceDuration(uint16 instance_id, uint32 new_duration); void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
@@ -183,8 +190,6 @@ public:
int16 CheckStatus(uint32 account_id); 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 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 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); uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
@@ -201,7 +206,7 @@ public:
/* Groups */ /* Groups */
std::string GetGroupLeaderForLogin(std::string character_name); 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); 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); uint32 GetGroupID(const char* name);
@@ -235,16 +240,19 @@ public:
/* Database Variables */ /* Database Variables */
bool GetVariable(std::string varname, std::string &varvalue); bool GetVariable(std::string varname, std::string &varvalue);
bool SetVariable(const std::string& varname, const std::string &varvalue); bool SetVariable(const std::string varname, const std::string &varvalue);
bool LoadVariables(); bool LoadVariables();
/* General Queries */ /* General Queries */
bool GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, float* safe_heading = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr);
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); bool 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); bool LoadPTimers(uint32 charid, PTimerList &into);
uint8 GetPEQZone(uint32 zone_id, uint32 version); uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version);
uint8 GetMinStatus(uint32 zone_id, uint32 instance_version);
uint8 GetPEQZone(uint32 zoneID, uint32 version);
uint8 GetRaceSkill(uint8 skillid, uint8 in_race); uint8 GetRaceSkill(uint8 skillid, uint8 in_race);
uint8 GetServerType(); uint8 GetServerType();
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
@@ -263,7 +271,7 @@ public:
void ClearInvSnapshots(bool from_now = false); void ClearInvSnapshots(bool from_now = false);
void SourceDatabaseTableFromUrl(std::string table_name, std::string url); void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
void SourceSqlFromUrl(std::string url);
private: private:
+139 -183
View File
@@ -23,12 +23,10 @@
#include <iterator> #include <iterator>
#include "database_dump_service.h" #include "database_dump_service.h"
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../strings.h" #include "../string_util.h"
#include "../eqemu_config.h" #include "../eqemu_config.h"
#include "../database_schema.h" #include "../database_schema.h"
#include "../file.h" #include "../file_util.h"
#include "../process/process.h"
#include "../termcolor/rang.hpp"
#include <ctime> #include <ctime>
@@ -37,12 +35,43 @@
#else #else
#include <sys/time.h> #include <sys/time.h>
#include <thread>
#endif #endif
#define DATABASE_DUMP_PATH "backups/" #define DATABASE_DUMP_PATH "backups/"
/**
* @param cmd
* @param return_result
* @return
*/
std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true)
{
const char *file_name = "db-exec-result.txt";
if (return_result) {
#ifdef _WINDOWS
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#else
std::system((cmd + " > " + file_name).c_str());
#endif
}
else {
std::system((cmd).c_str());
}
std::string result;
if (return_result) {
std::ifstream file(file_name);
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
std::remove(file_name);
}
return result;
}
/** /**
* @return bool * @return bool
*/ */
@@ -59,7 +88,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
*/ */
bool DatabaseDumpService::IsTarAvailable() bool DatabaseDumpService::IsTarAvailable()
{ {
std::string version_output = Process::execute("tar --version"); std::string version_output = execute("tar --version");
return version_output.find("GNU tar") != std::string::npos; return version_output.find("GNU tar") != std::string::npos;
} }
@@ -70,7 +99,7 @@ bool DatabaseDumpService::IsTarAvailable()
*/ */
bool DatabaseDumpService::Is7ZipAvailable() bool DatabaseDumpService::Is7ZipAvailable()
{ {
std::string version_output = Process::execute("7z --help"); std::string version_output = execute("7z --help");
return version_output.find("7-Zip") != std::string::npos; return version_output.find("7-Zip") != std::string::npos;
} }
@@ -88,13 +117,11 @@ bool DatabaseDumpService::HasCompressionBinary()
*/ */
std::string DatabaseDumpService::GetMySQLVersion() std::string DatabaseDumpService::GetMySQLVersion()
{ {
std::string version_output = Process::execute("mysql --version"); std::string version_output = execute("mysql --version");
return Strings::Trim(version_output); return trim(version_output);
} }
const std::string CREDENTIALS_FILE = "login.my.cnf";
/** /**
* @return * @return
*/ */
@@ -103,66 +130,114 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
auto config = EQEmuConfig::get(); auto config = EQEmuConfig::get();
if (IsDumpContentTables() && !config->ContentDbHost.empty()) { if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
return fmt::format( return fmt::format(
"mysqldump --defaults-extra-file={} {}", "mysqldump -u {} -p{} -h {} --port={} {}",
CREDENTIALS_FILE, config->ContentDbUsername,
config->ContentDbPassword,
config->ContentDbHost,
config->ContentDbPort,
config->ContentDbName config->ContentDbName
); );
}; };
return fmt::format( return fmt::format(
"mysqldump --defaults-extra-file={} {}", "mysqldump -u {} -p{} -h {} --port={} {}",
CREDENTIALS_FILE, config->DatabaseUsername,
config->DatabasePassword,
config->DatabaseHost,
config->DatabasePort,
config->DatabaseDB config->DatabaseDB
); );
} }
/**
* @return
*/
std::string DatabaseDumpService::GetPlayerTablesList() std::string DatabaseDumpService::GetPlayerTablesList()
{ {
return Strings::Join(DatabaseSchema::GetPlayerTables(), " "); std::string tables_list;
} std::vector<std::string> tables = DatabaseSchema::GetPlayerTables();
for (const auto &table : tables) {
std::string DatabaseDumpService::GetBotTablesList() tables_list += table + " ";
{ }
return Strings::Join(DatabaseSchema::GetBotTables(), " ");
} return trim(tables_list);
std::string DatabaseDumpService::GetMercTablesList()
{
return Strings::Join(DatabaseSchema::GetMercTables(), " ");
} }
/**
* @return
*/
std::string DatabaseDumpService::GetLoginTableList() std::string DatabaseDumpService::GetLoginTableList()
{ {
return Strings::Join(DatabaseSchema::GetLoginTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetLoginTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
} }
/**
* @return
*/
std::string DatabaseDumpService::GetQueryServTables() std::string DatabaseDumpService::GetQueryServTables()
{ {
return Strings::Join(DatabaseSchema::GetQueryServerTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetQueryServerTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
} }
/**
* @return
*/
std::string DatabaseDumpService::GetSystemTablesList() std::string DatabaseDumpService::GetSystemTablesList()
{ {
auto system_tables = DatabaseSchema::GetServerTables(); std::string tables_list;
auto version_tables = DatabaseSchema::GetVersionTables();
system_tables.insert( std::vector<std::string> tables = DatabaseSchema::GetServerTables();
std::end(system_tables), for (const auto &table : tables) {
std::begin(version_tables), tables_list += table + " ";
std::end(version_tables) }
);
return Strings::Join(system_tables, " "); tables = DatabaseSchema::GetVersionTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
} }
/**
* @return
*/
std::string DatabaseDumpService::GetStateTablesList() std::string DatabaseDumpService::GetStateTablesList()
{ {
return Strings::Join(DatabaseSchema::GetStateTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetStateTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
} }
/**
* @return
*/
std::string DatabaseDumpService::GetContentTablesList() std::string DatabaseDumpService::GetContentTablesList()
{ {
return Strings::Join(DatabaseSchema::GetContentTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetContentTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
} }
/** /**
@@ -197,7 +272,7 @@ std::string DatabaseDumpService::GetDumpFileNameWithPath()
return GetSetDumpPath() + GetDumpFileName(); return GetSetDumpPath() + GetDumpFileName();
} }
void DatabaseDumpService::DatabaseDump() void DatabaseDumpService::Dump()
{ {
if (!IsMySQLInstalled()) { if (!IsMySQLInstalled()) {
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation"); LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
@@ -243,16 +318,6 @@ void DatabaseDumpService::DatabaseDump()
dump_descriptor += "-player"; dump_descriptor += "-player";
} }
if (IsDumpBotTables()) {
tables_to_dump += GetBotTablesList() + " ";
dump_descriptor += "-bots";
}
if (IsDumpMercTables()) {
tables_to_dump += GetMercTablesList() + " ";
dump_descriptor += "-mercs";
}
if (IsDumpSystemTables()) { if (IsDumpSystemTables()) {
tables_to_dump += GetSystemTablesList() + " "; tables_to_dump += GetSystemTablesList() + " ";
dump_descriptor += "-system"; dump_descriptor += "-system";
@@ -279,11 +344,6 @@ void DatabaseDumpService::DatabaseDump()
} }
} }
if (IsDumpStaticInstanceData()) {
tables_to_dump += "instance_list";
options += " --no-create-info --where=\"instance_list.is_global > 0 and instance_list.never_expires > 0\"";
}
if (!dump_descriptor.empty()) { if (!dump_descriptor.empty()) {
SetDumpFileName(GetDumpFileName() + dump_descriptor); SetDumpFileName(GetDumpFileName() + dump_descriptor);
} }
@@ -296,25 +356,7 @@ void DatabaseDumpService::DatabaseDump()
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath()); pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
} }
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { std::string execute_command = fmt::format(
File::Makedir(GetSetDumpPath());
}
if (IsDumpDropTableSyntaxOnly()) {
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' ');
for (auto &table: tables) {
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
}
if (tables_to_dump.empty()) {
std::cerr << "No tables were specified" << std::endl;
}
return;
}
else {
const auto execute_command = fmt::format(
"{} {} {} {}", "{} {} {} {}",
GetBaseMySQLDumpCommand(), GetBaseMySQLDumpCommand(),
options, options,
@@ -322,46 +364,40 @@ void DatabaseDumpService::DatabaseDump()
pipe_file pipe_file
); );
BuildCredentialsFile(); if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
std::string execution_result = Process::execute(execute_command); FileUtil::mkdir(GetSetDumpPath());
if (!execution_result.empty() && IsDumpOutputToConsole()) { }
if (IsDumpDropTableSyntaxOnly()) {
std::vector<std::string> tables = SplitString(tables_to_dump, ' ');
for (auto &table : tables) {
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
}
if (tables_to_dump.empty()) {
std::cerr << "No tables were specified" << std::endl;
}
}
else {
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
if (!execution_result.empty()) {
std::cout << execution_result; std::cout << execution_result;
} }
} }
if (!IsDumpOutputToConsole()) {
LogSys.LoadLogSettingsDefaults();
}
if (!pipe_file.empty()) {
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
auto r = File::GetContents(file);
if (!r.error.empty()) {
LogError("{}", r.error);
}
for (auto &line: Strings::Split(r.contents, "\n")) {
if (Strings::Contains(line, "mysqldump:")) {
LogError("{}", line);
LogError("Database dump failed. Correct the error before continuing or trying again");
LogError("This is to prevent data loss on behalf of the server operator");
RemoveSqlBackup();
std::exit(1);
}
}
}
if (!tables_to_dump.empty()) { if (!tables_to_dump.empty()) {
LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump)); LogInfo("Dumping Tables [{}]", tables_to_dump);
} }
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath()); LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
if (IsDumpWithCompression() && !IsDumpOutputToConsole()) { if (IsDumpWithCompression() && !IsDumpOutputToConsole()) {
if (HasCompressionBinary()) { if (HasCompressionBinary()) {
LogInfo("Compression requested. Compressing dump [{}.sql]", GetDumpFileNameWithPath()); LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
if (IsTarAvailable()) { if (IsTarAvailable()) {
Process::execute( execute(
fmt::format( fmt::format(
"tar -zcvf {}.tar.gz -C {} {}.sql", "tar -zcvf {}.tar.gz -C {} {}.sql",
GetDumpFileNameWithPath(), GetDumpFileNameWithPath(),
@@ -370,10 +406,9 @@ void DatabaseDumpService::DatabaseDump()
) )
); );
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath()); LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
RemoveSqlBackup();
} }
else if (Is7ZipAvailable()) { else if (Is7ZipAvailable()) {
Process::execute( execute(
fmt::format( fmt::format(
"7z a -t7z {}.zip {}.sql", "7z a -t7z {}.zip {}.sql",
GetDumpFileNameWithPath(), GetDumpFileNameWithPath(),
@@ -381,7 +416,6 @@ void DatabaseDumpService::DatabaseDump()
) )
); );
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath()); LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
RemoveSqlBackup();
} }
else { else {
LogInfo("Compression requested, but no available compression binary was found"); LogInfo("Compression requested, but no available compression binary was found");
@@ -392,8 +426,6 @@ void DatabaseDumpService::DatabaseDump()
} }
} }
RemoveCredentialsFile();
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole()); // LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
// LogDebug("[{}] dump-path", GetSetDumpPath()); // LogDebug("[{}] dump-path", GetSetDumpPath());
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false")); // LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
@@ -404,7 +436,6 @@ void DatabaseDumpService::DatabaseDump()
// LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false")); // LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false"));
// LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false")); // LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false"));
// LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false")); // LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false"));
// LogDebug("[{}] bot", (IsDumpBotTables() ? "true" : "false"));
} }
bool DatabaseDumpService::IsDumpSystemTables() const bool DatabaseDumpService::IsDumpSystemTables() const
@@ -546,78 +577,3 @@ void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables)
{ {
DatabaseDumpService::dump_state_tables = 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;
}
bool DatabaseDumpService::IsDumpMercTables() const
{
return dump_merc_tables;
}
void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables)
{
DatabaseDumpService::dump_merc_tables = dump_merc_tables;
}
void DatabaseDumpService::RemoveSqlBackup()
{
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
if (File::Exists(file)) {
std::filesystem::remove(file);
}
RemoveCredentialsFile();
}
void DatabaseDumpService::BuildCredentialsFile()
{
auto config = EQEmuConfig::get();
std::ofstream out(CREDENTIALS_FILE);
if (out.is_open()) {
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
out << "[mysqldump]" << std::endl;
out << "user=" << config->ContentDbUsername << std::endl;
out << "password=" << config->ContentDbPassword << std::endl;
out << "host=" << config->ContentDbHost << std::endl;
out << "port=" << config->ContentDbPort << std::endl;
out << "default-character-set=utf8" << std::endl;
}
else {
out << "[mysqldump]" << std::endl;
out << "user=" << config->DatabaseUsername << std::endl;
out << "password=" << config->DatabasePassword << std::endl;
out << "host=" << config->DatabaseHost << std::endl;
out << "port=" << config->DatabasePort << std::endl;
out << "default-character-set=utf8" << std::endl;
}
out.close();
}
else {
LogError("Failed to open credentials file for writing");
}
}
void DatabaseDumpService::RemoveCredentialsFile()
{
if (File::Exists(CREDENTIALS_FILE)) {
std::filesystem::remove(CREDENTIALS_FILE);
}
}
bool DatabaseDumpService::IsDumpStaticInstanceData()
{
return dump_static_instance_data;
}
void DatabaseDumpService::SetDumpStaticInstanceData(bool b)
{
dump_static_instance_data = b;
}
+2 -17
View File
@@ -24,7 +24,7 @@
class DatabaseDumpService { class DatabaseDumpService {
public: public:
void DatabaseDump(); void Dump();
bool IsDumpAllTables() const; bool IsDumpAllTables() const;
void SetDumpAllTables(bool dump_all_tables); void SetDumpAllTables(bool dump_all_tables);
bool IsDumpWithNoData() const; bool IsDumpWithNoData() const;
@@ -53,13 +53,6 @@ public:
void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only); void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only);
bool IsDumpStateTables() const; bool IsDumpStateTables() const;
void SetDumpStateTables(bool dump_state_tables); void SetDumpStateTables(bool dump_state_tables);
bool IsDumpBotTables() const;
void SetDumpBotTables(bool dump_bot_tables);
bool IsDumpMercTables() const;
void SetDumpMercTables(bool dump_bot_tables);
void SetDumpStaticInstanceData(bool b);
bool IsDumpStaticInstanceData();
private: private:
bool dump_all_tables = false; bool dump_all_tables = false;
@@ -74,19 +67,14 @@ private:
bool dump_with_compression = false; bool dump_with_compression = false;
bool dump_output_to_console = false; bool dump_output_to_console = false;
bool dump_drop_table_syntax_only = false; bool dump_drop_table_syntax_only = false;
bool dump_bot_tables = false;
bool dump_merc_tables = false;
bool dump_static_instance_data = false;
std::string dump_path; std::string dump_path;
std::string dump_file_name; std::string dump_file_name;
std::string execute(const std::string &cmd, bool return_result);
bool IsMySQLInstalled(); bool IsMySQLInstalled();
std::string GetMySQLVersion(); std::string GetMySQLVersion();
std::string GetBaseMySQLDumpCommand(); std::string GetBaseMySQLDumpCommand();
std::string GetPlayerTablesList(); std::string GetPlayerTablesList();
std::string GetBotTablesList();
std::string GetMercTablesList();
std::string GetSystemTablesList(); std::string GetSystemTablesList();
std::string GetStateTablesList(); std::string GetStateTablesList();
std::string GetContentTablesList(); std::string GetContentTablesList();
@@ -97,9 +85,6 @@ private:
std::string GetDumpFileNameWithPath(); std::string GetDumpFileNameWithPath();
std::string GetSetDumpPath(); std::string GetSetDumpPath();
std::string GetQueryServTables(); std::string GetQueryServTables();
void RemoveSqlBackup();
void BuildCredentialsFile();
void RemoveCredentialsFile();
}; };
-300
View File
@@ -1,300 +0,0 @@
#include <filesystem>
#include "database_update.h"
#include "../eqemu_logsys.h"
#include "../database.h"
#include "../strings.h"
#include "../rulesys.h"
#include "../http/httplib.h"
#include "database_update_manifest.cpp"
#include "database_update_manifest_bots.cpp"
#include "database_dump_service.h"
constexpr int BREAK_LENGTH = 70;
DatabaseVersion DatabaseUpdate::GetDatabaseVersions()
{
auto results = m_database->QueryDatabase("SELECT `version`, `bots_version` FROM `db_version` LIMIT 1");
if (!results.Success() || !results.RowCount()) {
LogError("Failed to read from [db_version] table!");
return DatabaseVersion{};
}
auto r = results.begin();
return DatabaseVersion{
.server_database_version = Strings::ToInt(r[0]),
.bots_database_version = Strings::ToInt(r[1]),
};
}
DatabaseVersion DatabaseUpdate::GetBinaryDatabaseVersions()
{
return DatabaseVersion{
.server_database_version = CURRENT_BINARY_DATABASE_VERSION,
.bots_database_version = (RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0),
};
}
// the amount of versions we look-back to ensure we have all migrations
// we may not want to force these, but just warn about the look-backs
constexpr int LOOK_BACK_AMOUNT = 10;
// this check will take action
void DatabaseUpdate::CheckDbUpdates()
{
InjectBotsVersionColumn();
auto v = GetDatabaseVersions();
auto b = GetBinaryDatabaseVersions();
if (CheckVersionsUpToDate(v, b)) {
return;
}
if (UpdateManifest(manifest_entries, v.server_database_version, b.server_database_version)) {
LogInfo(
"Updates ran successfully, setting database version to [{}] from [{}]",
b.server_database_version,
v.server_database_version
);
m_database->QueryDatabase(fmt::format("UPDATE `db_version` SET `version` = {}", b.server_database_version));
}
if (b.bots_database_version > 0) {
if (UpdateManifest(bot_manifest_entries, v.bots_database_version, b.bots_database_version)) {
LogInfo(
"Updates ran successfully, setting database version to [{}] from [{}]",
b.bots_database_version,
v.bots_database_version
);
m_database->QueryDatabase(
fmt::format(
"UPDATE `db_version` SET `bots_version` = {}",
b.bots_database_version
)
);
}
}
}
std::string DatabaseUpdate::GetQueryResult(std::string query)
{
auto results = m_database->QueryDatabase(query);
std::vector<std::string> result_lines = {};
for (auto row = results.begin(); row != results.end(); ++row) {
std::vector<std::string> cols;
int field_count = results.ColumnCount();
cols.reserve(field_count);
for (int i = 0; i < field_count; ++i) {
if (row[i] != nullptr) {
cols.emplace_back(row[i]);
}
}
result_lines.emplace_back(Strings::Join(cols, " "));
}
return Strings::Join(result_lines, "\n");
}
bool DatabaseUpdate::ShouldRunMigration(ManifestEntry &e, std::string query_result)
{
std::string r = Strings::Trim(query_result);
if (e.condition == "contains") {
return Strings::Contains(r, e.match);
}
else if (e.condition == "match") {
return r == e.match;
}
else if (e.condition == "missing") {
return !Strings::Contains(r, e.match);
}
else if (e.condition == "empty") {
return r.empty();
}
else if (e.condition == "not_empty") {
return !r.empty();
}
return false;
}
// return true if we ran updates
bool DatabaseUpdate::UpdateManifest(
std::vector<ManifestEntry> entries,
int version_low,
int version_high
)
{
std::vector<int> missing_migrations = {};
if (version_low != version_high) {
LogSys.DisableMySQLErrorLogs();
for (int version = version_low + 1; version <= version_high; ++version) {
for (auto &e: entries) {
if (e.version == version) {
bool has_migration = true;
std::string r = GetQueryResult(e.check);
if (ShouldRunMigration(e, r)) {
has_migration = false;
missing_migrations.emplace_back(e.version);
}
std::string prefix = fmt::format(
"[{}]",
has_migration ? "ok" : "missing"
);
LogInfo(
"[{}] {:>10} | [{}]",
e.version,
prefix,
e.description
);
}
}
}
LogSys.EnableMySQLErrorLogs();
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
if (!missing_migrations.empty()) {
LogInfo("Automatically backing up database before applying updates");
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
auto s = DatabaseDumpService();
s.SetDumpAllTables(true);
s.SetDumpWithCompression(true);
s.DatabaseDump();
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
}
if (!missing_migrations.empty()) {
LogInfo("Running database migrations. Please wait...");
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
}
for (auto &m: missing_migrations) {
for (auto &e: entries) {
if (e.version == m) {
bool errored_migration = false;
auto r = m_database->QueryDatabaseMulti(e.sql);
// ignore empty query result "errors"
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
LogError("(#{}) [{}]", r.ErrorNumber(), r.ErrorMessage());
errored_migration = true;
LogInfo("Required database update failed. This could be a problem");
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
// user input
std::string input;
bool gave_input = false;
time_t start_time = time(nullptr);
time_t wait_time_seconds = 60;
// spawn a concurrent thread that waits for input from std::cin
std::thread t1(
[&]() {
std::cin >> input;
gave_input = true;
}
);
t1.detach();
// check the inputReceived flag once every 50ms for 10 seconds
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
// prompt for user skip
if (Strings::Trim(input) == "y") {
errored_migration = false;
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
}
}
LogInfo(
"[{}] [{}] [{}]",
e.version,
e.description,
(errored_migration ? "error" : "ok")
);
if (errored_migration) {
LogError("Fatal | Database migration [{}] failed to run", e.description);
LogError("Fatal | Shutting down");
std::exit(1);
}
}
}
}
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
return true;
}
return false;
}
DatabaseUpdate *DatabaseUpdate::SetDatabase(Database *db)
{
m_database = db;
return this;
}
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
{
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
LogInfo(
"{:>8} | database [{}] binary [{}] {}",
"Server",
v.server_database_version,
b.server_database_version,
(v.server_database_version == b.server_database_version) ? "up to date" : "checking updates"
);
if (RuleB(Bots, Enabled) && b.bots_database_version > 0) {
LogInfo(
"{:>8} | database [{}] binary [{}] {}",
"Bots",
v.bots_database_version,
b.bots_database_version,
(v.bots_database_version == b.bots_database_version) ? "up to date" : "checking updates"
);
}
LogInfo("{:>8} | [server.auto_database_updates] [<green>true]", "Config");
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
// server database version is required
bool server_up_to_date = v.server_database_version == b.server_database_version;
// bots database version is optional, if not enabled then it is always up-to-date
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version == b.bots_database_version : true;
return server_up_to_date && bots_up_to_date;
}
// checks to see if there are pending updates
// used by zone to prevent launch or boot loop until updates are applied
bool DatabaseUpdate::HasPendingUpdates()
{
auto v = GetDatabaseVersions();
auto b = GetBinaryDatabaseVersions();
return !CheckVersionsUpToDate(v, b);
}
void DatabaseUpdate::InjectBotsVersionColumn()
{
auto r = m_database->QueryDatabase("show columns from db_version where Field like '%bots_version%'");
if (r.RowCount() == 0) {
m_database->QueryDatabase("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version");
}
}
-37
View File
@@ -1,37 +0,0 @@
#ifndef EQEMU_DATABASE_UPDATE_H
#define EQEMU_DATABASE_UPDATE_H
#include "../database.h"
struct ManifestEntry {
int version{}; // database version of the migration
std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
std::string check{}; // query that checks against the condition
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
std::string sql{}; // the SQL DDL that gets ran when the condition is true
};
struct DatabaseVersion {
int server_database_version;
int bots_database_version;
};
class DatabaseUpdate {
public:
DatabaseVersion GetDatabaseVersions();
DatabaseVersion GetBinaryDatabaseVersions();
void CheckDbUpdates();
std::string GetQueryResult(std::string query);
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
DatabaseUpdate *SetDatabase(Database *db);
bool HasPendingUpdates();
private:
Database *m_database;
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
void InjectBotsVersionColumn();
};
#endif //EQEMU_DATABASE_UPDATE_H
File diff suppressed because one or more lines are too long
@@ -1,107 +0,0 @@
#include "database_update.h"
std::vector<ManifestEntry> bot_manifest_entries = {
ManifestEntry{
.version = 9035,
.description = "2022_12_04_bot_archery.sql",
.check = "SHOW COLUMNS FROM `bot_data` LIKE 'archery_setting'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `bot_data`
ADD COLUMN `archery_setting` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `enforce_spell_settings`;
)",
},
ManifestEntry{
.version = 9036,
.description = "2023_01_19_drop_bot_views.sql",
.check = "SHOW TABLES LIKE 'vw_groups'",
.condition = "not_empty",
.match = "",
.sql = R"(
DROP VIEW vw_bot_groups;
DROP VIEW vw_bot_character_mobs;
DROP VIEW vw_groups;
DROP VIEW vw_guild_members;
DROP TABLE bot_guild_members;
)",
},
ManifestEntry{
.version = 9037,
.description = "2023_01_22_add_name_index.sql",
.check = "show index from bot_data WHERE key_name = 'name`",
.condition = "",
.match = "empty",
.sql = R"(
create index `name` on bot_data(`name`);
)",
},
ManifestEntry{
.version = 9038,
.description = "2023_02_16_add_caster_range.sql",
.check = "SHOW COLUMNS FROM `bot_data` LIKE 'caster_range'",
.condition = "",
.match = "empty",
.sql = R"(
ALTER TABLE `bot_data`
ADD COLUMN `caster_range` INT(11) UNSIGNED NOT NULL DEFAULT '300' AFTER `archery_setting`;
)",
},
ManifestEntry{
.version = 9039,
.description = "2023_03_31_remove_bot_groups.sql",
.check = "SHOW TABLES LIKE 'bot_groups'",
.condition = "",
.match = "not_empty",
.sql = R"(
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `bot_groups`;
DROP TABLE IF EXISTS `bot_group_members`;
SET FOREIGN_KEY_CHECKS = 1;
)",
},
ManifestEntry{
.version = 9040,
.description = "2023_11_16_bot_starting_items.sql",
.check = "SHOW TABLES LIKE 'bot_starting_items'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `bot_starting_items` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`races` int(11) UNSIGNED NOT NULL DEFAULT 0,
`classes` int(11) UNSIGNED NOT NULL DEFAULT 0,
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
`min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
`slot_id` mediumint(9) NOT NULL DEFAULT -1,
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
`content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci;
)"
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
// .version = 9228,
// .description = "some_new_migration.sql",
// .check = "SHOW COLUMNS FROM `table_name` LIKE 'column_name'",
// .condition = "empty",
// .match = "",
// .sql = R"(
//
//)"
};
// see struct definitions for what each field does
// struct ManifestEntry {
// int version{}; // database version of the migration
// std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
// std::string check{}; // query that checks against the condition
// std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
// std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
// std::string sql{}; // the SQL DDL that gets ran when the condition is true
// };
File diff suppressed because it is too large Load Diff
+360 -333
View File
@@ -18,19 +18,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/strings.h" #include "../common/string_util.h"
#include "../common/timer.h" #include "../common/timer.h"
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/dynamic_zone_members_repository.h" #include "../common/repositories/dynamic_zone_members_repository.h"
#include "../common/repositories/dynamic_zones_repository.h" #include "../common/repositories/dynamic_zones_repository.h"
#include "../common/repositories/group_id_repository.h"
#include "../common/repositories/instance_list_repository.h"
#include "../common/repositories/instance_list_player_repository.h"
#include "../common/repositories/raid_members_repository.h"
#include "../common/repositories/respawn_times_repository.h"
#include "../common/repositories/spawn_condition_values_repository.h"
#include "repositories/spawn2_disabled_repository.h"
#include "database.h" #include "database.h"
@@ -50,242 +41,251 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/time.h> #include <sys/time.h>
#endif #endif
/**
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id) * @param instance_id
* @param char_id
* @return
*/
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
{ {
auto e = InstanceListPlayerRepository::NewEntity(); std::string query = StringFormat(
"REPLACE INTO `instance_list_player` (id, charid) "
"VALUES "
"(%lu, %lu)",
(unsigned long) instance_id,
(unsigned long) char_id
);
e.id = instance_id; auto results = QueryDatabase(query);
e.charid = character_id;
return InstanceListPlayerRepository::ReplaceOne(*this, e); return results.Success();
} }
bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id) bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id)
{ {
if (!instance_id) {
return false;
}
auto l = InstanceListPlayerRepository::GetWhere( std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id);
*this, auto results = QueryDatabase(query);
fmt::format(
"id = {} AND charid = {}", if (!results.Success())
instance_id, return false;
character_id
) if (results.RowCount() != 1)
);
if (l.empty()) {
return false; return false;
}
return true; return true;
} }
bool Database::CheckInstanceExists(uint16 instance_id) bool Database::CheckInstanceExists(uint16 instance_id) {
{ std::string query = StringFormat(
if (!instance_id) { "SELECT "
return false; "`id` "
} "FROM "
"`instance_list` "
"WHERE "
"`id` = %u",
instance_id
);
auto results = QueryDatabase(query);
auto i = InstanceListRepository::FindOne(*this, instance_id); if (!results.Success())
if (!i.id) { return false;
if (results.RowCount() == 0)
return false; return false;
}
return true; return true;
} }
bool Database::CheckInstanceExpired(uint16 instance_id) bool Database::CheckInstanceExpired(uint16 instance_id)
{ {
if (!instance_id) {
int32 start_time = 0;
int32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat(
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
instance_id
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return true; return true;
} }
auto i = InstanceListRepository::FindOne(*this, instance_id); if (results.RowCount() == 0) {
if (!i.id) {
return true; return true;
} }
if (i.never_expires) { auto row = results.begin();
start_time = atoi(row[0]);
duration = atoi(row[1]);
never_expires = atoi(row[2]);
if (never_expires == 1) {
return false; return false;
} }
timeval tv{}; timeval tv{};
gettimeofday(&tv, nullptr); gettimeofday(&tv, nullptr);
return (i.start_time + i.duration) <= tv.tv_sec; return (start_time + duration) <= tv.tv_sec;
} }
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
{ {
auto e = InstanceListRepository::NewEntity(); std::string query = StringFormat(
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
instance_id,
zone_id,
version,
duration
);
e.id = instance_id; auto results = QueryDatabase(query);
e.zone = zone_id;
e.version = version;
e.start_time = std::time(nullptr);
e.duration = duration;
return InstanceListRepository::InsertOne(*this, e).id; return results.Success();
} }
bool Database::GetUnusedInstanceID(uint16 &instance_id) bool Database::GetUnusedInstanceID(uint16 &instance_id)
{ {
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances); uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max_instance_id = 32000; uint32 max = 32000;
// sanity check reserved std::string query = StringFormat(
if (max_reserved_instance_id >= max_instance_id) { "SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
instance_id = 0;
return false;
}
// recycle instances
if (RuleB(Instances, RecycleInstanceIds)) {
//query to get first unused id above reserved
auto query = fmt::format(
SQL(
SELECT id
FROM instance_list
WHERE id = {};
),
max_reserved_instance_id + 1
);
auto results = QueryDatabase(query);
// could not successfully query - bail out
if (!results.Success()) {
instance_id = 0;
return false;
}
// first id is available
if (results.RowCount() == 0) {
instance_id = max_reserved_instance_id + 1;
return true;
}
// now look for next available above reserved
query = fmt::format(
SQL(
SELECT MIN(i.id + 1) AS next_available
FROM instance_list i
LEFT JOIN instance_list i2 ON i.id + 1 = i2.id
WHERE i.id >= {}
AND i2.id IS NULL;
),
max_reserved_instance_id
);
results = QueryDatabase(query);
// could not successfully query - bail out
if (!results.Success()) {
instance_id = 0;
return false;
}
// did not retrieve any rows - bail out
if (results.RowCount() == 0) {
instance_id = 0;
return false;
}
auto row = results.begin();
// check that id is within limits
if (row[0] && Strings::ToInt(row[0]) <= max_instance_id) {
instance_id = Strings::ToInt(row[0]);
return true;
}
// no available instance ids
instance_id = 0;
return false;
}
// get max unused id above reserved
auto query = fmt::format(
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}",
max_reserved_instance_id, max_reserved_instance_id,
max_reserved_instance_id max_reserved_instance_id
); );
if (RuleB(Instances, RecycleInstanceIds)) {
query = (
SQL(
SELECT i.id + 1 AS next_available
FROM instance_list i
LEFT JOIN instance_list i2 ON i2.id = i.id + 1
WHERE i2.id IS NULL
ORDER BY i.id
LIMIT 0, 1;
)
);
}
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
// could not successfully query - bail out
if (!results.Success()) { if (!results.Success()) {
instance_id = 0; instance_id = 0;
return false; return false;
} }
// did not retrieve any rows - bail out if (results.RowCount() == 0) {
instance_id = max_reserved_instance_id;
return true;
}
auto row = results.begin();
if (atoi(row[0]) <= max) {
instance_id = atoi(row[0]);
return true;
}
if (instance_id < max_reserved_instance_id) {
instance_id = max_reserved_instance_id;
return true;
}
query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id);
results = QueryDatabase(query);
if (!results.Success()) {
instance_id = 0;
return false;
}
if (results.RowCount() == 0) { if (results.RowCount() == 0) {
instance_id = 0; instance_id = 0;
return false; return false;
} }
auto row = results.begin(); max_reserved_instance_id++;
for (auto row = results.begin(); row != results.end(); ++row) {
// no instances currently used if (max_reserved_instance_id < atoi(row[0])) {
if (!row[0]) { instance_id = max_reserved_instance_id;
instance_id = max_reserved_instance_id + 1;
return true; return true;
} }
// check that id is within limits if (max_reserved_instance_id > max) {
if (Strings::ToInt(row[0]) <= max_instance_id) {
instance_id = Strings::ToInt(row[0]);
return true;
}
// no available instance ids
instance_id = 0; instance_id = 0;
return false; return false;
}
max_reserved_instance_id++;
}
instance_id = max_reserved_instance_id;
return true;
} }
bool Database::IsGlobalInstance(uint16 instance_id) bool Database::GlobalInstance(uint16 instance_id)
{ {
if (!instance_id) { std::string query = StringFormat(
return false; "SELECT "
} "is_global "
"FROM "
"instance_list "
"WHERE "
"id = %u "
"LIMIT 1 ",
instance_id
);
auto results = QueryDatabase(query);
auto i = InstanceListRepository::FindOne(*this, instance_id); if (!results.Success())
if (!i.id) {
return false; return false;
}
return i.is_global; if (results.RowCount() == 0)
return false;
auto row = results.begin();
return (atoi(row[0]) == 1) ? true : false;
} }
bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id)
{ {
return InstanceListPlayerRepository::DeleteWhere( std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu",
*this, (unsigned long)instance_id, (unsigned long)char_id);
fmt::format( auto results = QueryDatabase(query);
"id = {} AND charid = {}",
instance_id, return results.Success();
char_id
)
);
} }
bool Database::RemoveClientsFromInstance(uint16 instance_id) bool Database::RemoveClientsFromInstance(uint16 instance_id)
{ {
return InstanceListPlayerRepository::DeleteOne(*this, instance_id); std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id);
auto results = QueryDatabase(query);
return results.Success();
} }
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id) bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id)
{ {
//we are not saved to this instance so set our instance to 0 //we are not saved to this instance so set our instance to 0
if (!IsGlobalInstance(instance_id) && !CheckInstanceByCharID(instance_id, character_id)) { if (!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id))
return false; return false;
}
if (CheckInstanceExpired(instance_id)) { if (CheckInstanceExpired(instance_id))
{
DeleteInstance(instance_id); DeleteInstance(instance_id);
return false; return false;
} }
@@ -295,102 +295,99 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id)
bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id)
{ {
auto l = InstanceListRepository::GetWhere(
*this, std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u", instance_id, zone_id);
fmt::format( auto results = QueryDatabase(query);
"id = {} AND zone = {}",
instance_id, if (!results.Success())
zone_id return false;
)
); if (results.RowCount() == 0)
if (l.empty()) {
return false; return false;
}
return true; return true;
} }
uint16 Database::GetInstanceID(uint32 zone_id, uint32 character_id, int16 version) uint16 Database::GetInstanceID(uint32 zone, uint32 character_id, int16 version)
{ {
if (!zone_id) { if (!zone)
return 0; return 0;
}
const auto query = fmt::format( std::string query = StringFormat(
"SELECT instance_list.id FROM " "SELECT "
"instance_list, instance_list_player WHERE " "instance_list.id "
"instance_list.zone = {} AND " "FROM "
"instance_list.version = {} AND " "instance_list, "
"instance_list.id = instance_list_player.id AND " "instance_list_player "
"instance_list_player.charid = {} " "WHERE "
"LIMIT 1;", "instance_list.zone = %u "
zone_id, "AND instance_list.version = %u "
"AND instance_list.id = instance_list_player.id "
"AND instance_list_player.charid = %u "
"LIMIT 1; ",
zone,
version, version,
character_id character_id
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) { if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint16 Database::GetInstanceVersion(uint16 instance_id) {
if (instance_id == 0)
return 0;
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
{
uint32 start_time = 0;
uint32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
{
is_perma = false;
return 0;
}
if (results.RowCount() == 0)
{
is_perma = false;
return 0; return 0;
} }
auto row = results.begin(); auto row = results.begin();
return static_cast<uint16>(Strings::ToUnsignedInt(row[0])); start_time = atoi(row[0]);
} duration = atoi(row[1]);
never_expires = atoi(row[2]);
std::vector<uint16> Database::GetInstanceIDs(uint32 zone_id, uint32 character_id) if (never_expires == 1)
{ {
std::vector<uint16> l;
if (!zone_id) {
return l;
}
const auto query = fmt::format(
"SELECT instance_list.id FROM "
"instance_list, instance_list_player WHERE "
"instance_list.zone = {} AND "
"instance_list.id = instance_list_player.id AND "
"instance_list_player.charid = {}",
zone_id,
character_id
);
auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
return l;
}
for (auto row : results) {
l.push_back(static_cast<uint16>(Strings::ToUnsignedInt(row[0])));
}
return l;
}
uint8_t Database::GetInstanceVersion(uint16 instance_id) {
if (!instance_id) {
return 0;
}
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return 0;
}
return i.version;
}
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
{
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
is_perma = false;
return 0;
}
if (i.never_expires) {
is_perma = true; is_perma = true;
return 0; return 0;
} }
@@ -399,174 +396,204 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
timeval tv; timeval tv;
gettimeofday(&tv, nullptr); gettimeofday(&tv, nullptr);
return ((i.start_time + i.duration) - tv.tv_sec); return ((start_time + duration) - tv.tv_sec);
} }
uint32 Database::GetInstanceZoneID(uint16 instance_id) uint32 Database::VersionFromInstanceID(uint16 instance_id)
{ {
if (!instance_id) {
return 0;
}
auto i = InstanceListRepository::FindOne(*this, instance_id); std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
if (!i.id) { auto results = QueryDatabase(query);
return 0;
}
return i.zone; if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint32 Database::ZoneIDFromInstanceID(uint16 instance_id)
{
std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
} }
void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id) void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
{ {
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = GroupIdRepository::GetWhere( uint32 zone_id = ZoneIDFromInstanceID(instance_id);
*this, uint16 version = VersionFromInstanceID(instance_id);
fmt::format(
"groupid = {}", std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id);
group_id auto results = QueryDatabase(query);
)
); if (!results.Success())
if (l.empty()) {
return; return;
}
for (const auto& e : l) { for (auto row = results.begin(); row != results.end(); ++row)
if (!GetInstanceID(zone_id, e.charid, version)) { {
AddClientToInstance(instance_id, e.charid); uint32 charid = atoi(row[0]);
} if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
} }
} }
void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id) void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
{ {
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = RaidMembersRepository::GetWhere( uint32 zone_id = ZoneIDFromInstanceID(instance_id);
*this, uint16 version = VersionFromInstanceID(instance_id);
std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id);
auto results = QueryDatabase(query);
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
{
uint32 charid = atoi(row[0]);
if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
}
}
void Database::BuryCorpsesInInstance(uint16 instance_id) {
QueryDatabase(
fmt::format( fmt::format(
"raidid = {}", "UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id = {}",
raid_id instance_id
) )
); );
if (l.empty()) {
return;
}
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
}
}
} }
void Database::DeleteInstance(uint16 instance_id) void Database::DeleteInstance(uint16 instance_id)
{ {
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id)); std::string query;
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id);
QueryDatabase(query);
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id);
QueryDatabase(query);
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
QueryDatabase(query);
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id); DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
CharacterCorpsesRepository::BuryInstance(*this, instance_id); BuryCorpsesInInstance(instance_id);
} }
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id) void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid)
{ {
auto instance_id = GetInstanceID(zone_id, character_id, version); uint16 id = GetInstanceID(zone, charid, version);
if (instance_id) { if (id != 0)
return; return;
}
char ln[128]; char ln[128];
memset(ln, 0, 128); memset(ln, 0, 128);
GetGroupLeadershipInfo(group_id, ln); GetGroupLeadershipInfo(gid, ln);
uint32 l_charid = GetCharacterID((const char*)ln);
uint16 l_id = GetInstanceID(zone, l_charid, version);
auto group_leader_id = GetCharacterID((const char*)ln); if (l_id == 0)
auto group_leader_instance_id = GetInstanceID(zone_id, group_leader_id, version);
if (!group_leader_instance_id) {
return; return;
}
AddClientToInstance(group_leader_instance_id, character_id); AddClientToInstance(l_id, charid);
} }
void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id) void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid)
{ {
uint16 instance_id = GetInstanceID(zone_id, character_id, version); uint16 id = GetInstanceID(zone, charid, version);
if (instance_id) { if (id != 0)
return; return;
}
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id)); uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid));
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version); uint16 l_id = GetInstanceID(zone, l_charid, version);
if (!raid_leader_instance_id) { if (l_id == 0)
return; return;
}
AddClientToInstance(raid_leader_instance_id, character_id); AddClientToInstance(l_id, charid);
} }
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids) void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list) {
{
auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id));
if (l.empty()) {
return;
}
for (const auto& e : l) { std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id);
character_ids.push_back(e.charid); auto results = QueryDatabase(query);
}
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
charid_list.push_back(atoi(row[0]));
} }
void Database::PurgeExpiredInstances() void Database::PurgeExpiredInstances()
{ {
/** /**
* Delay purging by a day so that we can continue using adjacent free instance id's * Delay purging by a day so that we can continue using adjacent free instance id's
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but * from the table without risking the chance we immediately re-allocate a zone that freshly expired but
* has not been fully de-allocated * has not been fully de-allocated
*/ */
auto l = InstanceListRepository::GetWhere( std::string query =
*this, SQL(
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0" SELECT
id
FROM
instance_list
where
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
and never_expires = 0
); );
if (l.empty()) {
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
if (results.RowCount() == 0) {
return; return;
} }
std::vector<std::string> instance_ids; std::vector<std::string> instance_ids;
for (const auto& e : l) { for (auto row = results.begin(); row != results.end(); ++row) {
instance_ids.emplace_back(std::to_string(e.id)); instance_ids.emplace_back(row[0]);
} }
const auto imploded_instance_ids = Strings::Implode(",", instance_ids); std::string imploded_instance_ids = implode(",", instance_ids);
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM instance_list WHERE id IN ({})", imploded_instance_ids));
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM instance_list_player WHERE id IN ({})", imploded_instance_ids));
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
CharacterCorpsesRepository::BuryInstances(*this, 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); DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
} }
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
{ {
auto i = InstanceListRepository::FindOne(*this, instance_id); std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), "
if (!i.id) { "duration=%u WHERE id=%u", new_duration, instance_id);
return; auto results = QueryDatabase(query);
}
i.start_time = std::time(nullptr);
i.duration = new_duration;
InstanceListRepository::UpdateOne(*this, i);
} }
+7 -67
View File
@@ -62,14 +62,12 @@ namespace DatabaseSchema {
{"character_pet_buffs", "char_id"}, {"character_pet_buffs", "char_id"},
{"character_pet_info", "char_id"}, {"character_pet_info", "char_id"},
{"character_pet_inventory", "char_id"}, {"character_pet_inventory", "char_id"},
{"character_peqzone_flags", "id"},
{"character_potionbelt", "id"}, {"character_potionbelt", "id"},
{"character_skills", "id"}, {"character_skills", "id"},
{"character_spells", "id"}, {"character_spells", "id"},
{"character_stats_record", "character_id"},
{"character_task_timers", "character_id"}, {"character_task_timers", "character_id"},
{"character_tasks", "charid"}, {"character_tasks", "charid"},
{"character_tribute", "character_id"}, {"character_tribute", "id"},
{"completed_tasks", "charid"}, {"completed_tasks", "charid"},
{"data_buckets", "id"}, {"data_buckets", "id"},
{"faction_values", "char_id"}, {"faction_values", "char_id"},
@@ -84,6 +82,7 @@ namespace DatabaseSchema {
{"player_titlesets", "char_id"}, {"player_titlesets", "char_id"},
{"quest_globals", "charid"}, {"quest_globals", "charid"},
{"timers", "char_id"}, {"timers", "char_id"},
{"titles", "char_id"},
{"trader", "char_id"}, {"trader", "char_id"},
{"zone_flags", "charID"} {"zone_flags", "charID"}
}; };
@@ -131,11 +130,9 @@ namespace DatabaseSchema {
"character_pet_buffs", "character_pet_buffs",
"character_pet_info", "character_pet_info",
"character_pet_inventory", "character_pet_inventory",
"character_peqzone_flags",
"character_potionbelt", "character_potionbelt",
"character_skills", "character_skills",
"character_spells", "character_spells",
"character_stats_record",
"character_task_timers", "character_task_timers",
"character_tasks", "character_tasks",
"character_tribute", "character_tribute",
@@ -161,6 +158,7 @@ namespace DatabaseSchema {
"spell_buckets", "spell_buckets",
"spell_globals", "spell_globals",
"timers", "timers",
"titles",
"trader", "trader",
"trader_audit", "trader_audit",
"zone_flags" "zone_flags"
@@ -191,14 +189,13 @@ namespace DatabaseSchema {
"char_create_point_allocations", "char_create_point_allocations",
"damageshieldtypes", "damageshieldtypes",
"doors", "doors",
"dynamic_zone_templates",
"faction_association",
"faction_base_data", "faction_base_data",
"faction_list", "faction_list",
"faction_list_mod", "faction_list_mod",
"fishing", "fishing",
"forage", "forage",
"global_loot", "global_loot",
"goallists",
"graveyard", "graveyard",
"grid", "grid",
"grid_entries", "grid_entries",
@@ -227,6 +224,7 @@ namespace DatabaseSchema {
"pets_beastlord_data", "pets_beastlord_data",
"pets_equipmentset", "pets_equipmentset",
"pets_equipmentset_entries", "pets_equipmentset_entries",
"proximities",
"skill_caps", "skill_caps",
"spawn2", "spawn2",
"spawn_conditions", "spawn_conditions",
@@ -258,9 +256,7 @@ namespace DatabaseSchema {
{ {
return { return {
"chatchannels", "chatchannels",
"chatchannel_reserved_names",
"command_settings", "command_settings",
"command_subsettings",
"content_flags", "content_flags",
"db_str", "db_str",
"eqtime", "eqtime",
@@ -274,7 +270,6 @@ namespace DatabaseSchema {
"perl_event_export_settings", "perl_event_export_settings",
"profanity_list", "profanity_list",
"rule_sets", "rule_sets",
"titles",
"rule_values", "rule_values",
"variables", "variables",
}; };
@@ -322,21 +317,20 @@ namespace DatabaseSchema {
"completed_shared_task_activity_state", "completed_shared_task_activity_state",
"completed_shared_task_members", "completed_shared_task_members",
"completed_shared_tasks", "completed_shared_tasks",
"discord_webhooks",
"dynamic_zone_members", "dynamic_zone_members",
"dynamic_zones", "dynamic_zones",
"eventlog",
"expedition_lockouts", "expedition_lockouts",
"expeditions", "expeditions",
"gm_ips", "gm_ips",
"group_id", "group_id",
"group_leaders", "group_leaders",
"hackers",
"instance_list", "instance_list",
"ip_exemptions", "ip_exemptions",
"item_tick", "item_tick",
"lfguild", "lfguild",
"merc_buffs",
"merchantlist_temp", "merchantlist_temp",
"mercs",
"object_contents", "object_contents",
"raid_details", "raid_details",
"raid_leaders", "raid_leaders",
@@ -345,9 +339,6 @@ namespace DatabaseSchema {
"respawn_times", "respawn_times",
"saylink", "saylink",
"server_scheduled_events", "server_scheduled_events",
"spawn2_disabled",
"player_event_log_settings",
"player_event_logs",
"shared_task_activity_state", "shared_task_activity_state",
"shared_task_dynamic_zones", "shared_task_dynamic_zones",
"shared_task_members", "shared_task_members",
@@ -384,57 +375,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_heal_rotation_members",
"bot_heal_rotation_targets",
"bot_heal_rotations",
"bot_inspect_messages",
"bot_inventories",
"bot_owner_options",
"bot_pet_buffs",
"bot_pet_inventories",
"bot_pets",
"bot_spell_casting_chances",
"bot_spell_settings",
"bot_spells_entries",
"bot_stances",
"bot_timers"
};
}
static std::vector<std::string> GetMercTables()
{
return {
"merc_armorinfo",
"merc_inventory",
"merc_merchant_entries",
"merc_merchant_template_entries",
"merc_merchant_templates",
"merc_name_types",
"merc_npc_types",
"merc_spell_list_entries",
"merc_spell_lists",
"merc_stance_entries",
"merc_stats",
"merc_subtypes",
"merc_templates",
"merc_types",
"merc_weaponinfo"
};
}
} }
#endif //EQEMU_DATABASE_SCHEMA_H #endif //EQEMU_DATABASE_SCHEMA_H
+45 -183
View File
@@ -13,7 +13,6 @@
#include <iostream> #include <iostream>
#include <mysqld_error.h> #include <mysqld_error.h>
#include <string.h> #include <string.h>
#include "strings.h"
#ifdef _WINDOWS #ifdef _WINDOWS
#define snprintf _snprintf #define snprintf _snprintf
@@ -35,8 +34,7 @@
DBcore::DBcore() DBcore::DBcore()
{ {
mysql = mysql_init(nullptr); mysql_init(&mysql);
mysqlOwner = true;
pHost = nullptr; pHost = nullptr;
pUser = nullptr; pUser = nullptr;
pPassword = nullptr; pPassword = nullptr;
@@ -44,7 +42,6 @@ DBcore::DBcore()
pCompress = false; pCompress = false;
pSSL = false; pSSL = false;
pStatus = Closed; pStatus = Closed;
m_mutex = new Mutex;
} }
DBcore::~DBcore() DBcore::~DBcore()
@@ -54,10 +51,16 @@ DBcore::~DBcore()
* are re-using the default database connection pointer when we dont have an * are re-using the default database connection pointer when we dont have an
* external configuration setup ex: (content_database) * external configuration setup ex: (content_database)
*/ */
if (mysqlOwner) { std::string mysql_connection_host;
mysql_close(mysql); if (mysql.host) {
mysql_connection_host = mysql.host;
} }
if (GetOriginHost() != mysql_connection_host) {
return;
}
mysql_close(&mysql);
safe_delete_array(pHost); safe_delete_array(pHost);
safe_delete_array(pUser); safe_delete_array(pUser);
safe_delete_array(pPassword); safe_delete_array(pPassword);
@@ -67,21 +70,20 @@ DBcore::~DBcore()
// Sends the MySQL server a keepalive // Sends the MySQL server a keepalive
void DBcore::ping() void DBcore::ping()
{ {
if (!m_mutex->trylock()) { if (!MDatabase.trylock()) {
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive // well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
return; return;
} }
mysql_ping(mysql); mysql_ping(&mysql);
m_mutex->unlock(); MDatabase.unlock();
} }
MySQLRequestResult DBcore::QueryDatabase(const std::string& query, bool retryOnFailureOnce) MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce)
{ {
auto r = QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce); return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
return r;
} }
bool DBcore::DoesTableExist(const std::string& table_name) bool DBcore::DoesTableExist(std::string table_name)
{ {
auto results = QueryDatabase(fmt::format("SHOW TABLES LIKE '{}'", table_name)); auto results = QueryDatabase(fmt::format("SHOW TABLES LIKE '{}'", table_name));
@@ -93,16 +95,18 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
BenchTimer timer; BenchTimer timer;
timer.reset(); timer.reset();
LockMutex lock(m_mutex); LockMutex lock(&MDatabase);
// Reconnect if we are not connected before hand. // Reconnect if we are not connected before hand.
if (pStatus != Connected) { if (pStatus != Connected) {
Open(); Open();
} }
// request query. != 0 indicates some kind of error. // request query. != 0 indicates some kind of error.
if (mysql_real_query(mysql, query, querylen) != 0) { if (mysql_real_query(&mysql, query, querylen) != 0) {
unsigned int errorNumber = mysql_errno(mysql); unsigned int errorNumber = mysql_errno(&mysql);
if (errorNumber == CR_SERVER_GONE_ERROR) { if (errorNumber == CR_SERVER_GONE_ERROR) {
pStatus = Error; pStatus = Error;
@@ -126,26 +130,26 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE]; auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql)); snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(mysql), errorBuffer); return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(&mysql), errorBuffer);
} }
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE]; auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql)); snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
/** /**
* Error logging * Error logging
*/ */
if (mysql_errno(mysql) > 0 && query[0] != '\0') { if (mysql_errno(&mysql) > 0 && strlen(query) > 0) {
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(mysql), mysql_error(mysql), query); LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(&mysql), mysql_error(&mysql), query);
} }
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(mysql), errorBuffer); return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer);
} }
// successful query. get results. // successful query. get results.
MYSQL_RES *res = mysql_store_result(mysql); MYSQL_RES *res = mysql_store_result(&mysql);
uint32 rowCount = 0; uint32 rowCount = 0;
if (res != nullptr) { if (res != nullptr) {
@@ -154,16 +158,16 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
MySQLRequestResult requestResult( MySQLRequestResult requestResult(
res, res,
(uint32) mysql_affected_rows(mysql), (uint32) mysql_affected_rows(&mysql),
rowCount, rowCount,
(uint32) mysql_field_count(mysql), (uint32) mysql_field_count(&mysql),
(uint32) mysql_insert_id(mysql) (uint32) mysql_insert_id(&mysql)
); );
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) { if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
if ((strncasecmp(query, "select", 6) == 0)) { if ((strncasecmp(query, "select", 6) == 0)) {
LogMySQLQuery( LogMySQLQuery(
"{0} -- ({1} row{2} returned) ({3}s)", "{0} ({1} row{2} returned) ({3}s)",
query, query,
requestResult.RowCount(), requestResult.RowCount(),
requestResult.RowCount() == 1 ? "" : "s", requestResult.RowCount() == 1 ? "" : "s",
@@ -172,7 +176,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
} }
else { else {
LogMySQLQuery( LogMySQLQuery(
"{0} -- ({1} row{2} affected) ({3}s)", "{0} ({1} row{2} affected) ({3}s)",
query, query,
requestResult.RowsAffected(), requestResult.RowsAffected(),
requestResult.RowsAffected() == 1 ? "" : "s", requestResult.RowsAffected() == 1 ? "" : "s",
@@ -203,7 +207,7 @@ uint32 DBcore::DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen)
{ {
// No good reason to lock the DB, we only need it in the first place to check char encoding. // No good reason to lock the DB, we only need it in the first place to check char encoding.
// LockMutex lock(&MDatabase); // LockMutex lock(&MDatabase);
return mysql_real_escape_string(mysql, tobuf, frombuf, fromlen); return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen);
} }
bool DBcore::Open( bool DBcore::Open(
@@ -218,7 +222,7 @@ bool DBcore::Open(
bool iSSL bool iSSL
) )
{ {
LockMutex lock(m_mutex); LockMutex lock(&MDatabase);
safe_delete_array(pHost); safe_delete_array(pHost);
safe_delete_array(pUser); safe_delete_array(pUser);
safe_delete_array(pPassword); safe_delete_array(pPassword);
@@ -238,13 +242,13 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
if (errbuf) { if (errbuf) {
errbuf[0] = 0; errbuf[0] = 0;
} }
LockMutex lock(m_mutex); LockMutex lock(&MDatabase);
if (GetStatus() == Connected) { if (GetStatus() == Connected) {
return true; return true;
} }
if (GetStatus() == Error) { if (GetStatus() == Error) {
mysql_close(mysql); mysql_close(&mysql);
mysql_init(mysql); // Initialize structure again mysql_init(&mysql); // Initialize structure again
} }
if (!pHost) { if (!pHost) {
return false; return false;
@@ -261,7 +265,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
if (pSSL) { if (pSSL) {
flags |= CLIENT_SSL; flags |= CLIENT_SSL;
} }
if (mysql_real_connect(mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
pStatus = Connected; pStatus = Connected;
std::string connected_origin_host = pHost; std::string connected_origin_host = pHost;
@@ -271,16 +275,21 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
} }
else { else {
if (errnum) { if (errnum) {
*errnum = mysql_errno(mysql); *errnum = mysql_errno(&mysql);
} }
if (errbuf) { if (errbuf) {
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql)); snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
} }
pStatus = Error; pStatus = Error;
return false; return false;
} }
} }
void DBcore::SetMysql(MYSQL *mysql)
{
DBcore::mysql = *mysql;
}
const std::string &DBcore::GetOriginHost() const const std::string &DBcore::GetOriginHost() const
{ {
return origin_host; return origin_host;
@@ -290,150 +299,3 @@ void DBcore::SetOriginHost(const std::string &origin_host)
{ {
DBcore::origin_host = origin_host; DBcore::origin_host = origin_host;
} }
std::string DBcore::Escape(const std::string& s)
{
const std::size_t s_len = s.length();
std::vector<char> temp((s_len * 2) + 1, '\0');
mysql_real_escape_string(mysql, temp.data(), s.c_str(), s_len);
return temp.data();
}
void DBcore::SetMutex(Mutex *mutex)
{
safe_delete(m_mutex);
DBcore::m_mutex = mutex;
}
// executes multiple statements in one query
// do not use this in application logic
// this was built and maintained for database migrations only
MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
{
SetMultiStatementsOn();
BenchTimer timer;
timer.reset();
LockMutex lock(m_mutex);
// Reconnect if we are not connected before hand.
if (pStatus != Connected) {
Open();
}
auto r = MySQLRequestResult{};
int status = mysql_real_query(mysql, query.c_str(), query.length());
// process single result
if (status != 0) {
unsigned int error_number = mysql_errno(mysql);
if (error_number == CR_SERVER_GONE_ERROR) {
pStatus = Error;
}
// error logging
if (mysql_errno(mysql) > 0 && query.length() > 0 && mysql_errno(mysql) != 1065) {
std::string error_raw = fmt::format("{}", mysql_error(mysql));
std::string mysql_err = Strings::Trim(error_raw);
std::string clean_query = Strings::Replace(query, "\n", "");
LogMySQLError("[{}] ({}) query [{}]", mysql_err, mysql_errno(mysql), clean_query);
MYSQL_RES *res = mysql_store_result(mysql);
uint32 row_count = 0;
if (res) {
row_count = (uint32) mysql_num_rows(res);
}
r = MySQLRequestResult(
res,
(uint32) mysql_affected_rows(mysql),
row_count,
(uint32) mysql_field_count(mysql),
(uint32) mysql_insert_id(mysql)
);
std::string error_message = mysql_error(mysql);
r.SetErrorMessage(error_message);
r.SetErrorNumber(mysql_errno(mysql));
if (res) {
mysql_free_result(res);
}
SetMultiStatementsOff();
return r;
}
}
int index = 0;
// there could be a query with a semicolon in the actual data, this is best effort for
// logging / display purposes
// rare that we see this when this is only used in DDL statements
auto pieces = Strings::Split(query, ";");
// process each statement result
do {
uint32 row_count = 0;
MYSQL_RES *res = mysql_store_result(mysql);
r = MySQLRequestResult(
res,
(uint32) mysql_affected_rows(mysql),
row_count,
(uint32) mysql_field_count(mysql),
(uint32) mysql_insert_id(mysql)
);
if (pieces.size() >= index) {
auto piece = pieces[index];
LogMySQLQuery(
"{} -- ({} row{} affected) ({}s)",
piece,
r.RowsAffected(),
r.RowsAffected() == 1 ? "" : "s",
std::to_string(timer.elapsed())
);
}
if (res) {
row_count = (uint32) mysql_num_rows(res);
}
// more results? -1 = no, >0 = error, 0 = yes (keep looping)
if ((status = mysql_next_result(mysql)) > 0) {
if (mysql_errno(mysql) > 0) {
LogMySQLError("[{}] [{}]", mysql_errno(mysql), mysql_error(mysql));
}
mysql_free_result(res);
// error logging
std::string error_message = mysql_error(mysql);
r.SetErrorMessage(error_message);
r.SetErrorNumber(mysql_errno(mysql));
SetMultiStatementsOff();
// we handle errors elsewhere
return r;
}
if (res) {
mysql_free_result(res);
}
index++;
} while (status == 0);
SetMultiStatementsOff();
return r;
}
+7 -30
View File
@@ -12,7 +12,6 @@
#include <mysql.h> #include <mysql.h>
#include <string.h> #include <string.h>
#include <mutex>
class DBcore { class DBcore {
public: public:
@@ -24,26 +23,19 @@ public:
~DBcore(); ~DBcore();
eStatus GetStatus() { return pStatus; } eStatus GetStatus() { return pStatus; }
MySQLRequestResult QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce = true); MySQLRequestResult QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce = true);
MySQLRequestResult QueryDatabase(const std::string& query, bool retryOnFailureOnce = true); MySQLRequestResult QueryDatabase(std::string query, bool retryOnFailureOnce = true);
MySQLRequestResult QueryDatabaseMulti(const std::string &query);
void TransactionBegin(); void TransactionBegin();
void TransactionCommit(); void TransactionCommit();
void TransactionRollback(); void TransactionRollback();
std::string Escape(const std::string& s);
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen); uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
void ping(); void ping();
MYSQL *getMySQL() { return &mysql; }
void SetMysql(MYSQL *mysql);
const std::string &GetOriginHost() const; const std::string &GetOriginHost() const;
void SetOriginHost(const std::string &origin_host); void SetOriginHost(const std::string &origin_host);
bool DoesTableExist(const std::string& table_name); bool DoesTableExist(std::string table_name);
void SetMySQL(const DBcore &o)
{
mysql = o.mysql;
mysqlOwner = false;
}
void SetMutex(Mutex *mutex);
protected: protected:
bool Open( bool Open(
@@ -61,13 +53,10 @@ protected:
private: private:
bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr); bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr);
MYSQL* mysql; MYSQL mysql;
bool mysqlOwner; Mutex MDatabase;
Mutex *m_mutex;
eStatus pStatus; eStatus pStatus;
std::mutex m_query_lock{};
std::string origin_host; std::string origin_host;
char *pHost; char *pHost;
@@ -78,20 +67,8 @@ private:
uint32 pPort; uint32 pPort;
bool pSSL; bool pSSL;
// allows multiple queries to be executed within the same query
// do not use this under normal operation
// we use this during database migrations only currently
void SetMultiStatementsOn()
{
mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON);
}
// disables multiple statements to be executed in one query
void SetMultiStatementsOff()
{
mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF);
}
}; };
#endif #endif
+84 -34
View File
@@ -19,7 +19,8 @@
#include "deity.h" #include "deity.h"
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
EQ::deity::DeityTypeBit EQ::deity::ConvertDeityTypeToDeityTypeBit(DeityType deity_type)
{ {
switch (deity_type) { switch (deity_type) {
case DeityBertoxxulous: case DeityBertoxxulous:
@@ -59,41 +60,90 @@ EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
return bit_DeityAgnostic; return bit_DeityAgnostic;
default: default:
return bit_DeityAll; return bit_DeityAll;
}
}
const std::map<EQ::deity::DeityType, std::string>& EQ::deity::GetDeityMap()
{
static const std::map<EQ::deity::DeityType, std::string> deity_map = {
{ DeityAgnostic, "Agnostic" },
{ DeityAgnostic_LB, "Agnostic" },
{ DeityBertoxxulous, "Bertoxxulous" },
{ DeityBrellSirilis, "Brell Serilis" },
{ DeityBristlebane, "Bristlebane" },
{ DeityCazicThule, "Cazic-Thule" },
{ DeityErollisiMarr, "Erollisi Marr" },
{ DeityInnoruuk, "Innoruuk" },
{ DeityKarana, "Karana" },
{ DeityMithanielMarr, "Mithaniel Marr" },
{ DeityPrexus, "Prexus" },
{ DeityQuellious, "Quellious" },
{ DeityRallosZek, "Rallos Zek" },
{ DeityRodcetNife, "Rodcet Nife" },
{ DeitySolusekRo, "Solusek Ro" },
{ DeityTheTribunal, "The Tribunal" },
{ DeityTunare, "Tunare" },
{ DeityVeeshan, "Veeshan" }
}; };
return deity_map;
} }
std::string EQ::deity::GetDeityName(DeityType deity_type) EQ::deity::DeityType EQ::deity::ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit)
{ {
switch (deity_type_bit) {
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) { case bit_DeityAgnostic:
return EQ::deity::GetDeityMap().find(deity_type)->second; return DeityAgnostic;
} case bit_DeityBertoxxulous:
return DeityBertoxxulous;
return std::string(); case bit_DeityBrellSirilis:
return DeityBrellSirilis;
case bit_DeityCazicThule:
return DeityCazicThule;
case bit_DeityErollisiMarr:
return DeityErollisiMarr;
case bit_DeityBristlebane:
return DeityBristlebane;
case bit_DeityInnoruuk:
return DeityInnoruuk;
case bit_DeityKarana:
return DeityKarana;
case bit_DeityMithanielMarr:
return DeityMithanielMarr;
case bit_DeityPrexus:
return DeityPrexus;
case bit_DeityQuellious:
return DeityQuellious;
case bit_DeityRallosZek:
return DeityRallosZek;
case bit_DeityRodcetNife:
return DeityRodcetNife;
case bit_DeitySolusekRo:
return DeitySolusekRo;
case bit_DeityTheTribunal:
return DeityTheTribunal;
case bit_DeityTunare:
return DeityTunare;
case bit_DeityVeeshan:
return DeityVeeshan;
default:
return DeityUnknown;
};
}
const char* EQ::deity::DeityName(DeityType deity_type)
{
switch (deity_type) {
case DeityBertoxxulous:
return "Bertoxxulous";
case DeityBrellSirilis:
return "Brell Serilis";
case DeityCazicThule:
return "Cazic-Thule";
case DeityErollisiMarr:
return "Erollisi Marr";
case DeityBristlebane:
return "Bristlebane";
case DeityInnoruuk:
return "Innoruuk";
case DeityKarana:
return "Karana";
case DeityMithanielMarr:
return "Mithaniel Marr";
case DeityPrexus:
return "Prexus";
case DeityQuellious:
return "Quellious";
case DeityRallosZek:
return "Rallos Zek";
case DeityRodcetNife:
return "Rodcet Nife";
case DeitySolusekRo:
return "Solusek Ro";
case DeityTheTribunal:
return "The Tribunal";
case DeityTunare:
return "Tunare";
case DeityVeeshan:
return "Veeshan";
case DeityAgnostic_LB:
case DeityAgnostic:
return "Agnostic";
default:
return "Unknown";
};
} }
+5 -6
View File
@@ -21,8 +21,6 @@
#define COMMON_DEITY_H #define COMMON_DEITY_H
#include "types.h" #include "types.h"
#include <map>
#include <string>
namespace EQ namespace EQ
@@ -51,6 +49,7 @@ namespace EQ
}; };
enum DeityTypeBit : uint32 { enum DeityTypeBit : uint32 {
bit_DeityNone = 0x00000000,
bit_DeityAgnostic = 0x00000001, bit_DeityAgnostic = 0x00000001,
bit_DeityBertoxxulous = 0x00000002, bit_DeityBertoxxulous = 0x00000002,
bit_DeityBrellSirilis = 0x00000004, bit_DeityBrellSirilis = 0x00000004,
@@ -68,12 +67,12 @@ namespace EQ
bit_DeityTheTribunal = 0x00004000, bit_DeityTheTribunal = 0x00004000,
bit_DeityTunare = 0x00008000, bit_DeityTunare = 0x00008000,
bit_DeityVeeshan = 0x00010000, bit_DeityVeeshan = 0x00010000,
bit_DeityAll = UINT32_MAX bit_DeityAll = 0xFFFFFFFF
}; };
extern DeityTypeBit GetDeityBitmask(DeityType deity_type); extern DeityTypeBit ConvertDeityTypeToDeityTypeBit(DeityType deity_type);
extern std::string GetDeityName(DeityType deity_type); extern DeityType ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit);
extern const std::map<DeityType, std::string>& GetDeityMap(); extern const char* DeityName(DeityType deity_type);
} /*deity*/ } /*deity*/
-165
View File
@@ -1,165 +0,0 @@
#include <cereal/archives/json.hpp>
#include <cereal/archives/binary.hpp>
#include "discord.h"
#include "../http/httplib.h"
#include "../json/json.h"
#include "../strings.h"
#include "../eqemu_logsys.h"
#include "../events/player_event_logs.h"
constexpr int MAX_RETRIES = 10;
void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url)
{
if (!ValidateWebhookUrl(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);
cli.set_connection_timeout(0, 15000000); // 15 sec
cli.set_read_timeout(15, 0); // 15 seconds
cli.set_write_timeout(15, 0); // 15 seconds
// 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, 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 = Strings::ToInt(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++;
}
}
}
void Discord::SendPlayerEventMessage(
const PlayerEvent::PlayerEventContainer &e,
const std::string &webhook_url
)
{
if (!ValidateWebhookUrl(webhook_url)) {
return;
}
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);
cli.set_connection_timeout(0, 15000000); // 15 sec
cli.set_read_timeout(15, 0); // 15 seconds
cli.set_write_timeout(15, 0); // 15 seconds
std::string payload = PlayerEventLogs::GetDiscordPayloadFromEvent(e);
if (payload.empty()) {
return;
}
bool retry = true;
int retries = 0;
int retry_timer = 1000;
while (retry) {
if (auto res = cli.Post(endpoint, payload, "application/json")) {
if (res->status != 200 && res->status != 204) {
LogError("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 = Strings::ToInt(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 player event 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";
}
bool Discord::ValidateWebhookUrl(const std::string &webhook_url)
{
// validate
if (webhook_url.empty()) {
LogDiscord("[webhook_url] is empty");
return false;
}
// validate
if (!Strings::Contains(webhook_url, "http://") && !Strings::Contains(webhook_url, "https://")) {
LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url);
return false;
}
return true;
}
-20
View File
@@ -1,20 +0,0 @@
#ifndef EQEMU_DISCORD_H
#define EQEMU_DISCORD_H
#include <string>
#include "../types.h"
#include "../http/httplib.h"
#include "../repositories/player_event_logs_repository.h"
#include "../events/player_events.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);
static void SendPlayerEventMessage(const PlayerEvent::PlayerEventContainer& e, const std::string &webhook_url);
static bool ValidateWebhookUrl(const std::string &webhook_url);
};
#endif //EQEMU_DISCORD_H
-75
View File
@@ -1,75 +0,0 @@
#include "discord_manager.h"
#include "../../common/discord/discord.h"
#include "../events/player_event_logs.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.clear();
}
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.clear();
}
}
// final flush
if (!message.empty()) {
Discord::SendWebhookMessage(
message,
webhook.webhook_url
);
}
}
webhook_message_queue.clear();
webhook_queue_lock.unlock();
}
void DiscordManager::QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e)
{
auto w = player_event_logs.GetDiscordWebhookUrlFromEventType(e.player_event_log.event_type_id);
if (!w.empty()) {
Discord::SendPlayerEventMessage(e, w);
}
}
-22
View File
@@ -1,22 +0,0 @@
#ifndef EQEMU_DISCORD_MANAGER_H
#define EQEMU_DISCORD_MANAGER_H
#include <mutex>
#include <map>
#include <vector>
#include "../../common/types.h"
#include "../repositories/player_event_logs_repository.h"
#include "../events/player_events.h"
class DiscordManager {
public:
void QueueWebhookMessage(uint32 webhook_id, const std::string& message);
void ProcessMessageQueue();
void QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e);
private:
std::mutex webhook_queue_lock{};
std::map<uint32, std::vector<std::string>> webhook_message_queue{};
};
#endif
+1 -51
View File
@@ -79,7 +79,6 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
m_max_players = dz_entry.max_players; m_max_players = dz_entry.max_players;
m_instance_id = dz_entry.instance_id; m_instance_id = dz_entry.instance_id;
m_type = static_cast<DynamicZoneType>(dz_entry.type); 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.zone_id = dz_entry.compass_zone_id;
m_compass.x = dz_entry.compass_x; m_compass.x = dz_entry.compass_x;
m_compass.y = dz_entry.compass_y; m_compass.y = dz_entry.compass_y;
@@ -130,7 +129,6 @@ uint32_t DynamicZoneBase::SaveToDatabase()
insert_dz.max_players = m_max_players; insert_dz.max_players = m_max_players;
insert_dz.instance_id = m_instance_id, insert_dz.instance_id = m_instance_id,
insert_dz.type = static_cast<int>(m_type); 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_zone_id = m_compass.zone_id;
insert_dz.compass_x = m_compass.x; insert_dz.compass_x = m_compass.x;
insert_dz.compass_y = m_compass.y; insert_dz.compass_y = m_compass.y;
@@ -318,17 +316,6 @@ void DynamicZoneBase::SetZoneInLocation(float x, float y, float z, float heading
SetZoneInLocation({ 0, x, y, z, heading }, 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) void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update_db)
{ {
m_leader = new_leader; m_leader = new_leader;
@@ -416,17 +403,6 @@ std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzLocationPacket(
return pack; 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( std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberStatusPacket(
uint32_t character_id, DynamicZoneMemberStatus status) uint32_t character_id, DynamicZoneMemberStatus status)
{ {
@@ -585,9 +561,8 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
return "Mission"; return "Mission";
case DynamicZoneType::Quest: case DynamicZoneType::Quest:
return "Quest"; return "Quest";
default:
return "Unknown";
} }
return "Unknown";
} }
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket() EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
@@ -622,28 +597,3 @@ void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_
cereal::BinaryInputArchive archive(ss); cereal::BinaryInputArchive archive(ss);
archive(*this); 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;
}
-9
View File
@@ -5,7 +5,6 @@
#include "net/packet.h" #include "net/packet.h"
#include "repositories/dynamic_zones_repository.h" #include "repositories/dynamic_zones_repository.h"
#include "repositories/dynamic_zone_members_repository.h" #include "repositories/dynamic_zone_members_repository.h"
#include "repositories/dynamic_zone_templates_repository.h"
#include <algorithm> #include <algorithm>
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
@@ -75,7 +74,6 @@ public:
virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0; 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); } uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint32_t GetID() const { return m_id; } uint32_t GetID() const { return m_id; }
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); } uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); }
@@ -87,7 +85,6 @@ public:
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_zone_id); } 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 GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); }
uint32_t GetZoneVersion() const { return m_zone_version; } uint32_t GetZoneVersion() const { return m_zone_version; }
int GetSwitchID() const { return m_dz_switch_id; }
DynamicZoneType GetType() const { return m_type; } DynamicZoneType GetType() const { return m_type; }
const std::string& GetLeaderName() const { return m_leader.name; } const std::string& GetLeaderName() const { return m_leader.name; }
const std::string& GetName() const { return m_name; } const std::string& GetName() const { return m_name; }
@@ -115,7 +112,6 @@ public:
bool IsValid() const { return m_instance_id != 0; } 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; } 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 LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
void RemoveAllMembers(); void RemoveAllMembers();
bool RemoveMember(uint32_t character_id); bool RemoveMember(uint32_t character_id);
bool RemoveMember(const std::string& character_name); bool RemoveMember(const std::string& character_name);
@@ -131,7 +127,6 @@ public:
void SetName(const std::string& name) { m_name = name; } void SetName(const std::string& name) { m_name = name; }
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false); 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 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 SetType(DynamicZoneType type) { m_type = type; }
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); } void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false); void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
@@ -146,7 +141,6 @@ protected:
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed); virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status); virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status);
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); } virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); }
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
virtual bool SendServerPacket(ServerPacket* packet) = 0; virtual bool SendServerPacket(ServerPacket* packet) = 0;
void AddInternalMember(const DynamicZoneMember& member); void AddInternalMember(const DynamicZoneMember& member);
@@ -159,7 +153,6 @@ protected:
std::unique_ptr<ServerPacket> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id); 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> 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> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed);
std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status); 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> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
@@ -171,7 +164,6 @@ protected:
uint32_t m_zone_version = 0; uint32_t m_zone_version = 0;
uint32_t m_min_players = 0; uint32_t m_min_players = 0;
uint32_t m_max_players = 0; uint32_t m_max_players = 0;
int m_dz_switch_id = 0;
bool m_never_expires = false; bool m_never_expires = false;
bool m_has_zonein = false; bool m_has_zonein = false;
bool m_has_member_statuses = false; bool m_has_member_statuses = false;
@@ -198,7 +190,6 @@ public:
m_zone_version, m_zone_version,
m_min_players, m_min_players,
m_max_players, m_max_players,
m_dz_switch_id,
m_never_expires, m_never_expires,
m_has_zonein, m_has_zonein,
m_has_member_statuses, m_has_member_statuses,
+5 -388
View File
@@ -18,12 +18,8 @@
*/ */
#include "emu_constants.h" #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 "languages.h"
#include "rulesys.h"
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) { int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
static const int16 local_array[] = { static const int16 local_array[] = {
@@ -152,9 +148,8 @@ const char *EQ::constants::GetStanceName(StanceType stance_type) {
} }
int EQ::constants::ConvertStanceTypeToIndex(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 (stance_type - EQ::constants::stancePassive);
}
return 0; return 0;
} }
@@ -191,392 +186,14 @@ const std::map<int, std::string>& EQ::constants::GetLanguageMap()
{ LANG_HADAL, "Hadal" }, { LANG_HADAL, "Hadal" },
{ LANG_UNKNOWN, "Unknown" } { LANG_UNKNOWN, "Unknown" }
}; };
return language_map; return language_map;
} }
std::string EQ::constants::GetLanguageName(int language_id) std::string EQ::constants::GetLanguageName(int language_id)
{ {
if (!EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) { if (language_id >= LANG_COMMON_TONGUE && language_id <= LANG_UNKNOWN) {
return std::string(); auto languages = EQ::constants::GetLanguageMap();
return languages[language_id];
} }
return EQ::constants::GetLanguageMap().find(language_id)->second;
}
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 std::string();
}
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
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 std::string();
}
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
}
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(); 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::ValueWithin(faction_consider_level, ConsiderLevel::Ally, ConsiderLevel::Scowls)) {
return std::string();;
}
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
}
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 std::string();
}
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
}
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 std::string();
}
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
}
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 std::string();
}
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
}
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 std::string();
}
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
}
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 std::string();
}
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
}
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 std::string();
}
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
}
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 std::string();
}
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
}
+11 -292
View File
@@ -22,7 +22,6 @@
#include "eq_limits.h" #include "eq_limits.h"
#include "emu_versions.h" #include "emu_versions.h"
#include "bodytypes.h"
#include <string.h> #include <string.h>
@@ -33,6 +32,10 @@ namespace EQ
using RoF2::IINVALID; using RoF2::IINVALID;
using RoF2::INULL; using RoF2::INULL;
namespace inventory {
} /*inventory*/
namespace invtype { namespace invtype {
using namespace RoF2::invtype::enum_; using namespace RoF2::invtype::enum_;
@@ -217,186 +220,12 @@ namespace EQ
stanceBurnAE 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); const char *GetStanceName(StanceType stance_type);
int ConvertStanceTypeToIndex(StanceType stance_type); int ConvertStanceTypeToIndex(StanceType stance_type);
extern const std::map<int, std::string>& GetLanguageMap(); extern const std::map<int, std::string>& GetLanguageMap();
std::string GetLanguageName(int language_id); 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_FIRST = stancePassive;
const int STANCE_TYPE_LAST = stanceBurnAE; const int STANCE_TYPE_LAST = stanceBurnAE;
const int STANCE_TYPE_COUNT = stanceBurnAE; const int STANCE_TYPE_COUNT = stanceBurnAE;
@@ -499,123 +328,13 @@ namespace EQ
Guild Guild
}; };
}; // namespace consent }; // namespace consent
} /*EQEmu*/ } /*EQEmu*/
enum ServerLockType : int {
List,
Lock,
Unlock
};
enum AccountStatus : uint8 {
Player = 0,
Steward = 10,
ApprenticeGuide = 20,
Guide = 50,
QuestTroupe = 80,
SeniorGuide = 81,
GMTester = 85,
EQSupport = 90,
GMStaff = 95,
GMAdmin = 100,
GMLeadAdmin = 150,
QuestMaster = 160,
GMAreas = 170,
GMCoder = 180,
GMMgmt = 200,
GMImpossible = 250,
Max = 255
};
enum Invisibility : uint8 {
Visible,
Invisible,
Special = 255
};
enum AugmentActions : int {
Insert,
Remove,
Swap,
Destroy
};
enum ConsiderLevel : uint8 {
Ally = 1,
Warmly,
Kindly,
Amiably,
Indifferently,
Apprehensively,
Dubiously,
Threateningly,
Scowls
};
enum TargetDescriptionType : uint8 {
LCSelf,
UCSelf,
LCYou,
UCYou,
LCYour,
UCYour
};
enum ReloadWorld : uint8 {
NoRepop = 0,
Repop,
ForceRepop
};
enum BucketComparison : uint8 {
BucketEqualTo = 0,
BucketNotEqualTo,
BucketGreaterThanOrEqualTo,
BucketLesserThanOrEqualTo,
BucketGreaterThan,
BucketLesserThan,
BucketIsAny,
BucketIsNotAny,
BucketIsBetween,
BucketIsNotBetween
};
enum class EntityFilterType {
All,
Bots,
Clients,
NPCs
};
enum class ApplySpellType {
Solo,
Group,
Raid
};
namespace HeroicBonusBucket
{
const std::string WisMaxMana = "HWIS-MaxMana";
const std::string WisManaRegen = "HWIS-ManaRegen";
const std::string WisHealAmt = "HWIS-HealAmt";
const std::string IntMaxMana = "HINT-MaxMana";
const std::string IntManaRegen = "HINT-ManaRegen";
const std::string IntSpellDmg = "HINT-SpellDmg";
const std::string StrMeleeDamage = "HSTR-MeleeDamage";
const std::string StrShieldAC = "HSTR-ShieldAC";
const std::string StrMaxEndurance = "HSTR-MaxEndurance";
const std::string StrEnduranceRegen = "HSTR-EnduranceRegen";
const std::string StaMaxHP = "HSTA-MaxHP";
const std::string StaHPRegen = "HSTA-HPRegen";
const std::string StaMaxEndurance = "HSTA-MaxEndurance";
const std::string StaEnduranceRegen = "HSTA-EnduranceRegen";
const std::string AgiAvoidance = "HAGI-Avoidance";
const std::string AgiMaxEndurance = "HAGI-MaxEndurance";
const std::string AgiEnduranceRegen = "HAGI-EnduranceRegen";
const std::string DexRangedDamage = "HDEX-RangedDamage";
const std::string DexMaxEndurance = "HDEX-MaxEndurance";
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
}
#endif /*COMMON_EMU_CONSTANTS_H*/ #endif /*COMMON_EMU_CONSTANTS_H*/
/* hack list to prevent circular references
eq_limits.h:EQ::inventory::LookupEntry::InventoryTypeSize[n];
*/
+3 -11
View File
@@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest),
N(OP_AltCurrencyPurchase), N(OP_AltCurrencyPurchase),
N(OP_AltCurrencyReclaim), N(OP_AltCurrencyReclaim),
N(OP_AltCurrencySell), N(OP_AltCurrencySell),
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069 N(OP_AltCurrencySellSelection),
N(OP_Animation), N(OP_Animation),
N(OP_AnnoyingZoneUnknown), N(OP_AnnoyingZoneUnknown),
N(OP_ApplyPoison), N(OP_ApplyPoison),
@@ -62,7 +62,6 @@ N(OP_BeginCast),
N(OP_Bind_Wound), N(OP_Bind_Wound),
N(OP_BlockedBuffs), N(OP_BlockedBuffs),
N(OP_BoardBoat), N(OP_BoardBoat),
N(OP_BookButton),
N(OP_Buff), N(OP_Buff),
N(OP_BuffCreate), N(OP_BuffCreate),
N(OP_BuffRemoveRequest), N(OP_BuffRemoveRequest),
@@ -72,7 +71,6 @@ N(OP_Camp),
N(OP_CancelSneakHide), N(OP_CancelSneakHide),
N(OP_CancelTask), N(OP_CancelTask),
N(OP_CancelTrade), N(OP_CancelTrade),
N(OP_CashReward),
N(OP_CastSpell), N(OP_CastSpell),
N(OP_ChangeSize), N(OP_ChangeSize),
N(OP_ChannelMessage), N(OP_ChannelMessage),
@@ -131,8 +129,8 @@ N(OP_DisciplineTimer),
N(OP_DisciplineUpdate), N(OP_DisciplineUpdate),
N(OP_DiscordMerchantInventory), N(OP_DiscordMerchantInventory),
N(OP_DoGroupLeadershipAbility), N(OP_DoGroupLeadershipAbility),
N(OP_DuelDecline), N(OP_DuelResponse),
N(OP_DuelAccept), N(OP_DuelResponse2),
N(OP_DumpName), N(OP_DumpName),
N(OP_Dye), N(OP_Dye),
N(OP_DynamicWall), N(OP_DynamicWall),
@@ -305,7 +303,6 @@ N(OP_LockoutTimerInfo),
N(OP_Login), N(OP_Login),
N(OP_LoginAccepted), N(OP_LoginAccepted),
N(OP_LoginComplete), 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_LoginUnknown1),
N(OP_LoginUnknown2), N(OP_LoginUnknown2),
N(OP_Logout), N(OP_Logout),
@@ -317,7 +314,6 @@ N(OP_LootRequest),
N(OP_ManaChange), N(OP_ManaChange),
N(OP_ManaUpdate), N(OP_ManaUpdate),
N(OP_MarkNPC), N(OP_MarkNPC),
N(OP_MarkRaidNPC),
N(OP_Marquee), N(OP_Marquee),
N(OP_MemorizeSpell), N(OP_MemorizeSpell),
N(OP_Mend), N(OP_Mend),
@@ -400,8 +396,6 @@ N(OP_PVPLeaderBoardRequest),
N(OP_PVPStats), N(OP_PVPStats),
N(OP_QueryResponseThing), N(OP_QueryResponseThing),
N(OP_QueryUCSServerStatus), N(OP_QueryUCSServerStatus),
N(OP_RaidDelegateAbility),
N(OP_RaidClearNPCMarks),
N(OP_RaidInvite), N(OP_RaidInvite),
N(OP_RaidJoin), N(OP_RaidJoin),
N(OP_RaidUpdate), N(OP_RaidUpdate),
@@ -461,7 +455,6 @@ N(OP_ServerListResponse),
N(OP_SessionReady), N(OP_SessionReady),
N(OP_SetChatServer), N(OP_SetChatServer),
N(OP_SetChatServer2), N(OP_SetChatServer2),
N(OP_SetFace),
N(OP_SetGroupTarget), N(OP_SetGroupTarget),
N(OP_SetGuildMOTD), N(OP_SetGuildMOTD),
N(OP_SetGuildRank), N(OP_SetGuildRank),
@@ -565,7 +558,6 @@ N(OP_WhoAllRequest),
N(OP_WhoAllResponse), N(OP_WhoAllResponse),
N(OP_World_Client_CRC1), N(OP_World_Client_CRC1),
N(OP_World_Client_CRC2), N(OP_World_Client_CRC2),
N(OP_World_Client_CRC3),
N(OP_WorldClientReady), N(OP_WorldClientReady),
N(OP_WorldComplete), N(OP_WorldComplete),
N(OP_WorldLogout), N(OP_WorldLogout),
+9 -59
View File
@@ -79,8 +79,6 @@
#define ANIM_DEATH 0x73 #define ANIM_DEATH 0x73
#define ANIM_LOOT 0x69 #define ANIM_LOOT 0x69
constexpr int16 RECAST_TYPE_UNLINKED_ITEM = -1;
typedef enum { typedef enum {
eaStanding = 0, eaStanding = 0,
eaSitting, //1 eaSitting, //1
@@ -686,6 +684,14 @@ namespace Zones {
constexpr uint16 APPRENTICE = 999; // Designer Apprentice constexpr uint16 APPRENTICE = 999; // Designer Apprentice
} }
//ZoneChange_Struct->success values
#define ZONE_ERROR_NOMSG 0
#define ZONE_ERROR_NOTREADY -1
#define ZONE_ERROR_VALIDPC -2
#define ZONE_ERROR_STORYZONE -3
#define ZONE_ERROR_NOEXPANSION -6
#define ZONE_ERROR_NOEXPERIENCE -7
typedef enum { typedef enum {
FilterNone = 0, FilterNone = 0,
@@ -712,7 +718,7 @@ typedef enum {
FilterPetMisses = 21, //0=show, 1=hide FilterPetMisses = 21, //0=show, 1=hide
FilterFocusEffects = 22, //0=show, 1=hide FilterFocusEffects = 22, //0=show, 1=hide
FilterPetSpells = 23, //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, FilterUnknown25 = 25,
FilterUnknown26 = 26, FilterUnknown26 = 26,
FilterUnknown27 = 27, FilterUnknown27 = 27,
@@ -1003,60 +1009,4 @@ enum StartZoneIndex {
SharVahl SharVahl
}; };
enum FVNoDropFlagRule
{
Disabled = 0,
Enabled = 1,
AdminOnly = 2
};
enum Anonymity : uint8
{
NotAnonymous,
Anonymous,
Roleplaying
};
enum ZoningMessage : int8 {
ZoneNoMessage = 0,
ZoneSuccess = 1,
ZoneNotReady = -1,
ZoneValidPC = -2,
ZoneStoryZone = -3,
ZoneNoExpansion = -6,
ZoneNoExperience = -7
};
enum class RecipeCountType : uint8
{
Component,
Container,
Fail,
Salvage,
Success
};
#define ALT_CURRENCY_ID_RADIANT 4
#define ALT_CURRENCY_ID_EBON 5
enum ResurrectionActions
{
Decline,
Accept
};
enum ScribeSpellActions
{
Scribe,
Memorize,
Unmemorize
};
enum SpellTimeRestrictions
{
NoRestriction,
Day,
Night
};
#endif /*COMMON_EQ_CONSTANTS_H*/ #endif /*COMMON_EQ_CONSTANTS_H*/
+1 -1
View File
@@ -26,7 +26,7 @@
static bool global_dictionary_init = false; static bool global_dictionary_init = false;
void EQ::InitializeDynamicLookups() { void EQ::InitializeDynamicLookups() {
if (global_dictionary_init) if (global_dictionary_init == true)
return; return;
constants::InitializeDynamicLookups(); constants::InitializeDynamicLookups();
+1 -1
View File
@@ -129,7 +129,7 @@ namespace EQ
LookupEntry(const LookupEntry *lookup_entry) { } LookupEntry(const LookupEntry *lookup_entry) { }
LookupEntry( LookupEntry(
const InventoryTypeSize_Struct& InventoryTypeSize, InventoryTypeSize_Struct InventoryTypeSize,
uint64 EquipmentBitmask, uint64 EquipmentBitmask,
uint64 GeneralBitmask, uint64 GeneralBitmask,
uint64 CursorBitmask, uint64 CursorBitmask,
+137
View File
@@ -236,6 +236,26 @@ uint32 EQApplicationPacket::serialize(uint16 opcode, unsigned char *dest) const
return size+OpCodeBytes; return size+OpCodeBytes;
} }
/*EQProtocolPacket::EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len)
: BasePacket(buf, len),
opcode(op)
{
uint32 offset;
opcode=ntohs(*(const uint16 *)buf);
offset=2;
if (len-offset) {
pBuffer= new unsigned char[len-offset];
memcpy(pBuffer,buf+offset,len-offset);
size=len-offset;
} else {
pBuffer=nullptr;
size=0;
}
OpMgr=&RawOpcodeManager;
}*/
bool EQProtocolPacket::combine(const EQProtocolPacket *rhs) bool EQProtocolPacket::combine(const EQProtocolPacket *rhs)
{ {
bool result=false; bool result=false;
@@ -267,6 +287,74 @@ bool result=false;
} }
/*
this is the code to do app-layer combining, instead of protocol layer.
this was taken out due to complex interactions with the opcode manager,
and will require a bit more thinking (likely moving into EQStream) to
get running again... but might be a good thing some day.
bool EQApplicationPacket::combine(const EQApplicationPacket *rhs)
{
uint32 newsize=0, offset=0;
unsigned char *tmpbuffer=nullptr;
if (opcode!=OP_AppCombined) {
newsize=app_opcode_size+size+(size>254?3:1)+app_opcode_size+rhs->size+(rhs->size>254?3:1);
tmpbuffer=new unsigned char [newsize];
offset=0;
if (size>254) {
tmpbuffer[offset++]=0xff;
*(uint16 *)(tmpbuffer+offset)=htons(size);
offset+=1;
} else {
tmpbuffer[offset++]=size;
}
offset+=serialize(tmpbuffer+offset);
} else {
newsize=size+app_opcode_size+rhs->size+(rhs->size>254?3:1);
tmpbuffer=new unsigned char [newsize];
memcpy(tmpbuffer,pBuffer,size);
offset=size;
}
if (rhs->size>254) {
tmpbuffer[offset++]=0xff;
*(uint16 *)(tmpbuffer+offset)=htons(rhs->size);
offset+=1;
} else {
tmpbuffer[offset++]=rhs->size;
}
offset+=rhs->serialize(tmpbuffer+offset);
size=offset;
opcode=OP_AppCombined;
delete[] pBuffer;
pBuffer=tmpbuffer;
return true;
}
*/
bool EQProtocolPacket::ValidateCRC(const unsigned char *buffer, int length, uint32 Key)
{
bool valid=false;
// OP_SessionRequest, OP_SessionResponse, OP_OutOfSession are not CRC'd
if (buffer[0]==0x00 && (buffer[1]==OP_SessionRequest || buffer[1]==OP_SessionResponse || buffer[1]==OP_OutOfSession)) {
valid=true;
} else {
uint16 comp_crc=CRC16(buffer,length-2,Key);
uint16 packet_crc=ntohs(*(const uint16 *)(buffer+length-2));
#ifdef EQN_DEBUG
if (packet_crc && comp_crc != packet_crc) {
std::cout << "CRC mismatch: comp=" << std::hex << comp_crc << ", packet=" << packet_crc << std::dec << std::endl;
}
#endif
valid = (!packet_crc || comp_crc == packet_crc);
}
return valid;
}
uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize) uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize)
{ {
uint32 newlen=0; uint32 newlen=0;
@@ -315,6 +403,55 @@ uint32 flag_offset=1,newlength;
return newlength; return newlength;
} }
void EQProtocolPacket::ChatDecode(unsigned char *buffer, int size, int DecodeKey)
{
if ((size >= 2) && buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
int Key=DecodeKey;
unsigned char *test=(unsigned char *)malloc(size);
buffer+=2;
size-=2;
int i;
for (i = 0 ; i+4 <= size ; i+=4)
{
int pt = (*(int*)&buffer[i])^(Key);
Key = (*(int*)&buffer[i]);
*(int*)&test[i]=pt;
}
unsigned char KC=Key&0xFF;
for ( ; i < size ; i++)
{
test[i]=buffer[i]^KC;
}
memcpy(buffer,test,size);
free(test);
}
}
void EQProtocolPacket::ChatEncode(unsigned char *buffer, int size, int EncodeKey)
{
if (buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
int Key=EncodeKey;
char *test=(char*)malloc(size);
int i;
buffer+=2;
size-=2;
for ( i = 0 ; i+4 <= size ; i+=4)
{
int pt = (*(int*)&buffer[i])^(Key);
Key = pt;
*(int*)&test[i]=pt;
}
unsigned char KC=Key&0xFF;
for ( ; i < size ; i++)
{
test[i]=buffer[i]^KC;
}
memcpy(buffer,test,size);
free(test);
}
}
EQApplicationPacket *EQApplicationPacket::Copy() const { EQApplicationPacket *EQApplicationPacket::Copy() const {
return(new EQApplicationPacket(*this)); return(new EQApplicationPacket(*this));
} }
+3
View File
@@ -80,8 +80,11 @@ public:
protected: protected:
static bool ValidateCRC(const unsigned char *buffer, int length, uint32 Key);
static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize); static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize); static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
static void ChatDecode(unsigned char *buffer, int size, int DecodeKey);
static void ChatEncode(unsigned char *buffer, int size, int EncodeKey);
uint16 GetRawOpcode() const { return(opcode); } uint16 GetRawOpcode() const { return(opcode); }
+28 -83
View File
@@ -29,7 +29,7 @@
#include "textures.h" #include "textures.h"
static const uint32 BUFF_COUNT = 42; static const uint32 BUFF_COUNT = 25;
static const uint32 PET_BUFF_COUNT = 30; static const uint32 PET_BUFF_COUNT = 30;
static const uint32 MAX_MERC = 100; static const uint32 MAX_MERC = 100;
static const uint32 MAX_MERC_GRADES = 10; static const uint32 MAX_MERC_GRADES = 10;
@@ -378,14 +378,14 @@ struct NewZone_Struct {
// 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 // 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 // Just wastes some bandwidth sending to tit clients /shrug
/*0700*/ float fog_density; /*0700*/ float fog_density;
/*0704*/ uint32 suspend_buffs; /*0704*/ uint32 SuspendBuffs;
/*0708*/ uint32 fast_regen_hp; /*0708*/ uint32 FastRegenHP;
/*0712*/ uint32 fast_regen_mana; /*0712*/ uint32 FastRegenMana;
/*0716*/ uint32 fast_regen_endurance; /*0716*/ uint32 FastRegenEndurance;
/*0720*/ uint32 npc_aggro_max_dist; /*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 /*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 /*0728*/ uint32 LavaDamage; // Seen 50
/*0732*/ uint32 min_lava_damage; // Seen 10 /*0732*/ uint32 MinLavaDamage; // Seen 10
/*0736*/ /*0736*/
}; };
@@ -448,7 +448,6 @@ struct ManaChange_Struct
/*08*/ uint32 spell_id; /*08*/ uint32 spell_id;
/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? /*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 /*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 struct SwapSpell_Struct
@@ -1793,17 +1792,6 @@ struct GMSummon_Struct {
/*104*/ uint32 unknown2; // E0 E0 56 00 /*104*/ uint32 unknown2; // E0 E0 56 00
}; };
struct GMFind_Struct {
char charname[64];
char gmname[64];
uint32 success;
uint32 zoneID;
float x;
float y;
float z;
uint32 unknown2;
};
struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet
/* 0*/ char charname[64]; /* 0*/ char charname[64];
@@ -2203,19 +2191,11 @@ struct QuestReward_Struct
/*068*/ /*068*/
}; };
struct CashReward_Struct
{
/*000*/ uint32 copper;
/*004*/ uint32 silver;
/*008*/ uint32 gold;
/*012*/ uint32 platinum;
};
// Size: 8 // Size: 8
struct Camera_Struct struct Camera_Struct
{ {
uint32 duration; // Duration in ms uint32 duration; // Duration in ms
float intensity; uint32 intensity; // Between 1023410176 and 1090519040
}; };
struct ZonePoint_Entry { struct ZonePoint_Entry {
@@ -2335,12 +2315,9 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle; /*004*/ uint8 hairstyle;
/*005*/ uint8 beard; /*005*/ uint8 beard;
/*006*/ uint8 face; /*006*/ uint8 face;
/*007*/ uint8 unused_padding; /*007*/ uint32 drakkin_heritage;
/*008*/ uint32 drakkin_heritage; /*011*/ uint32 drakkin_tattoo;
/*012*/ uint32 drakkin_tattoo; /*015*/ uint32 drakkin_details;
/*016*/ uint32 drakkin_details;
/*020*/ uint32 entity_id;
/*024*/
//there are only 10 faces for barbs changing woad just //there are only 10 faces for barbs changing woad just
//increase the face value by ten so if there were 8 woad //increase the face value by ten so if there were 8 woad
//designs then there would be 80 barb faces //designs then there would be 80 barb faces
@@ -2559,10 +2536,7 @@ struct GMEmoteZone_Struct {
struct BookText_Struct { struct BookText_Struct {
uint8 window; // where to display the text (0xFF means new window) uint8 window; // where to display the text (0xFF means new window)
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others. uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
int16 invslot; // Only used in SoF and later clients. uint32 invslot; // Only used in SoF and later clients.
int32 target_id;
int8 can_cast;
int8 can_scribe;
char booktext[1]; // Variable Length char booktext[1]; // Variable Length
}; };
// This is the request to read a book. // This is the request to read a book.
@@ -2571,18 +2545,11 @@ struct BookText_Struct {
struct BookRequest_Struct { struct BookRequest_Struct {
uint8 window; // where to display the text (0xFF means new window) uint8 window; // where to display the text (0xFF means new window)
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others. uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
int16 invslot; // Only used in Sof and later clients; uint32 invslot; // Only used in Sof and later clients;
int32 target_id; int16 subslot; // The subslot inside of a bag if it is inside one.
char txtfile[20]; char txtfile[20];
}; };
// used by Scribe and CastSpell book buttons
struct BookButton_Struct
{
int16 invslot; // server slot
int32 target_id;
};
/* /*
** Object/Ground Spawn struct ** Object/Ground Spawn struct
** Used for Forges, Ovens, ground spawns, items dropped to ground, etc ** Used for Forges, Ovens, ground spawns, items dropped to ground, etc
@@ -2794,7 +2761,7 @@ struct EnvDamage2_Struct {
/*0004*/ uint16 unknown4; /*0004*/ uint16 unknown4;
/*0006*/ uint32 damage; /*0006*/ uint32 damage;
/*0010*/ uint8 unknown10[12]; /*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]; /*0023*/ uint8 unknown2[4];
/*0027*/ uint16 constant; //Always FFFF /*0027*/ uint16 constant; //Always FFFF
/*0029*/ uint16 unknown29; /*0029*/ uint16 unknown29;
@@ -3658,14 +3625,9 @@ struct MerchantList {
uint32 item; uint32 item;
int16 faction_required; int16 faction_required;
int8 level_required; int8 level_required;
uint8 min_status;
uint8 max_status;
uint16 alt_currency_cost; uint16 alt_currency_cost;
uint32 classes_required; uint32 classes_required;
uint8 probability; uint8 probability;
std::string bucket_name;
std::string bucket_value;
uint8 bucket_comparison;
}; };
struct TempMerchantList { struct TempMerchantList {
@@ -4115,9 +4077,7 @@ struct UpdateLeadershipAA_Struct {
enum enum
{ {
GroupLeadershipAbility_MarkNPC = 0, GroupLeadershipAbility_MarkNPC = 0
RaidLeadershipAbility_MarkNPC = 16,
RaidLeadershipAbility_MainAssist = 19
}; };
struct DoGroupLeadershipAbility_Struct struct DoGroupLeadershipAbility_Struct
@@ -4161,9 +4121,8 @@ struct InspectBuffs_Struct {
struct RaidGeneral_Struct { struct RaidGeneral_Struct {
/*00*/ uint32 action; //=10 /*00*/ uint32 action; //=10
/*04*/ char player_name[64]; //should both be the player's name /*04*/ char player_name[64]; //should both be the player's name
/*68*/ uint32 unknown1; /*64*/ char leader_name[64];
/*72*/ char leader_name[64]; /*132*/ uint32 parameter;
/*136*/ uint32 parameter;
}; };
struct RaidAddMember_Struct { struct RaidAddMember_Struct {
@@ -4174,14 +4133,9 @@ struct RaidAddMember_Struct {
/*139*/ uint8 flags[5]; //no idea if these are needed... /*139*/ uint8 flags[5]; //no idea if these are needed...
}; };
struct RaidNote_Struct {
/*000*/ RaidGeneral_Struct general;
/*140*/ char note[64];
};
struct RaidMOTD_Struct { struct RaidMOTD_Struct {
/*000*/ RaidGeneral_Struct general; /*000*/ RaidGeneral_Struct general; // leader_name and action only used
/*140*/ char motd[1024]; /*136*/ char motd[0]; // max size is 1024, but reply is variable
}; };
struct RaidLeadershipUpdate_Struct { struct RaidLeadershipUpdate_Struct {
@@ -4576,7 +4530,7 @@ struct ItemVerifyReply_Struct {
struct ItemRecastDelay_Struct { struct ItemRecastDelay_Struct {
/*000*/ uint32 recast_delay; // in seconds /*000*/ uint32 recast_delay; // in seconds
/*004*/ uint32 recast_type; /*004*/ uint32 recast_type;
/*008*/ bool ignore_casting_requirement; //Ignores recast times allows items to be reset? /*008*/ uint32 unknown008;
/*012*/ /*012*/
}; };
@@ -5037,7 +4991,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair /*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id; /*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) /*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; /*012*/ float y;
/*016*/ float x; /*016*/ float x;
/*020*/ float z; /*020*/ float z;
@@ -5194,10 +5148,10 @@ struct AltCurrencySelectItemReply_Struct {
/*000*/ uint32 unknown000; /*000*/ uint32 unknown000;
/*004*/ uint8 unknown004; //0xff /*004*/ uint8 unknown004; //0xff
/*005*/ uint8 unknown005; //0xff /*005*/ uint8 unknown005; //0xff
/*006*/ uint16 unknown006; //0xffff /*006*/ uint8 unknown006; //0xff
/*008*/ uint16 unknown008; //0xffff /*007*/ uint8 unknown007; //0xff
/*010*/ char item_name[64]; /*008*/ char item_name[64];
/*074*/ uint16 unknown074; /*072*/ uint32 unknown074;
/*076*/ uint32 cost; /*076*/ uint32 cost;
/*080*/ uint32 unknown080; /*080*/ uint32 unknown080;
/*084*/ uint32 unknown084; /*084*/ uint32 unknown084;
@@ -5551,11 +5505,7 @@ struct ServerLootItem_Struct {
uint32 aug_4; // uint32 aug_4; uint32 aug_4; // uint32 aug_4;
uint32 aug_5; // uint32 aug_5; uint32 aug_5; // uint32 aug_5;
uint32 aug_6; // uint32 aug_5; uint32 aug_6; // uint32 aug_5;
bool attuned; uint8 attuned;
std::string custom_data;
uint32 ornamenticon {};
uint32 ornamentidfile {};
uint32 ornament_hero_model {};
uint16 trivial_min_level; uint16 trivial_min_level;
uint16 trivial_max_level; uint16 trivial_max_level;
uint16 npc_min_level; uint16 npc_min_level;
@@ -5631,11 +5581,6 @@ struct SayLinkBodyFrame_Struct {
/*056*/ /*056*/
}; };
struct Checksum_Struct {
uint64 checksum;
uint8 data[2048];
};
struct UpdateMovementEntry { struct UpdateMovementEntry {
/* 00 */ float Y; /* 00 */ float Y;
/* 04 */ float X; /* 04 */ float X;
+1 -1
View File
@@ -23,7 +23,7 @@
#include "op_codes.h" #include "op_codes.h"
#include "crc16.h" #include "crc16.h"
#include "platform.h" #include "platform.h"
#include "strings.h" #include "string_util.h"
#include <string> #include <string>
#include <iomanip> #include <iomanip>
-5
View File
@@ -243,11 +243,6 @@ class EQStream : public EQStreamInterface {
virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; } virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; }
virtual OpcodeManager* GetOpcodeManager() const
{
return (*OpMgr);
};
void CheckTimeout(uint32 now, uint32 timeout=30); void CheckTimeout(uint32 now, uint32 timeout=30);
bool HasOutgoingData(); bool HasOutgoingData();
void Process(const unsigned char *data, const uint32 length); void Process(const unsigned char *data, const uint32 length);
+2 -2
View File
@@ -26,7 +26,7 @@ EQStreamIdentifier::~EQStreamIdentifier() {
} }
} }
void EQStreamIdentifier::RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) { void EQStreamIdentifier::RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) {
auto p = new Patch; auto p = new Patch;
p->signature = sig; p->signature = sig;
p->name = name; p->name = name;
@@ -145,7 +145,7 @@ void EQStreamIdentifier::Process() {
} }
void EQStreamIdentifier::AddStream(std::shared_ptr<EQStreamInterface> eqs) { void EQStreamIdentifier::AddStream(std::shared_ptr<EQStreamInterface> eqs) {
m_streams.emplace_back(Record(eqs)); m_streams.push_back(Record(eqs));
eqs = nullptr; eqs = nullptr;
} }
+1 -1
View File
@@ -18,7 +18,7 @@ public:
~EQStreamIdentifier(); ~EQStreamIdentifier();
//registration interface. //registration interface.
void RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs); void RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs);
//main processing interface //main processing interface
void Process(); void Process();
-1
View File
@@ -100,7 +100,6 @@ public:
virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; } virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; }
virtual EQStreamState GetState() = 0; virtual EQStreamState GetState() = 0;
virtual void SetOpcodeManager(OpcodeManager **opm) = 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 const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; }
virtual Stats GetStats() const = 0; virtual Stats GetStats() const = 0;
virtual void ResetStats() = 0; virtual void ResetStats() = 0;
+5 -6
View File
@@ -38,8 +38,12 @@ void EQStreamProxy::SetOpcodeManager(OpcodeManager **opm)
} }
void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) { void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
if (p == nullptr) { if(p == nullptr)
return; 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(); EQApplicationPacket *newp = p->Copy();
@@ -108,8 +112,3 @@ bool EQStreamProxy::CheckState(EQStreamState state) {
return false; return false;
} }
OpcodeManager *EQStreamProxy::GetOpcodeManager() const
{
return (*m_opcodes);
}
+1 -3
View File
@@ -34,15 +34,13 @@ public:
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats(); virtual void ResetStats();
virtual EQStreamManagerInterface* GetManager() const; virtual EQStreamManagerInterface* GetManager() const;
virtual OpcodeManager* GetOpcodeManager() const;
protected: protected:
std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object. std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object.
const StructStrategy *const m_structs; //we do not own this 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 //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. //reference an invalid opcode manager when they are being reloaded.
OpcodeManager **const m_opcodes; OpcodeManager **const m_opcodes; //we do not own this object.
//we do not own this object.
}; };
#endif /*EQSTREAMPROXY_H_*/ #endif /*EQSTREAMPROXY_H_*/
+3
View File
@@ -23,6 +23,9 @@
EQDB EQDB::s_EQDB; EQDB EQDB::s_EQDB;
EQDB::EQDB() {
}
unsigned int EQDB::field_count() { unsigned int EQDB::field_count() {
return mysql_field_count(mysql_ref); return mysql_field_count(mysql_ref);
} }
+1 -1
View File
@@ -27,7 +27,7 @@
//this is the main object exported to perl. //this is the main object exported to perl.
class EQDB { class EQDB {
EQDB() = default; EQDB();
public: public:
static EQDB *Singleton() { return(&s_EQDB); } static EQDB *Singleton() { return(&s_EQDB); }
+18 -29
View File
@@ -19,7 +19,6 @@
#include "../common/global_define.h" #include "../common/global_define.h"
#include "eqemu_config.h" #include "eqemu_config.h"
#include "misc_functions.h" #include "misc_functions.h"
#include "strings.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@@ -34,13 +33,13 @@ void EQEmuConfig::parse_config()
LongName = _root["server"]["world"].get("longname", "").asString(); LongName = _root["server"]["world"].get("longname", "").asString();
WorldAddress = _root["server"]["world"].get("address", "").asString(); WorldAddress = _root["server"]["world"].get("address", "").asString();
LocalAddress = _root["server"]["world"].get("localaddress", "").asString(); LocalAddress = _root["server"]["world"].get("localaddress", "").asString();
MaxClients = Strings::ToInt(_root["server"]["world"].get("maxclients", "-1").asString()); MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str());
SharedKey = _root["server"]["world"].get("key", "").asString(); SharedKey = _root["server"]["world"].get("key", "").asString();
LoginCount = 0; LoginCount = 0;
if (_root["server"]["world"]["loginserver"].isObject()) { if (_root["server"]["world"]["loginserver"].isObject()) {
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString(); LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
LoginPort = Strings::ToUnsignedInt(_root["server"]["world"]["loginserver"].get("port", "5998").asString()); LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
LoginLegacy = false; LoginLegacy = false;
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; } if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString(); LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
@@ -63,7 +62,7 @@ void EQEmuConfig::parse_config()
auto loginconfig = new LoginConfig; auto loginconfig = new LoginConfig;
loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString(); loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString();
loginconfig->LoginPort = Strings::ToUnsignedInt(_root["server"]["world"][str].get("port", "5998").asString()); loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str());
loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString(); loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString();
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString(); loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
@@ -85,39 +84,29 @@ void EQEmuConfig::parse_config()
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true //The only way to enable locked is by switching to true, meaning this value is always false until manually set true
Locked = false; Locked = false;
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; } if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
auto_database_updates = false;
if (_root["server"].get("auto_database_updates", "true").asString() == "true") {
auto_database_updates = true;
}
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString(); WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
WorldTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["tcp"].get("port", "9000").asString()); WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString(); TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
TelnetTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["telnet"].get("port", "9001").asString()); TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
TelnetEnabled = false; TelnetEnabled = false;
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; } if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; }
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString(); WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
WorldHTTPPort = Strings::ToUnsignedInt(_root["server"]["world"]["http"].get("port", "9080").asString()); WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
WorldHTTPEnabled = false; WorldHTTPEnabled = false;
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") { if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
WorldHTTPEnabled = true; WorldHTTPEnabled = true;
} }
if (_root["server"].get("disable_config_checks", "false").asString() == "true") {
DisableConfigChecks = true;
}
/** /**
* UCS * UCS
*/ */
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString(); ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
ChatPort = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "7778").asString()); ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString(); MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
MailPort = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "7778").asString()); MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
/** /**
* Database * Database
@@ -125,7 +114,7 @@ void EQEmuConfig::parse_config()
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString(); DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
DatabasePassword = _root["server"]["database"].get("password", "eq").asString(); DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString(); DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
DatabasePort = Strings::ToUnsignedInt(_root["server"]["database"].get("port", "3306").asString()); DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
DatabaseDB = _root["server"]["database"].get("db", "eq").asString(); DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
/** /**
@@ -134,14 +123,14 @@ void EQEmuConfig::parse_config()
ContentDbUsername = _root["server"]["content_database"].get("username", "").asString(); ContentDbUsername = _root["server"]["content_database"].get("username", "").asString();
ContentDbPassword = _root["server"]["content_database"].get("password", "").asString(); ContentDbPassword = _root["server"]["content_database"].get("password", "").asString();
ContentDbHost = _root["server"]["content_database"].get("host", "").asString(); ContentDbHost = _root["server"]["content_database"].get("host", "").asString();
ContentDbPort = Strings::ToUnsignedInt(_root["server"]["content_database"].get("port", 0).asString()); ContentDbPort = atoi(_root["server"]["content_database"].get("port", 0).asString().c_str());
ContentDbName = _root["server"]["content_database"].get("db", "").asString(); ContentDbName = _root["server"]["content_database"].get("db", "").asString();
/** /**
* QS * QS
*/ */
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString(); QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
QSDatabasePort = Strings::ToUnsignedInt(_root["server"]["qsdatabase"].get("port", "3306").asString()); QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString(); QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString(); QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString(); QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
@@ -149,9 +138,9 @@ void EQEmuConfig::parse_config()
/** /**
* Zones * Zones
*/ */
DefaultStatus = Strings::ToUnsignedInt(_root["server"]["zones"].get("defaultstatus", 0).asString()); DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
ZonePortLow = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("low", "7000").asString()); ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
ZonePortHigh = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("high", "7999").asString()); ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
/** /**
* Files * Files
@@ -181,10 +170,10 @@ void EQEmuConfig::parse_config()
/** /**
* Launcher * Launcher
*/ */
RestartWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("restart", "10000").asString()); RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
TerminateWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString()); TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
InitialBootWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("initial", "20000").asString()); InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
ZoneBootInterval = Strings::ToInt(_root["server"]["launcher"]["timers"].get("interval", "2000").asString()); ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str());
#ifdef WIN32 #ifdef WIN32
ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString(); ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString();
#else #else
+11 -18
View File
@@ -20,9 +20,7 @@
#include "json/json.h" #include "json/json.h"
#include "linked_list.h" #include "linked_list.h"
#include "path_manager.h"
#include <fstream> #include <fstream>
#include <fmt/format.h>
struct LoginConfig { struct LoginConfig {
std::string LoginHost; std::string LoginHost;
@@ -60,7 +58,6 @@ class EQEmuConfig
uint16 WorldHTTPPort; uint16 WorldHTTPPort;
std::string WorldHTTPMimeFile; std::string WorldHTTPMimeFile;
std::string SharedKey; std::string SharedKey;
bool DisableConfigChecks;
// From <chatserver/> // From <chatserver/>
std::string ChatHost; std::string ChatHost;
@@ -120,8 +117,6 @@ class EQEmuConfig
uint16 ZonePortHigh; uint16 ZonePortHigh;
uint8 DefaultStatus; uint8 DefaultStatus;
bool auto_database_updates;
// uint16 DynamicCount; // uint16 DynamicCount;
// map<string,uint16> StaticZones; // map<string,uint16> StaticZones;
@@ -149,32 +144,30 @@ class EQEmuConfig
return (_config); return (_config);
} }
// Allow the use to set the conf file to be used.
static void SetConfigFile(std::string file)
{
EQEmuConfig::ConfigFile = file;
}
// Load the config // Load the config
static bool LoadConfig(const std::string& path = "") static bool LoadConfig()
{ {
if (_config != nullptr) { if (_config != nullptr) {
return true; return true;
} }
_config = new EQEmuConfig; _config = new EQEmuConfig;
return parseFile(path); return parseFile();
} }
// Load config file and parse data // Load config file and parse data
static bool parseFile(const std::string& file_path = ".") static bool parseFile() {
{
if (_config == nullptr) { if (_config == nullptr) {
return LoadConfig(file_path); return LoadConfig();
} }
std::string file = fmt::format( std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary);
"{}/{}",
(file_path.empty() ? path.GetServerPath() : file_path),
EQEmuConfig::ConfigFile
);
std::ifstream fconfig(file, std::ifstream::binary);
try { try {
fconfig >> _config->_root; fconfig >> _config->_root;
_config->parse_config(); _config->parse_config();
+301 -431
View File
@@ -21,20 +21,20 @@
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "rulesys.h" #include "rulesys.h"
#include "platform.h" #include "platform.h"
#include "strings.h" #include "string_util.h"
#include "repositories/discord_webhooks_repository.h" #include "misc.h"
#include "repositories/logsys_categories_repository.h" #include "repositories/logsys_categories_repository.h"
#include "termcolor/rang.hpp"
#include <iostream> #include <iostream>
#include <fstream>
#include <string> #include <string>
#include <iomanip>
#include <time.h> #include <time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <algorithm>
std::ofstream process_log; std::ofstream process_log;
#include <filesystem>
#ifdef _WINDOWS #ifdef _WINDOWS
#include <direct.h> #include <direct.h>
#include <conio.h> #include <conio.h>
@@ -46,17 +46,50 @@ std::ofstream process_log;
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <thread>
#endif #endif
/**
* Linux ANSI console color defines
*/
#define LC_RESET "\033[0m"
#define LC_BLACK "\033[30m" /* Black */
#define LC_RED "\033[31m" /* Red */
#define LC_GREEN "\033[32m" /* Green */
#define LC_YELLOW "\033[33m" /* Yellow */
#define LC_BLUE "\033[34m" /* Blue */
#define LC_MAGENTA "\033[35m" /* Magenta */
#define LC_CYAN "\033[36m" /* Cyan */
#define LC_WHITE "\033[37m" /* White */
namespace Console {
enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
LightMagenta = 13,
Yellow = 14,
White = 15
};
}
/** /**
* EQEmuLogSys Constructor * EQEmuLogSys Constructor
*/ */
EQEmuLogSys::EQEmuLogSys() EQEmuLogSys::EQEmuLogSys()
{ {
m_on_log_gmsay_hook = [](uint16 log_type, const char *func, const std::string &) {}; on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
m_on_log_console_hook = [](uint16 log_type, const std::string &) {}; on_log_console_hook = [](uint16 debug_level, uint16 log_type, const std::string &) {};
} }
/** /**
@@ -69,23 +102,28 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/** /**
* Get Executable platform currently running this code (Zone/World/etc) * 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++) { 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_console = 0;
log_settings[log_category_id].log_to_file = 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_gmsay = 0;
log_settings[log_category_id].log_to_discord = 0;
log_settings[log_category_id].is_category_enabled = 0; log_settings[log_category_id].is_category_enabled = 0;
} }
m_file_logs_enabled = false; file_logs_enabled = false;
/** /**
* Set Defaults * 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::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].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::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_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
@@ -94,18 +132,16 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Cheat].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_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General); log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::CombatRecord].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
/** /**
* RFC 5424 * RFC 5424
*/ */
log_settings[Logs::Emergency].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Alert].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Critical].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Notice].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
/** /**
@@ -115,8 +151,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
const bool log_to_console = log_settings[log_category_id].log_to_console > 0; 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_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_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;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord;
if (is_category_enabled) { if (is_category_enabled) {
log_settings[log_category_id].is_category_enabled = 1; log_settings[log_category_id].is_category_enabled = 1;
} }
@@ -125,37 +160,99 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/** /**
* Declare process file names for log writing= * Declare process file names for log writing=
*/ */
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld) { if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) {
m_platform_file_name = "world"; platform_file_name = "world";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformQueryServ) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
m_platform_file_name = "query_server"; platform_file_name = "query_server";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
m_platform_file_name = "zone"; platform_file_name = "zone";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformUCS) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) {
m_platform_file_name = "ucs"; platform_file_name = "ucs";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLogin) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) {
m_platform_file_name = "login"; platform_file_name = "login";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLaunch) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) {
m_platform_file_name = "launcher"; platform_file_name = "launcher";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformHC) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) {
m_platform_file_name = "hc"; platform_file_name = "hc";
} }
return this; return this;
} }
/**
* @param log_category
* @return
*/
bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category)
{
return (
log_category == Logs::Emergency ||
log_category == Logs::Alert ||
log_category == Logs::Critical ||
log_category == Logs::Error ||
log_category == Logs::Warning ||
log_category == Logs::Notice ||
log_category == Logs::Info ||
log_category == Logs::Debug
);
}
/**
* @param log_category
* @param in_message
* @return
*/
std::string EQEmuLogSys::FormatOutMessageString(
uint16 log_category,
const std::string &in_message
)
{
std::string return_string = "[" + GetPlatformName() + "] ";
return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message;
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessGMSay(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
{
/**
* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
*/
if (log_category == Logs::LogCategory::Netcode) {
return;
}
/**
* Processes that actually support hooks
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld
) {
on_log_gmsay_hook(log_category, message);
}
}
/** /**
* @param debug_level * @param debug_level
* @param log_category * @param log_category
* @param message * @param message
*/ */
void EQEmuLogSys::ProcessLogWrite( void EQEmuLogSys::ProcessLogWrite(
uint16 debug_level,
uint16 log_category, uint16 log_category,
const std::string &message const std::string &message
) )
@@ -166,20 +263,79 @@ void EQEmuLogSys::ProcessLogWrite(
std::ofstream crash_log; std::ofstream crash_log;
EQEmuLogSys::MakeDirectory("logs/crashes"); EQEmuLogSys::MakeDirectory("logs/crashes");
crash_log.open( 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 std::ios_base::app | std::ios_base::out
); );
crash_log << time_stamp << " " << message << "\n"; crash_log << time_stamp << " " << message << "\n";
crash_log.close(); crash_log.close();
} }
if (process_log) {
char time_stamp[80]; char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp); EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
if (process_log) {
process_log << time_stamp << " " << message << std::endl; process_log << time_stamp << " " << message << std::endl;
} }
} }
/**
* @param log_category
* @return
*/
uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) {
case Logs::Status:
case Logs::Normal:
return Console::Color::Yellow;
case Logs::MySQLError:
case Logs::Error:
return Console::Color::LightRed;
case Logs::MySQLQuery:
case Logs::Debug:
return Console::Color::LightGreen;
case Logs::Quests:
return Console::Color::LightCyan;
case Logs::Commands:
case Logs::Mercenaries:
return Console::Color::LightMagenta;
case Logs::Crash:
return Console::Color::LightRed;
default:
return Console::Color::Yellow;
}
}
/**
* @param log_category
* @return
*/
std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) {
case Logs::Status:
case Logs::Normal:
return LC_YELLOW;
case Logs::MySQLError:
case Logs::Warning:
case Logs::Critical:
case Logs::Error:
return LC_RED;
case Logs::MySQLQuery:
case Logs::Debug:
return LC_GREEN;
case Logs::Quests:
return LC_CYAN;
case Logs::Commands:
case Logs::Mercenaries:
return LC_MAGENTA;
case Logs::Crash:
return LC_RED;
default:
return LC_YELLOW;
}
}
/** /**
* @param log_category * @param log_category
* @return * @return
@@ -187,10 +343,11 @@ void EQEmuLogSys::ProcessLogWrite(
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
{ {
switch (log_category) { switch (log_category) {
case Logs::Crash: case Logs::Status:
case Logs::Error: case Logs::Normal:
return Chat::Yellow;
case Logs::MySQLError: case Logs::MySQLError:
case Logs::QuestErrors: case Logs::Error:
return Chat::Red; return Chat::Red;
case Logs::MySQLQuery: case Logs::MySQLQuery:
case Logs::Debug: case Logs::Debug:
@@ -200,208 +357,37 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
case Logs::Commands: case Logs::Commands:
case Logs::Mercenaries: case Logs::Mercenaries:
return Chat::Magenta; return Chat::Magenta;
case Logs::Crash:
return Chat::Red;
default: default:
return Chat::Yellow; return Chat::Yellow;
} }
} }
/** /**
* @param debug_level * @param debug_level
* @param log_category * @param log_category
* @param message * @param message
*/ */
void EQEmuLogSys::ProcessConsoleMessage( void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message)
uint16 log_category,
const std::string &message,
const char *file,
const char *func,
int line
)
{ {
bool is_error = ( #ifdef _WINDOWS
log_category == Logs::LogCategory::Error || HANDLE console_handle;
log_category == Logs::LogCategory::MySQLError || console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
log_category == Logs::LogCategory::Crash || CONSOLE_FONT_INFOEX info = { 0 };
log_category == Logs::LogCategory::QuestErrors info.cbSize = sizeof(info);
); info.dwFontSize.Y = 12; // leave X as zero
bool is_warning = ( info.FontWeight = FW_NORMAL;
log_category == Logs::LogCategory::Warning wcscpy(info.FaceName, L"Lucida Console");
); SetCurrentConsoleFontEx(console_handle, NULL, &info);
SetConsoleTextAttribute(console_handle, EQEmuLogSys::GetWindowsConsoleColorFromCategory(log_category));
std::cout << message << "\n";
SetConsoleTextAttribute(console_handle, Console::Color::White);
#else
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
#endif
(!is_error ? std::cout : std::cerr) on_log_console_hook(debug_level, log_category, message);
<< ""
<< rang::fgB::black
<< rang::style::bold
<< fmt::format("{:>6}", GetPlatformName().substr(0, 6))
<< rang::style::reset
<< rang::fgB::gray
<< " | "
<< ((is_error || is_warning) ? rang::fgB::red : rang::fgB::gray)
<< rang::style::bold
<< fmt::format("{:^10}", fmt::format("{}", Logs::LogCategoryName[log_category]).substr(0, 10))
<< rang::style::reset
<< rang::fgB::gray
<< " | "
<< rang::fgB::gray
<< rang::style::bold
<< fmt::format("{}", func)
<< rang::style::reset
<< rang::fgB::gray
<< " ";
if (RuleB(Logging, PrintFileFunctionAndLine)) {
(!is_error ? std::cout : std::cerr)
<< ""
<< rang::fgB::green
<< rang::style::bold
<< fmt::format("{:}", fmt::format("{}:{}:{}", std::filesystem::path(file).filename().string(), func, line))
<< rang::style::reset
<< " | ";
}
if (log_category == Logs::LogCategory::MySQLQuery) {
auto s = Strings::Split(message, "--");
if (s.size() > 1) {
std::string query = Strings::Trim(s[0]);
std::string meta = Strings::Trim(s[1]);
std::cout <<
rang::fgB::green
<<
query
<<
rang::style::reset;
std::cout <<
rang::fgB::black
<<
" -- "
<<
meta
<<
rang::style::reset;
}
}
else if (Strings::Contains(message, "[")) {
for (auto &e: Strings::Split(message, " ")) {
if (Strings::Contains(e, "[") && Strings::Contains(e, "]")) {
e = Strings::Replace(e, "[", "");
e = Strings::Replace(e, "]", "");
bool is_upper = false;
for (int i = 0; i < strlen(e.c_str()); i++) {
if (isupper(e[i])) {
is_upper = true;
}
}
// color matching in []
// ex: [<red>variable] would produce [variable] with red inside brackets
std::map<std::string, rang::fgB> colors = {
{"<black>", rang::fgB::black},
{"<green>", rang::fgB::green},
{"<yellow>", rang::fgB::yellow},
{"<blue>", rang::fgB::blue},
{"<magenta>", rang::fgB::magenta},
{"<cyan>", rang::fgB::cyan},
{"<gray>", rang::fgB::gray},
{"<red>", rang::fgB::red},
};
bool match_color = false;
for (auto &c: colors) {
if (Strings::Contains(e, c.first)) {
e = Strings::Replace(e, c.first, "");
(!is_error ? std::cout : std::cerr)
<< rang::fgB::gray
<< "["
<< rang::style::bold
<< c.second
<< e
<< rang::style::reset
<< rang::fgB::gray
<< "] ";
match_color = true;
}
}
// string match to colors
std::map<std::string, rang::fgB> matches = {
{"missing", rang::fgB::red},
{"error", rang::fgB::red},
{"ok", rang::fgB::green},
};
for (auto &c: matches) {
if (Strings::Contains(e, c.first)) {
(!is_error ? std::cout : std::cerr)
<< rang::fgB::gray
<< "["
<< rang::style::bold
<< c.second
<< e
<< rang::style::reset
<< rang::fgB::gray
<< "] ";
match_color = true;
}
}
// if we don't match a color in either the string matching or
// the color tag matching, we default to yellow inside brackets
// if uppercase, does not get colored
if (!match_color) {
if (!is_upper) {
(!is_error ? std::cout : std::cerr)
<< rang::fgB::gray
<< "["
<< rang::style::bold
<< rang::fgB::yellow
<< e
<< rang::style::reset
<< rang::fgB::gray
<< "] ";
}
else {
(!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] ";
}
}
}
else {
(!is_error ? std::cout : std::cerr)
<< (is_error ? rang::fgB::red : rang::fgB::gray)
<< e
<< " ";
}
}
}
else {
(!is_error ? std::cout : std::cerr)
<< (is_error ? rang::fgB::red : rang::fgB::gray)
<< message
<< " ";
}
if (!origination_info.zone_short_name.empty()) {
(!is_error ? std::cout : std::cerr)
<<
rang::fgB::black
<<
"-- "
<<
fmt::format(
"[{}] ({}) inst_id [{}]",
origination_info.zone_short_name,
origination_info.zone_long_name,
origination_info.instance_id
);
}
(!is_error ? std::cout : std::cerr) << rang::style::reset << std::endl;
m_on_log_console_hook(log_category, message);
} }
/** /**
@@ -413,6 +399,33 @@ constexpr const char *str_end(const char *str)
return *str ? str_end(str + 1) : str; return *str ? str_end(str + 1) : str;
} }
/**
* @param str
* @return
*/
constexpr bool str_slant(const char *str)
{
return *str == '/' ? true : (*str ? str_slant(str + 1) : false);
}
/**
* @param str
* @return
*/
constexpr const char *r_slant(const char *str)
{
return *str == '/' ? (str + 1) : r_slant(str - 1);
}
/**
* @param str
* @return
*/
constexpr const char *base_file_name(const char *str)
{
return str_slant(str) ? r_slant(str_end(str)) : str;
}
/** /**
* Core logging function * Core logging function
* *
@@ -431,57 +444,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 bool log_to_file = true;
if (!l.log_enabled) { 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; return;
} }
std::string prefix; std::string prefix;
if (RuleB(Logging, PrintFileFunctionAndLine)) { if (RuleB(Logging, PrintFileFunctionAndLine)) {
prefix = fmt::format("[{0}::{1}:{2}] ", std::filesystem::path(file).filename().string(), func, line); 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::MySQLQuery ||
log_category == Logs::MySQLError ||
log_category == Logs::PacketServerClient ||
log_category == Logs::PacketClientServer ||
log_category == Logs::PacketServerToServer
);
// remove this when we remove all legacy logs
std::string output_message = message;
if (!ignore_log_legacy_format) {
va_list args; va_list args;
va_start(args, message); va_start(args, message);
output_message = vStringFormat(message, args); std::string output_message = vStringFormat(message, args);
va_end(args); va_end(args);
}
if (l.log_to_console_enabled) { std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message);
EQEmuLogSys::ProcessConsoleMessage(
log_category, if (log_to_console) {
output_message, EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
file,
func,
line
);
} }
if (l.log_to_gmsay_enabled) { if (log_to_gmsay) {
m_on_log_gmsay_hook(log_category, func, output_message); EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
} }
if (l.log_to_file_enabled) { if (log_to_file) {
EQEmuLogSys::ProcessLogWrite( EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
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);
} }
} }
@@ -494,7 +497,7 @@ void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp)
struct tm *time_info; struct tm *time_info;
time(&raw_time); time(&raw_time);
time_info = localtime(&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);
} }
/** /**
@@ -533,45 +536,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... * 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; return;
} }
/** /**
* Zone * Zone
*/ */
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) { if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
if (!log_name.empty()) { 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; 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( 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 std::ios_base::app | std::ios_base::out
); );
} }
else { else {
// All other processes /**
if (m_platform_file_name.empty()) { * All other processes
*/
if (platform_file_name.empty()) {
return; 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( 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 std::ios_base::app | std::ios_base::out
); );
} }
@@ -582,14 +593,10 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
*/ */
void EQEmuLogSys::SilenceConsoleLogging() void EQEmuLogSys::SilenceConsoleLogging()
{ {
std::copy(std::begin(log_settings), std::end(log_settings), std::begin(pre_silence_settings));
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) { for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
log_settings[log_index].log_to_console = 0; log_settings[log_index].log_to_console = 0;
log_settings[log_index].is_category_enabled = 0; log_settings[log_index].is_category_enabled = 0;
} }
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
} }
/** /**
@@ -597,13 +604,14 @@ void EQEmuLogSys::SilenceConsoleLogging()
*/ */
void EQEmuLogSys::EnableConsoleLogging() void EQEmuLogSys::EnableConsoleLogging()
{ {
std::copy(std::begin(pre_silence_settings), std::end(pre_silence_settings), std::begin(log_settings)); for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
log_settings[log_index].log_to_console = Logs::General;
log_settings[log_index].is_category_enabled = 1;
}
} }
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings() EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
{ {
InjectTablesIfNotExist();
auto categories = LogsysCategoriesRepository::GetWhere( auto categories = LogsysCategoriesRepository::GetWhere(
*m_database, *m_database,
"TRUE ORDER BY log_category_id" "TRUE ORDER BY log_category_id"
@@ -622,17 +630,13 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
log_settings[c.log_category_id].log_to_console = static_cast<uint8>(c.log_to_console); 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_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_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 // 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 // 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_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_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_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 && const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
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) { if (is_category_enabled) {
log_settings[c.log_category_id].is_category_enabled = 1; log_settings[c.log_category_id].is_category_enabled = 1;
@@ -642,7 +646,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
// If we go through this whole loop and nothing is set to any debug level, there // 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 // is no point to create a file or keep anything open
if (log_settings[c.log_category_id].log_to_file > 0) { if (log_settings[c.log_category_id].log_to_file > 0) {
LogSys.m_file_logs_enabled = true; LogSys.file_logs_enabled = true;
} }
db_categories.emplace_back(c.log_category_id); db_categories.emplace_back(c.log_category_id);
@@ -650,32 +654,18 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
// Auto inject categories that don't exist in the database... // Auto inject categories that don't exist in the database...
for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) { for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) {
if (std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end()) {
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( LogInfo(
"Logging category [{}] ({}) is now deprecated, deleting from database", "Automatically adding new log category [{0}]",
Logs::LogCategoryName[i], 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(); auto new_category = LogsysCategoriesRepository::NewEntity();
new_category.log_category_id = i; new_category.log_category_id = i;
new_category.log_category_description = Strings::Escape(Logs::LogCategoryName[i]); new_category.log_category_description = EscapeString(Logs::LogCategoryName[i]);
new_category.log_to_console = log_settings[i].log_to_console; 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_gmsay = log_settings[i].log_to_gmsay;
new_category.log_to_file = log_settings[i].log_to_file; 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); LogsysCategoriesRepository::InsertOne(*m_database, new_category);
} }
@@ -683,19 +673,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
LogInfo("Loaded [{}] log categories", categories.size()); 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());
}
// force override this setting
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_file = static_cast<uint8>(Logs::General);
return this; return this;
} }
@@ -705,110 +682,3 @@ EQEmuLogSys *EQEmuLogSys::SetDatabase(Database *db)
return this; 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;
}
void EQEmuLogSys::DisableMySQLErrorLogs()
{
log_settings[Logs::MySQLError].log_to_file = 0;
log_settings[Logs::MySQLError].log_to_console = 0;
log_settings[Logs::MySQLError].log_to_gmsay = 0;
}
void EQEmuLogSys::EnableMySQLErrorLogs()
{
log_settings[Logs::MySQLError].log_to_file = 1;
log_settings[Logs::MySQLError].log_to_console = 1;
log_settings[Logs::MySQLError].log_to_gmsay = 1;
}
+62 -133
View File
@@ -39,7 +39,8 @@
namespace Logs { namespace Logs {
enum DebugLevel { enum DebugLevel {
General = 1, // 1 - Low-Level general debugging, useful info on single line General = 1, // 1 - Low-Level general debugging, useful info on single line
Detail // 2 - Use this for very chatty logging you want to leave in but don't want on by default 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
}; };
/** /**
@@ -53,7 +54,7 @@ namespace Logs {
AI, AI,
Aggro, Aggro,
Attack, Attack,
DeprecatedCS, // deprecated PacketClientServer,
Combat, Combat,
Commands, Commands,
Crash, Crash,
@@ -64,36 +65,36 @@ namespace Logs {
Inventory, Inventory,
Launcher, Launcher,
Netcode, Netcode,
Normal, // deprecated Normal,
Object, Object,
Pathing, Pathing,
QSServer, // deprecated QSServer,
Quests, Quests,
Rules, Rules,
Skills, Skills,
Spawns, Spawns,
Spells, Spells,
Status, // deprecated Status,
TCPConnection, TCPConnection,
Tasks, Tasks,
Tradeskills, Tradeskills,
Trading, Trading,
Tribute, Tribute,
UCSServer, // deprecated UCSServer,
WebInterfaceServer, // deprecated WebInterfaceServer,
WorldServer, // deprecated WorldServer,
ZoneServer, // deprecated ZoneServer,
MySQLError, MySQLError,
MySQLQuery, MySQLQuery,
Mercenaries, Mercenaries,
QuestDebug, QuestDebug,
DeprecatedSC, // deprecated PacketServerClient,
DeprecatedCSU, // deprecated PacketClientServerUnhandled,
DeprecatedSCD, // deprecated PacketServerClientWithDump,
DeprecatedCSD, // deprecated PacketClientServerWithDump,
Loginserver, // deprecated Loginserver,
ClientLogin, ClientLogin,
HeadlessClient, // deprecated HeadlessClient,
HPUpdate, HPUpdate,
FixZ, FixZ,
Food, Food,
@@ -103,10 +104,10 @@ namespace Logs {
MobAppearance, MobAppearance,
Info, Info,
Warning, Warning,
Critical, // deprecated Critical,
Emergency, // deprecated Emergency,
Alert, // deprecated Alert,
Notice, // deprecated Notice,
AIScanClose, AIScanClose,
AIYellForHelp, AIYellForHelp,
AICastBeneficialClose, AICastBeneficialClose,
@@ -126,19 +127,6 @@ namespace Logs {
DiaWind, DiaWind,
HTTP, HTTP,
Saylink, Saylink,
ChecksumVerification,
CombatRecord,
Hate,
Discord,
Faction,
PacketServerClient,
PacketClientServer,
PacketServerToServer,
Bugs,
QuestErrors,
PlayerEvents,
DataBuckets,
Zoning,
MaxCategoryID /* Don't Remove this */ MaxCategoryID /* Don't Remove this */
}; };
@@ -151,7 +139,7 @@ namespace Logs {
"AI", "AI",
"Aggro", "Aggro",
"Attack", "Attack",
"Deprecated", "Packet :: Client -> Server",
"Combat", "Combat",
"Commands", "Commands",
"Crash", "Crash",
@@ -162,52 +150,52 @@ namespace Logs {
"Inventory", "Inventory",
"Launcher", "Launcher",
"Netcode", "Netcode",
"Normal (Deprecated)", "Normal",
"Object", "Object",
"Pathing", "Pathing",
"QS Server (Deprecated)", "QS Server",
"Quests", "Quests",
"Rules", "Rules",
"Skills", "Skills",
"Spawns", "Spawns",
"Spells", "Spells",
"Status (Deprecated)", "Status",
"TCP Connection", "TCP Connection",
"Tasks", "Tasks",
"Tradeskills", "Tradeskills",
"Trading", "Trading",
"Tribute", "Tribute",
"UCS Server (Deprecated)", "UCS Server",
"Web Interface (Deprecated)", "WebInterface Server",
"World Server (Deprecated)", "World Server",
"Zone Server (Deprecated)", "Zone Server",
"QueryErr", "MySQL Error",
"Query", "MySQL Query",
"Mercenaries", "Mercenaries",
"Quest Debug", "Quest Debug",
"Legacy Packet Logging (Deprecated)", "Packet :: Server -> Client",
"Legacy Packet Logging (Deprecated)", "Packet :: Client -> Server Unhandled",
"Legacy Packet Logging (Deprecated)", "Packet :: Server -> Client (Dump)",
"Legacy Packet Logging (Deprecated)", "Packet :: Client -> Server (Dump)",
"Login Server (Deprecated)", "Login Server",
"Client Login", "Client Login",
"Headless Client (Deprecated)", "Headless Client",
"HP Update", "HP Update",
"FixZ", "FixZ",
"Food", "Food",
"Traps", "Traps",
"NPC Roam Box", "NPC Roam Box",
"NPC Scaling", "NPC Scaling",
"MobAppearance", "Mob Appearance",
"Info", "Info",
"Warning", "Warning",
"Critical (Deprecated)", "Critical",
"Emergency (Deprecated)", "Emergency",
"Alert (Deprecated)", "Alert",
"Notice (Deprecated)", "Notice",
"AI Scan", "AI Scan Close",
"AI Yell", "AI Yell For Help",
"AI CastBeneficial", "AI Cast Beneficial Close",
"AOE Cast", "AOE Cast",
"Entity Management", "Entity Management",
"Flee", "Flee",
@@ -224,19 +212,6 @@ namespace Logs {
"DialogueWindow", "DialogueWindow",
"HTTP", "HTTP",
"Saylink", "Saylink",
"ChecksumVer",
"CombatRecord",
"Hate",
"Discord",
"Faction",
"Packet S->C",
"Packet C->S",
"Packet S->S",
"Bugs",
"QuestErrors",
"PlayerEvents",
"DataBuckets",
"Zoning",
}; };
} }
@@ -244,8 +219,6 @@ namespace Logs {
class Database; class Database;
constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300;
class EQEmuLogSys { class EQEmuLogSys {
public: public:
EQEmuLogSys(); EQEmuLogSys();
@@ -308,19 +281,9 @@ public:
uint8 log_to_file; uint8 log_to_file;
uint8 log_to_console; uint8 log_to_console;
uint8 log_to_gmsay; 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) */ 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 * Internally used memory reference for all log settings per category
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults * These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
@@ -328,84 +291,50 @@ public:
*/ */
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{}; LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
// temporary bucket to re-load after silencing bool file_logs_enabled = false;
LogSettings pre_silence_settings[Logs::LogCategory::MaxCategoryID]{};
struct LogEnabled { int log_platform = 0;
bool log_to_file_enabled; std::string platform_file_name;
bool log_to_console_enabled;
bool log_to_gmsay_enabled;
bool log_to_discord_enabled;
bool log_enabled;
};
LogEnabled GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
bool IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
struct DiscordWebhooks {
int id;
std::string webhook_name;
std::string webhook_url;
};
const DiscordWebhooks *GetDiscordWebhooks() const;
// gmsay // gmsay
uint16 GetGMSayColorFromCategory(uint16 log_category); uint16 GetGMSayColorFromCategory(uint16 log_category);
EQEmuLogSys *SetGMSayHandler(const std::function<void(uint16 log_type, const char *func, const std::string &)>& f) EQEmuLogSys * SetGMSayHandler(std::function<void(uint16 log_type, const std::string &)> f) {
{ on_log_gmsay_hook = f;
m_on_log_gmsay_hook = f;
return this;
}
EQEmuLogSys *SetDiscordHandler(std::function<void(uint16 log_category, int webhook_id, const std::string &)> f)
{
m_on_log_discord_hook = f;
return this; return this;
} }
// console // console
void SetConsoleHandler( void SetConsoleHandler(
std::function<void( std::function<void(
uint16 debug_level,
uint16 log_type, uint16 log_type,
const std::string & const std::string &
)> f )> f
) { m_on_log_console_hook = f; } ) { on_log_console_hook = f; }
void SilenceConsoleLogging(); void SilenceConsoleLogging();
void EnableConsoleLogging(); void EnableConsoleLogging();
// database // database
EQEmuLogSys *SetDatabase(Database *db); EQEmuLogSys *SetDatabase(Database *db);
[[nodiscard]] const std::string &GetLogPath() const;
EQEmuLogSys * SetLogPath(const std::string &log_path);
void DisableMySQLErrorLogs();
void EnableMySQLErrorLogs();
private: private:
// reference to database // reference to database
Database *m_database; Database *m_database;
std::function<void(uint16 log_category, const char *func, 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;
void ProcessConsoleMessage( std::function<void(uint16 log_category, const std::string &)> on_log_gmsay_hook;
uint16 log_category, std::function<void(uint16 debug_level, uint16 log_category, const std::string &)> on_log_console_hook;
const std::string &message,
const char *file, std::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
const char *func, std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
int line uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
);
void ProcessLogWrite(uint16 log_category, const std::string &message); void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message);
void InjectTablesIfNotExist(); void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
bool IsRfc5424LogCategory(uint16 log_category);
}; };
extern EQEmuLogSys LogSys; extern EQEmuLogSys LogSys;
File diff suppressed because it is too large Load Diff
+4 -22
View File
@@ -58,6 +58,10 @@ EQTime::EQTime()
SetCurrentEQTimeOfDay(start, time(0)); SetCurrentEQTimeOfDay(start, time(0));
} }
EQTime::~EQTime()
{
}
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay //getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
//This function was written by the ShowEQ Project. //This function was written by the ShowEQ Project.
//Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to. //Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to.
@@ -200,25 +204,3 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
buf[127] = '\0'; buf[127] = '\0';
str = buf; str = buf;
} }
bool EQTime::IsDayTime() {
TimeOfDay_Struct tod; //Day time is 5am to 6:59pm (14 hours in-game)
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
if (tod.hour >= 5 || tod.hour < 19) {
return true;
}
return false;
}
bool EQTime::IsNightTime() {
TimeOfDay_Struct tod; //Night time is 7pm to 4:59am (10 hours in-game)
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
if (tod.hour >= 19 || tod.hour < 5) {
return true;
}
return false;
}
+1 -3
View File
@@ -18,7 +18,7 @@ public:
//Constructor/destructor //Constructor/destructor
EQTime(TimeOfDay_Struct start_eq, time_t start_real); EQTime(TimeOfDay_Struct start_eq, time_t start_real);
EQTime(); EQTime();
~EQTime() = default; ~EQTime();
//Get functions //Get functions
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); } int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
@@ -28,8 +28,6 @@ public:
uint32 getEQTimeZone() { return timezone; } uint32 getEQTimeZone() { return timezone; }
uint32 getEQTimeZoneHr() { return timezone/60; } uint32 getEQTimeZoneHr() { return timezone/60; }
uint32 getEQTimeZoneMin() { return timezone%60; } uint32 getEQTimeZoneMin() { return timezone%60; }
bool IsDayTime();
bool IsNightTime();
//Set functions //Set functions
int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real); int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
+4 -4
View File
@@ -1,14 +1,14 @@
#pragma once #pragma once
#include <any>
#include <functional> #include <functional>
#include <exception> #include <exception>
#include "event_loop.h" #include "event_loop.h"
#include "../any.h"
namespace EQ { namespace EQ {
class Task class Task
{ {
public: 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(const std::exception&)> RejectFn;
typedef std::function<void()> FinallyFn; typedef std::function<void()> FinallyFn;
typedef std::function<void(ResolveFn, RejectFn)> TaskFn; typedef std::function<void(ResolveFn, RejectFn)> TaskFn;
@@ -19,7 +19,7 @@ namespace EQ {
RejectFn on_catch; RejectFn on_catch;
FinallyFn on_finally; FinallyFn on_finally;
bool has_result; bool has_result;
std::any result; EQ::Any result;
bool has_error; bool has_error;
std::exception error; std::exception error;
}; };
@@ -63,7 +63,7 @@ namespace EQ {
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) { uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
TaskBaton *baton = (TaskBaton*)req->data; 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_error = false;
baton->has_result = true; baton->has_result = true;
baton->result = result; baton->result = result;
+3 -3
View File
@@ -38,7 +38,7 @@ namespace EQ
_running = true; _running = true;
for (size_t i = 0; i < threads; ++i) { for (size_t i = 0; i < threads; ++i) {
_threads.emplace_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this))); _threads.push_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
} }
} }
@@ -60,8 +60,8 @@ namespace EQ
} }
template<typename Fn, typename... Args> template<typename Fn, typename... Args>
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<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::invoke_result<Fn, Args...>::type; using return_type = typename std::result_of<Fn(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>( auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...) std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
File diff suppressed because it is too large Load Diff
@@ -1,214 +0,0 @@
#ifndef EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H
#define EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H
#include <string>
#include "player_events.h"
#include "../repositories/base/base_player_event_logs_repository.h"
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
struct DiscordField {
std::string name;
std::string value;
bool is_inline;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(name),
CEREAL_NVP(value),
cereal::make_nvp("inline", is_inline)
);
}
};
struct DiscordAuthor {
std::string name;
std::string icon_url;
std::string url;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(name),
CEREAL_NVP(icon_url),
CEREAL_NVP(url)
);
}
};
struct DiscordEmbed {
std::vector<DiscordField> fields;
std::string title;
std::string description;
std::string timestamp;
DiscordAuthor author;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(fields),
CEREAL_NVP(title),
CEREAL_NVP(description),
CEREAL_NVP(timestamp),
CEREAL_NVP(author)
);
}
};
struct DiscordWebhook {
std::vector<DiscordEmbed> embeds;
std::string content;
std::string avatar_url;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(embeds),
CEREAL_NVP(avatar_url),
CEREAL_NVP(content)
);
}
};
class PlayerEventDiscordFormatter {
public:
static std::string GetCurrentTimestamp();
static std::string FormatEventSay(const PlayerEvent::PlayerEventContainer &c, const PlayerEvent::SayEvent &e);
static std::string
FormatGMCommand(const PlayerEvent::PlayerEventContainer &c, const PlayerEvent::GMCommandEvent &e);
static void BuildDiscordField(
std::vector<DiscordField> *f,
const std::string &name,
const std::string &value,
bool is_inline = true
);
static void BuildBaseEmbed(
std::vector<DiscordEmbed> *e,
const std::vector<DiscordField> &f,
PlayerEvent::PlayerEventContainer c
);
static std::string FormatWithNodata(const PlayerEvent::PlayerEventContainer &c);
static std::string FormatAAGainedEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::AAGainedEvent &e
);
static std::string FormatAAPurchasedEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::AAPurchasedEvent &e
);
static std::string FormatDeathEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::DeathEvent &e
);
static std::string FormatFishSuccessEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::FishSuccessEvent &e
);
static std::string FormatForageSuccessEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::ForageSuccessEvent &e
);
static std::string FormatDestroyItemEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::DestroyItemEvent &e
);
static std::string FormatDiscoverItemEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::DiscoverItemEvent &e
);
static std::string FormatDroppedItemEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::DroppedItemEvent &e
);
static std::string FormatLevelGainedEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::LevelGainedEvent &e
);
static std::string FormatLevelLostEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::LevelLostEvent &e
);
static std::string FormatLootItemEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::LootItemEvent &e
);
static std::string FormatGroundSpawnPickupEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::GroundSpawnPickupEvent &e
);
static std::string FormatMerchantPurchaseEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::MerchantPurchaseEvent &e
);
static std::string FormatMerchantSellEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::MerchantSellEvent &e
);
static std::string FormatNPCHandinEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::HandinEvent &e
);
static std::string FormatSkillUpEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::SkillUpEvent &e
);
static std::string FormatTaskAcceptEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::TaskAcceptEvent &e
);
static std::string FormatTaskCompleteEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::TaskCompleteEvent &e
);
static std::string FormatTaskUpdateEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::TaskUpdateEvent &e
);
static std::string FormatTradeEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::TradeEvent &e
);
static std::string FormatTraderPurchaseEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::TraderPurchaseEvent &e
);
static std::string FormatTraderSellEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::TraderSellEvent &e
);
static std::string FormatResurrectAcceptEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::ResurrectAcceptEvent &e
);
static std::string FormatSplitMoneyEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::SplitMoneyEvent &e
);
static std::string FormatCombineEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::CombineEvent &e
);
static std::string FormatZoningEvent(
const PlayerEvent::PlayerEventContainer &c,
const PlayerEvent::ZoningEvent &e
);
static DiscordWebhook BuildDiscordWebhook(
const PlayerEvent::PlayerEventContainer &p,
std::vector<DiscordEmbed> &embeds
);
};
#endif //EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H
-702
View File
@@ -1,702 +0,0 @@
#include <cereal/archives/json.hpp>
#include "player_event_logs.h"
#include "player_event_discord_formatter.h"
#include "../platform.h"
#include "../rulesys.h"
const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour
// general initialization routine
void PlayerEventLogs::Init()
{
m_process_batch_events_timer.SetTimer(RuleI(Logging, BatchPlayerEventProcessIntervalSeconds) * 1000);
m_process_retention_truncation_timer.SetTimer(PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL);
ValidateDatabaseConnection();
// initialize settings array
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
m_settings[i].id = i;
m_settings[i].event_name = PlayerEvent::EventName[i];
m_settings[i].event_enabled = 1;
m_settings[i].retention_days = 0;
m_settings[i].discord_webhook_id = 0;
}
SetSettingsDefaults();
// initialize settings from database
auto s = PlayerEventLogSettingsRepository::All(*m_database);
std::vector<int> db{};
db.reserve(s.size());
for (auto &e: s) {
if (e.id >= PlayerEvent::MAX) {
continue;
}
m_settings[e.id] = e;
db.emplace_back(e.id);
}
// insert entries that don't exist in database
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
bool is_in_database = std::find(db.begin(), db.end(), i) != db.end();
bool is_deprecated = Strings::Contains(PlayerEvent::EventName[i], "Deprecated");
bool is_implemented = !Strings::Contains(PlayerEvent::EventName[i], "Unimplemented");
// remove when deprecated
if (is_deprecated && is_in_database) {
LogInfo("[Deprecated] Removing PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i);
PlayerEventLogSettingsRepository::DeleteWhere(*m_database, fmt::format("id = {}", i));
}
// remove when unimplemented if present
if (!is_implemented && is_in_database) {
LogInfo("[Unimplemented] Removing PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i);
PlayerEventLogSettingsRepository::DeleteWhere(*m_database, fmt::format("id = {}", i));
}
bool is_missing_in_database = std::find(db.begin(), db.end(), i) == db.end();
if (is_missing_in_database && is_implemented && !is_deprecated) {
LogInfo(
"[New] PlayerEvent [{}] ({})",
PlayerEvent::EventName[i],
i
);
auto c = PlayerEventLogSettingsRepository::NewEntity();
c.id = i;
c.event_name = PlayerEvent::EventName[i];
c.event_enabled = m_settings[i].event_enabled;
c.retention_days = m_settings[i].retention_days;
PlayerEventLogSettingsRepository::InsertOne(*m_database, c);
}
}
bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld();
bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ();
// on initial boot process truncation
if (processing_in_world || processing_in_qs) {
ProcessRetentionTruncation();
}
}
// set the database object, during initialization
PlayerEventLogs *PlayerEventLogs::SetDatabase(Database *db)
{
m_database = db;
return this;
}
// validates whether the connection is valid or not, used in initialization
bool PlayerEventLogs::ValidateDatabaseConnection()
{
if (!m_database) {
LogError("No database connection");
return false;
}
return true;
}
// determines if the passed in event is enabled or not
// this is used to gate logic or events from firing off
// this is used prior to building the events, we don't want to
// build the events, send them through the stack in a function call
// only to discard them immediately afterwards, very wasteful on resources
// the quest api currently does this
bool PlayerEventLogs::IsEventEnabled(PlayerEvent::EventType event)
{
return m_settings[event].event_enabled ? m_settings[event].event_enabled : false;
}
// this processes any current player events on the queue
void PlayerEventLogs::ProcessBatchQueue()
{
m_batch_queue_lock.lock();
if (m_record_batch_queue.empty()) {
m_batch_queue_lock.unlock();
return;
}
BenchTimer benchmark;
// flush many
PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue);
LogPlayerEventsDetail(
"Processing batch player event log queue of [{}] took [{}]",
m_record_batch_queue.size(),
benchmark.elapsed()
);
// empty
m_record_batch_queue = {};
m_batch_queue_lock.unlock();
}
// adds a player event to the queue
void PlayerEventLogs::AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &log)
{
m_batch_queue_lock.lock();
m_record_batch_queue.emplace_back(log);
m_batch_queue_lock.unlock();
}
// fills common event data in the SendEvent function
void PlayerEventLogs::FillPlayerEvent(
const PlayerEvent::PlayerEvent &p,
PlayerEventLogsRepository::PlayerEventLogs &n
)
{
n.account_id = p.account_id;
n.character_id = p.character_id;
n.zone_id = p.zone_id;
n.instance_id = p.instance_id;
n.x = p.x;
n.y = p.y;
n.z = p.z;
n.heading = p.heading;
}
// builds the dynamic packet used to ship the player event over the wire
// supports serializing the struct so it can be rebuilt on the other end
std::unique_ptr<ServerPacket>
PlayerEventLogs::BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e)
{
EQ::Net::DynamicPacket dyn_pack;
dyn_pack.PutSerialize(0, e);
auto pack_size = sizeof(ServerSendPlayerEvent_Struct) + dyn_pack.Length();
auto pack = std::make_unique<ServerPacket>(ServerOP_PlayerEvent, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerSendPlayerEvent_Struct *>(pack->pBuffer);
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
return pack;
}
const PlayerEventLogSettingsRepository::PlayerEventLogSettings *PlayerEventLogs::GetSettings() const
{
return m_settings;
}
bool PlayerEventLogs::IsEventDiscordEnabled(int32_t event_type_id)
{
// out of bounds check
if (event_type_id >= PlayerEvent::EventType::MAX) {
return false;
}
// make sure webhook id is set
if (m_settings[event_type_id].discord_webhook_id == 0) {
return false;
}
// ensure there is a matching webhook to begin with
if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
return true;
}
return false;
}
std::string PlayerEventLogs::GetDiscordWebhookUrlFromEventType(int32_t event_type_id)
{
// out of bounds check
if (event_type_id >= PlayerEvent::EventType::MAX) {
return "";
}
// make sure webhook id is set
if (m_settings[event_type_id].discord_webhook_id == 0) {
return "";
}
// ensure there is a matching webhook to begin with
if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
return LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url;
}
return "";
}
// GM_COMMAND | [x] Implemented Formatter
// ZONING | [x] Implemented Formatter
// AA_GAIN | [x] Implemented Formatter
// AA_PURCHASE | [x] Implemented Formatter
// FORAGE_SUCCESS | [x] Implemented Formatter
// FORAGE_FAILURE | [x] Implemented Formatter
// FISH_SUCCESS | [x] Implemented Formatter
// FISH_FAILURE | [x] Implemented Formatter
// ITEM_DESTROY | [x] Implemented Formatter
// WENT_ONLINE | [x] Implemented Formatter
// WENT_OFFLINE | [x] Implemented Formatter
// LEVEL_GAIN | [x] Implemented Formatter
// LEVEL_LOSS | [x] Implemented Formatter
// LOOT_ITEM | [x] Implemented Formatter
// MERCHANT_PURCHASE | [x] Implemented Formatter
// MERCHANT_SELL | [x] Implemented Formatter
// GROUP_JOIN | [] Implemented Formatter
// GROUP_LEAVE | [] Implemented Formatter
// RAID_JOIN | [] Implemented Formatter
// RAID_LEAVE | [] Implemented Formatter
// GROUNDSPAWN_PICKUP | [x] Implemented Formatter
// NPC_HANDIN | [x] Implemented Formatter
// SKILL_UP | [x] Implemented Formatter
// TASK_ACCEPT | [x] Implemented Formatter
// TASK_UPDATE | [x] Implemented Formatter
// TASK_COMPLETE | [x] Implemented Formatter
// TRADE | [] Implemented Formatter
// GIVE_ITEM | [] Implemented Formatter
// SAY | [x] Implemented Formatter
// REZ_ACCEPTED | [x] Implemented Formatter
// DEATH | [x] Implemented Formatter
// COMBINE_FAILURE | [x] Implemented Formatter
// COMBINE_SUCCESS | [x] Implemented Formatter
// DROPPED_ITEM | [x] Implemented Formatter
// SPLIT_MONEY | [x] Implemented Formatter
// DZ_JOIN | [] Implemented Formatter
// DZ_LEAVE | [] Implemented Formatter
// TRADER_PURCHASE | [x] Implemented Formatter
// TRADER_SELL | [x] Implemented Formatter
// BANDOLIER_CREATE | [] Implemented Formatter
// BANDOLIER_SWAP | [] Implemented Formatter
// DISCOVER_ITEM | [X] Implemented Formatter
std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e)
{
std::string payload;
switch (e.player_event_log.event_type_id) {
case PlayerEvent::AA_GAIN: {
PlayerEvent::AAGainedEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatAAGainedEvent(e, n);
break;
}
case PlayerEvent::AA_PURCHASE: {
PlayerEvent::AAPurchasedEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatAAPurchasedEvent(e, n);
break;
}
case PlayerEvent::COMBINE_FAILURE:
case PlayerEvent::COMBINE_SUCCESS: {
PlayerEvent::CombineEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatCombineEvent(e, n);
break;
}
case PlayerEvent::DEATH: {
PlayerEvent::DeathEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatDeathEvent(e, n);
break;
}
case PlayerEvent::DISCOVER_ITEM: {
PlayerEvent::DiscoverItemEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatDiscoverItemEvent(e, n);
break;
}
case PlayerEvent::DROPPED_ITEM: {
PlayerEvent::DroppedItemEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatDroppedItemEvent(e, n);
break;
}
case PlayerEvent::FISH_FAILURE:
case PlayerEvent::FORAGE_FAILURE:
case PlayerEvent::WENT_ONLINE:
case PlayerEvent::WENT_OFFLINE: {
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
break;
}
case PlayerEvent::FISH_SUCCESS: {
PlayerEvent::FishSuccessEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatFishSuccessEvent(e, n);
break;
}
case PlayerEvent::FORAGE_SUCCESS: {
PlayerEvent::ForageSuccessEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatForageSuccessEvent(e, n);
break;
}
case PlayerEvent::ITEM_DESTROY: {
PlayerEvent::DestroyItemEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatDestroyItemEvent(e, n);
break;
}
case PlayerEvent::LEVEL_GAIN: {
PlayerEvent::LevelGainedEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatLevelGainedEvent(e, n);
break;
}
case PlayerEvent::LEVEL_LOSS: {
PlayerEvent::LevelLostEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatLevelLostEvent(e, n);
break;
}
case PlayerEvent::LOOT_ITEM: {
PlayerEvent::LootItemEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatLootItemEvent(e, n);
break;
}
case PlayerEvent::GROUNDSPAWN_PICKUP: {
PlayerEvent::GroundSpawnPickupEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatGroundSpawnPickupEvent(e, n);
break;
}
case PlayerEvent::NPC_HANDIN: {
PlayerEvent::HandinEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatNPCHandinEvent(e, n);
break;
}
case PlayerEvent::SAY: {
PlayerEvent::SayEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatEventSay(e, n);
break;
}
case PlayerEvent::GM_COMMAND: {
PlayerEvent::GMCommandEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatGMCommand(e, n);
break;
}
case PlayerEvent::SKILL_UP: {
PlayerEvent::SkillUpEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatSkillUpEvent(e, n);
break;
}
case PlayerEvent::SPLIT_MONEY: {
PlayerEvent::SplitMoneyEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatSplitMoneyEvent(e, n);
break;
}
case PlayerEvent::TASK_ACCEPT: {
PlayerEvent::TaskAcceptEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatTaskAcceptEvent(e, n);
break;
}
case PlayerEvent::TASK_COMPLETE: {
PlayerEvent::TaskCompleteEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatTaskCompleteEvent(e, n);
break;
}
case PlayerEvent::TASK_UPDATE: {
PlayerEvent::TaskUpdateEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatTaskUpdateEvent(e, n);
break;
}
case PlayerEvent::TRADE: {
PlayerEvent::TradeEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatTradeEvent(e, n);
break;
}
case PlayerEvent::TRADER_PURCHASE: {
PlayerEvent::TraderPurchaseEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatTraderPurchaseEvent(e, n);
break;
}
case PlayerEvent::TRADER_SELL: {
PlayerEvent::TraderSellEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatTraderSellEvent(e, n);
break;
}
case PlayerEvent::REZ_ACCEPTED: {
PlayerEvent::ResurrectAcceptEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatResurrectAcceptEvent(e, n);
break;
}
case PlayerEvent::MERCHANT_PURCHASE: {
PlayerEvent::MerchantPurchaseEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatMerchantPurchaseEvent(e, n);
break;
}
case PlayerEvent::MERCHANT_SELL: {
PlayerEvent::MerchantSellEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatMerchantSellEvent(e, n);
break;
}
case PlayerEvent::ZONING: {
PlayerEvent::ZoningEvent n{};
std::stringstream ss;
{
ss << e.player_event_log.event_data;
cereal::JSONInputArchive ar(ss);
n.serialize(ar);
}
payload = PlayerEventDiscordFormatter::FormatZoningEvent(e, n);
break;
}
default: {
LogInfo(
"Player event [{}] ({}) Discord formatter not implemented",
e.player_event_log.event_type_name,
e.player_event_log.event_type_id
);
}
}
return payload;
}
// general process function, used in world or QS depending on rule Logging:PlayerEventsQSProcess
void PlayerEventLogs::Process()
{
if (m_process_batch_events_timer.Check() || m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) {
ProcessBatchQueue();
}
if (m_process_retention_truncation_timer.Check()) {
ProcessRetentionTruncation();
}
}
void PlayerEventLogs::ProcessRetentionTruncation()
{
LogInfo("Running truncation");
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
if (m_settings[i].retention_days > 0) {
int deleted_count = PlayerEventLogsRepository::DeleteWhere(
*m_database,
fmt::format(
"event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)",
i,
m_settings[i].retention_days
)
);
if (deleted_count > 0) {
LogInfo(
"Truncated [{}] events of type [{}] ({}) older than [{}] days",
deleted_count,
PlayerEvent::EventName[i],
i,
m_settings[i].retention_days
);
}
}
}
}
void PlayerEventLogs::ReloadSettings()
{
for (auto &e: PlayerEventLogSettingsRepository::All(*m_database)) {
m_settings[e.id] = e;
}
}
const int32_t RETENTION_DAYS_DEFAULT = 7;
void PlayerEventLogs::SetSettingsDefaults()
{
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
m_settings[PlayerEvent::ZONING].event_enabled = 1;
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
m_settings[PlayerEvent::TRADE].event_enabled = 1;
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
m_settings[PlayerEvent::SAY].event_enabled = 0;
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
m_settings[PlayerEvent::DEATH].event_enabled = 1;
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
}
}
-85
View File
@@ -1,85 +0,0 @@
#ifndef EQEMU_PLAYER_EVENT_LOGS_H
#define EQEMU_PLAYER_EVENT_LOGS_H
#include "../repositories/player_event_log_settings_repository.h"
#include "player_events.h"
#include "../servertalk.h"
#include "../repositories/player_event_logs_repository.h"
#include "../timer.h"
#include "../json/json_archive_single_line.h"
#include <cereal/archives/json.hpp>
#include <mutex>
class PlayerEventLogs {
public:
void Init();
void ReloadSettings();
PlayerEventLogs *SetDatabase(Database *db);
bool ValidateDatabaseConnection();
bool IsEventEnabled(PlayerEvent::EventType event);
void Process();
// batch queue
void AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &logs);
// main event record generic function
// can ingest any struct event types
template<typename T>
std::unique_ptr<ServerPacket> RecordEvent(
PlayerEvent::EventType t,
const PlayerEvent::PlayerEvent &p,
T e
)
{
auto n = PlayerEventLogsRepository::NewEntity();
FillPlayerEvent(p, n);
n.event_type_id = t;
std::stringstream ss;
{
cereal::JSONOutputArchiveSingleLine ar(ss);
e.serialize(ar);
}
n.event_type_name = PlayerEvent::EventName[t];
n.event_data = Strings::Contains(ss.str(), "noop") ? "{}" : ss.str();
n.created_at = std::time(nullptr);
auto c = PlayerEvent::PlayerEventContainer{
.player_event = p,
.player_event_log = n
};
return BuildPlayerEventPacket(c);
}
[[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const;
bool IsEventDiscordEnabled(int32_t event_type_id);
std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id);
static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e);
private:
Database *m_database; // reference to database
PlayerEventLogSettingsRepository::PlayerEventLogSettings m_settings[PlayerEvent::EventType::MAX]{};
// batch queue is used to record events in batch
std::vector<PlayerEventLogsRepository::PlayerEventLogs> m_record_batch_queue{};
static void FillPlayerEvent(const PlayerEvent::PlayerEvent &p, PlayerEventLogsRepository::PlayerEventLogs &n);
static std::unique_ptr<ServerPacket>
BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e);
// timers
Timer m_process_batch_events_timer; // events processing timer
Timer m_process_retention_truncation_timer; // timer for truncating events based on retention settings
// processing
std::mutex m_batch_queue_lock{};
void ProcessBatchQueue();
void ProcessRetentionTruncation();
void SetSettingsDefaults();
};
extern PlayerEventLogs player_event_logs;
#endif //EQEMU_PLAYER_EVENT_LOGS_H
-971
View File
@@ -1,971 +0,0 @@
#ifndef EQEMU_PLAYER_EVENTS_H
#define EQEMU_PLAYER_EVENTS_H
#include <string>
#include <cereal/cereal.hpp>
#include "../types.h"
#include "../repositories/player_event_logs_repository.h"
namespace PlayerEvent {
enum EventType {
GM_COMMAND = 1,
ZONING,
AA_GAIN,
AA_PURCHASE,
FORAGE_SUCCESS,
FORAGE_FAILURE,
FISH_SUCCESS,
FISH_FAILURE,
ITEM_DESTROY,
WENT_ONLINE,
WENT_OFFLINE,
LEVEL_GAIN,
LEVEL_LOSS,
LOOT_ITEM,
MERCHANT_PURCHASE,
MERCHANT_SELL,
GROUP_JOIN, // unimplemented
GROUP_LEAVE, // unimplemented
RAID_JOIN, // unimplemented
RAID_LEAVE, // unimplemented
GROUNDSPAWN_PICKUP,
NPC_HANDIN,
SKILL_UP,
TASK_ACCEPT,
TASK_UPDATE,
TASK_COMPLETE,
TRADE,
GIVE_ITEM, // unimplemented
SAY,
REZ_ACCEPTED,
DEATH,
COMBINE_FAILURE,
COMBINE_SUCCESS,
DROPPED_ITEM,
SPLIT_MONEY,
DZ_JOIN, // unimplemented
DZ_LEAVE, // unimplemented
TRADER_PURCHASE,
TRADER_SELL,
BANDOLIER_CREATE, // unimplemented
BANDOLIER_SWAP, // unimplemented
DISCOVER_ITEM,
POSSIBLE_HACK,
KILLED_NPC,
KILLED_NAMED_NPC,
KILLED_RAID_NPC,
ITEM_CREATION,
MAX // dont remove
};
// Don't ever remove items, even if they are deprecated
// If event is deprecated just tag (Deprecated) in the name
// If event is unimplemented just tag (Unimplemented) in the name
// Events don't get saved to the database if unimplemented or deprecated
// Events tagged as deprecated will get automatically removed
static const char *EventName[PlayerEvent::MAX] = {
"None",
"GM Command",
"Zoning",
"AA Gain",
"AA Purchase",
"Forage Success",
"Forage Failure",
"Fish Success",
"Fish Failure",
"Item Destroy",
"Went Online",
"Went Offline",
"Level Gain",
"Level Loss",
"Loot Item",
"Merchant Purchase",
"Merchant Sell",
"Group Join (Unimplemented)",
"Group Leave (Unimplemented)",
"Raid Join (Unimplemented)",
"Raid Leave (Unimplemented)",
"Groundspawn Pickup",
"NPC Handin",
"Skill Up",
"Task Accept",
"Task Update",
"Task Complete",
"Trade",
"Given Item (Unimplemented)",
"Say",
"Rez Accepted",
"Death",
"Combine Failure",
"Combine Success",
"Dropped Item",
"Split Money",
"DZ Join (Unimplemented)",
"DZ Leave (Unimplemented)",
"Trader Purchase",
"Trader Sell",
"Bandolier Create (Unimplemented)",
"Bandolier Swap (Unimplemented)",
"Discover Item",
"Possible Hack",
"Killed NPC",
"Killed Named NPC",
"Killed Raid NPC",
"Item Creation"
};
// Generic struct used by all events
struct PlayerEvent {
int64 account_id;
std::string account_name;
int64 character_id;
std::string character_name;
int64 guild_id;
std::string guild_name;
int zone_id;
std::string zone_short_name;
std::string zone_long_name;
int instance_id;
float x;
float y;
float z;
float heading;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(account_id),
CEREAL_NVP(account_name),
CEREAL_NVP(character_id),
CEREAL_NVP(character_name),
CEREAL_NVP(guild_id),
CEREAL_NVP(guild_name),
CEREAL_NVP(zone_id),
CEREAL_NVP(zone_short_name),
CEREAL_NVP(zone_long_name),
CEREAL_NVP(instance_id),
CEREAL_NVP(x),
CEREAL_NVP(y),
CEREAL_NVP(z),
CEREAL_NVP(heading)
);
}
};
// contains metadata in use for things like log/discord formatters
// along with the actual event to be persisted
struct PlayerEventContainer {
PlayerEvent player_event;
PlayerEventLogsRepository::PlayerEventLogs player_event_log;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(player_event),
CEREAL_NVP(player_event_log)
);
}
};
// used in events with no extra data
struct EmptyEvent {
std::string noop; // noop, gets discard upstream
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(noop)
);
}
};
// used in Trade event
struct ItemCreationEvent {
int64 item_id;
std::string item_name;
uint16 to_slot;
int16 charges;
uint32 aug1;
uint32 aug2;
uint32 aug3;
uint32 aug4;
uint32 aug5;
uint32 aug6;
bool attuned;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(to_slot),
CEREAL_NVP(charges),
CEREAL_NVP(aug1),
CEREAL_NVP(aug2),
CEREAL_NVP(aug3),
CEREAL_NVP(aug4),
CEREAL_NVP(aug5),
CEREAL_NVP(aug6),
CEREAL_NVP(attuned)
);
}
};
// used in Trade event
struct TradeItem {
int64 item_id;
std::string item_name;
int32 slot;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(slot)
);
}
};
// used in Trade event
class TradeItemEntry {
public:
uint16 slot;
uint32 item_id;
std::string item_name;
uint16 charges;
uint32 aug_1_item_id;
std::string aug_1_item_name;
uint32 aug_2_item_id;
std::string aug_2_item_name;
uint32 aug_3_item_id;
std::string aug_3_item_name;
uint32 aug_4_item_id;
std::string aug_4_item_name;
uint32 aug_5_item_id;
std::string aug_5_item_name;
uint32 aug_6_item_id;
std::string aug_6_item_name;
bool in_bag;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(slot),
CEREAL_NVP(item_id),
CEREAL_NVP(charges),
CEREAL_NVP(aug_1_item_id),
CEREAL_NVP(aug_2_item_id),
CEREAL_NVP(aug_3_item_id),
CEREAL_NVP(aug_4_item_id),
CEREAL_NVP(aug_5_item_id),
CEREAL_NVP(in_bag)
);
}
};
/**
* Events
*/
struct Money {
int32 platinum;
int32 gold;
int32 silver;
int32 copper;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(platinum),
CEREAL_NVP(gold),
CEREAL_NVP(silver),
CEREAL_NVP(copper)
);
}
};
struct TradeEvent {
uint32 character_1_id;
std::string character_1_name;
uint32 character_2_id;
std::string character_2_name;
Money character_1_give_money;
Money character_2_give_money;
std::vector<TradeItemEntry> character_1_give_items;
std::vector<TradeItemEntry> character_2_give_items;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(character_1_id),
CEREAL_NVP(character_1_name),
CEREAL_NVP(character_2_id),
CEREAL_NVP(character_2_name),
CEREAL_NVP(character_1_give_money),
CEREAL_NVP(character_2_give_money),
CEREAL_NVP(character_1_give_items),
CEREAL_NVP(character_2_give_items)
);
}
};
struct GMCommandEvent {
std::string message;
std::string target;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(message),
CEREAL_NVP(target)
);
}
};
struct ZoningEvent {
std::string from_zone_long_name;
std::string from_zone_short_name;
int32 from_zone_id;
int32 from_instance_id;
int32 from_instance_version;
std::string to_zone_long_name;
std::string to_zone_short_name;
int32 to_zone_id;
int32 to_instance_id;
int32 to_instance_version;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(from_zone_long_name),
CEREAL_NVP(from_zone_short_name),
CEREAL_NVP(from_zone_id),
CEREAL_NVP(from_instance_id),
CEREAL_NVP(from_instance_version),
CEREAL_NVP(to_zone_long_name),
CEREAL_NVP(to_zone_short_name),
CEREAL_NVP(to_zone_id),
CEREAL_NVP(to_instance_id),
CEREAL_NVP(to_instance_version)
);
}
};
struct AAGainedEvent {
uint32 aa_gained;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(CEREAL_NVP(aa_gained));
}
};
struct AAPurchasedEvent {
uint32 aa_id;
int32 aa_cost;
int32 aa_previous_id;
int32 aa_next_id;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(aa_id),
CEREAL_NVP(aa_cost),
CEREAL_NVP(aa_previous_id),
CEREAL_NVP(aa_next_id)
);
}
};
struct ForageSuccessEvent {
uint32 item_id;
std::string item_name;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name)
);
}
};
struct FishSuccessEvent {
uint32 item_id;
std::string item_name;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name)
);
}
};
struct DestroyItemEvent {
uint32 item_id;
std::string item_name;
int16 charges;
std::string reason;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(reason),
CEREAL_NVP(charges)
);
}
};
struct LevelGainedEvent {
uint32 from_level;
uint8 to_level;
int levels_gained;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(from_level),
CEREAL_NVP(to_level),
CEREAL_NVP(levels_gained)
);
}
};
struct LevelLostEvent {
uint32 from_level;
uint8 to_level;
int levels_lost;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(from_level),
CEREAL_NVP(to_level),
CEREAL_NVP(levels_lost)
);
}
};
struct LootItemEvent {
uint32 item_id;
std::string item_name;
int16 charges;
uint32 npc_id;
std::string corpse_name;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(charges),
CEREAL_NVP(npc_id),
CEREAL_NVP(corpse_name)
);
}
};
struct MerchantPurchaseEvent {
uint32 npc_id;
std::string merchant_name;
uint32 merchant_type;
uint32 item_id;
std::string item_name;
int16 charges;
uint32 cost;
uint32 alternate_currency_id;
uint64 player_money_balance;
uint64 player_currency_balance;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(npc_id),
CEREAL_NVP(merchant_name),
CEREAL_NVP(merchant_type),
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(charges),
CEREAL_NVP(cost),
CEREAL_NVP(alternate_currency_id),
CEREAL_NVP(player_money_balance),
CEREAL_NVP(player_currency_balance)
);
}
};
struct MerchantSellEvent {
uint32 npc_id;
std::string merchant_name;
uint32 merchant_type;
uint32 item_id;
std::string item_name;
int16 charges;
uint32 cost;
uint32 alternate_currency_id;
uint64 player_money_balance;
uint64 player_currency_balance;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(npc_id),
CEREAL_NVP(merchant_name),
CEREAL_NVP(merchant_type),
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(charges),
CEREAL_NVP(cost),
CEREAL_NVP(alternate_currency_id),
CEREAL_NVP(player_money_balance),
CEREAL_NVP(player_currency_balance)
);
}
};
struct SkillUpEvent {
uint32 skill_id;
int value;
int16 max_skill;
std::string against_who;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(skill_id),
CEREAL_NVP(value),
CEREAL_NVP(max_skill),
CEREAL_NVP(against_who)
);
}
};
struct TaskAcceptEvent {
uint32 npc_id;
std::string npc_name;
uint32 task_id;
std::string task_name;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(npc_id),
CEREAL_NVP(npc_name),
CEREAL_NVP(task_id),
CEREAL_NVP(task_name)
);
}
};
struct TaskUpdateEvent {
uint32 task_id;
std::string task_name;
uint32 activity_id;
uint32 done_count;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(task_id),
CEREAL_NVP(task_name),
CEREAL_NVP(activity_id),
CEREAL_NVP(done_count)
);
}
};
struct TaskCompleteEvent {
uint32 task_id;
std::string task_name;
uint32 activity_id;
uint32 done_count;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(task_id),
CEREAL_NVP(task_name),
CEREAL_NVP(activity_id),
CEREAL_NVP(done_count)
);
}
};
struct GroundSpawnPickupEvent {
uint32 item_id;
std::string item_name;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name)
);
}
};
struct SayEvent {
std::string message;
std::string target;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(message),
CEREAL_NVP(target)
);
}
};
struct ResurrectAcceptEvent {
std::string resurrecter_name;
std::string spell_name;
uint32 spell_id;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(resurrecter_name),
CEREAL_NVP(spell_name),
CEREAL_NVP(spell_id)
);
}
};
struct CombineEvent {
uint32 recipe_id;
std::string recipe_name;
uint32 made_count;
uint32 tradeskill_id;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(recipe_id),
CEREAL_NVP(recipe_name),
CEREAL_NVP(made_count),
CEREAL_NVP(tradeskill_id)
);
}
};
struct DroppedItemEvent {
uint32 item_id;
std::string item_name;
int16 slot_id;
uint32 charges;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(slot_id),
CEREAL_NVP(charges)
);
}
};
struct DeathEvent {
uint32 killer_id;
std::string killer_name;
int64 damage;
uint32 spell_id;
std::string spell_name;
int skill_id;
std::string skill_name;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(killer_id),
CEREAL_NVP(killer_name),
CEREAL_NVP(damage),
CEREAL_NVP(spell_id),
CEREAL_NVP(spell_name),
CEREAL_NVP(skill_id),
CEREAL_NVP(skill_name)
);
}
};
struct SplitMoneyEvent {
uint32 copper;
uint32 silver;
uint32 gold;
uint32 platinum;
uint64 player_money_balance;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(copper),
CEREAL_NVP(silver),
CEREAL_NVP(gold),
CEREAL_NVP(platinum),
CEREAL_NVP(player_money_balance)
);
}
};
struct TraderPurchaseEvent {
uint32 item_id;
std::string item_name;
uint32 trader_id;
std::string trader_name;
uint32 price;
uint32 charges;
uint32 total_cost;
uint64 player_money_balance;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(trader_id),
CEREAL_NVP(trader_name),
CEREAL_NVP(price),
CEREAL_NVP(charges),
CEREAL_NVP(total_cost),
CEREAL_NVP(player_money_balance)
);
}
};
struct TraderSellEvent {
uint32 item_id;
std::string item_name;
uint32 buyer_id;
std::string buyer_name;
uint32 price;
uint32 charges;
uint32 total_cost;
uint64 player_money_balance;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(buyer_id),
CEREAL_NVP(buyer_name),
CEREAL_NVP(price),
CEREAL_NVP(charges),
CEREAL_NVP(total_cost),
CEREAL_NVP(player_money_balance)
);
}
};
struct DiscoverItemEvent {
uint32 item_id;
std::string item_name;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name)
);
}
};
class HandinEntry {
public:
uint32 item_id;
std::string item_name;
uint16 charges;
bool attuned;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(charges),
CEREAL_NVP(attuned)
);
}
};
class HandinMoney {
public:
uint32 copper;
uint32 silver;
uint32 gold;
uint32 platinum;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(copper),
CEREAL_NVP(silver),
CEREAL_NVP(gold),
CEREAL_NVP(platinum)
);
}
};
struct HandinEvent {
uint32 npc_id;
std::string npc_name;
std::vector<HandinEntry> handin_items;
HandinMoney handin_money;
std::vector<HandinEntry> return_items;
HandinMoney return_money;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(npc_id),
CEREAL_NVP(npc_name),
CEREAL_NVP(handin_items),
CEREAL_NVP(handin_money),
CEREAL_NVP(return_items),
CEREAL_NVP(return_money)
);
}
};
struct PossibleHackEvent {
std::string message;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(message)
);
}
};
struct KilledNPCEvent {
uint32 npc_id;
std::string npc_name;
uint32 combat_time_seconds;
uint64 total_damage_per_second_taken;
uint64 total_heal_per_second_taken;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(npc_id),
CEREAL_NVP(npc_name),
CEREAL_NVP(combat_time_seconds),
CEREAL_NVP(total_damage_per_second_taken),
CEREAL_NVP(total_heal_per_second_taken)
);
}
};
}
#endif //EQEMU_PLAYER_EVENTS_H
#define RecordPlayerEventLog(event_type, event_data) do {\
if (player_event_logs.IsEventEnabled(event_type)) {\
worldserver.SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
GetPlayerEvent(),\
event_data\
).get()\
);\
}\
} while (0)
#define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\
if (player_event_logs.IsEventEnabled(event_type)) {\
worldserver.SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
(c)->GetPlayerEvent(),\
event_data\
).get()\
);\
}\
} while (0)
+1 -1
View File
@@ -19,7 +19,7 @@
*/ */
#include "expedition_lockout_timer.h" #include "expedition_lockout_timer.h"
#include "../common/strings.h" #include "../common/string_util.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/util/uuid.h" #include "../common/util/uuid.h"
#include <fmt/format.h> #include <fmt/format.h>
+24 -24
View File
@@ -20,31 +20,31 @@
#include "races.h" #include "races.h"
#include "rulesys.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: case FACTION_ALLY:
return "Ally"; return ("Ally");
case FACTION_WARMLY: case FACTION_WARMLY:
return "Warmly"; return ("Warmly");
case FACTION_KINDLY: case FACTION_KINDLY:
return "Kindly"; return ("Kindly");
case FACTION_AMIABLY: case FACTION_AMIABLE:
return "Amiably"; return ("Amiable");
case FACTION_INDIFFERENTLY: case FACTION_INDIFFERENT:
return "Indifferently"; return ("Indifferent");
case FACTION_APPREHENSIVELY: case FACTION_APPREHENSIVE:
return "Apprehensively"; return ("Apprehensive");
case FACTION_DUBIOUSLY: case FACTION_DUBIOUS:
return "Dubiously"; return ("Dubious");
case FACTION_THREATENINGLY: case FACTION_THREATENLY:
return "Threateningly"; return ("Threatenly");
case FACTION_SCOWLS: case FACTION_SCOWLS:
return "Scowls"; return ("Scowls, ready to attack.");
default: default:
break; break;
} }
return "Unknown"; return ("Unknown Faction Con");
} }
@@ -70,19 +70,19 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
return FACTION_KINDLY; return FACTION_KINDLY;
} }
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) { if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) {
return FACTION_AMIABLY; return FACTION_AMIABLE;
} }
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) { if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) {
return FACTION_INDIFFERENTLY; return FACTION_INDIFFERENT;
} }
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) { if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) {
return FACTION_APPREHENSIVELY; return FACTION_APPREHENSIVE;
} }
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) { if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) {
return FACTION_DUBIOUSLY; return FACTION_DUBIOUS;
} }
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) { if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) {
return FACTION_THREATENINGLY; return FACTION_THREATENLY;
} }
return FACTION_SCOWLS; return FACTION_SCOWLS;
} }
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
// TODO: add more values // TODO: add more values
switch (r1) { switch (r1) {
case DARK_ELF: case DARK_ELF:
if (r2 == RACE_NERIAK_CITIZEN_77) { if (r2 == 77) {
return true; return true;
} }
break; break;
case BARBARIAN: case BARBARIAN:
if (r2 == RACE_HALAS_CITIZEN_90) { if (r2 == 90) {
return true; return true;
} }
} }
+6 -23
View File
@@ -27,13 +27,13 @@ enum FACTION_VALUE {
FACTION_ALLY = 1, FACTION_ALLY = 1,
FACTION_WARMLY = 2, FACTION_WARMLY = 2,
FACTION_KINDLY = 3, FACTION_KINDLY = 3,
FACTION_AMIABLY = 4, FACTION_AMIABLE = 4,
FACTION_INDIFFERENTLY = 5, FACTION_INDIFFERENT = 5,
FACTION_APPREHENSIVELY = 6, FACTION_APPREHENSIVE = 6,
FACTION_DUBIOUSLY = 7, FACTION_DUBIOUS = 7,
FACTION_THREATENINGLY = 8, FACTION_THREATENLY = 8,
FACTION_SCOWLS = 9 FACTION_SCOWLS = 9
}; };
@@ -75,23 +75,6 @@ struct NPCFaction
uint8 temp; uint8 temp;
}; };
// Faction Associations give a much more live like faction system const char *FactionValueToString(FACTION_VALUE fv);
// 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);
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value); FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
#endif #endif
+21 -5
View File
@@ -132,7 +132,7 @@ enum { //reuse times
InstillDoubtReuseTime = 9, InstillDoubtReuseTime = 9,
FishingReuseTime = 11, FishingReuseTime = 11,
ForagingReuseTime = 50, ForagingReuseTime = 50,
MendReuseTime = 360, MendReuseTime = 290,
BashReuseTime = 5, BashReuseTime = 5,
BackstabReuseTime = 9, BackstabReuseTime = 9,
KickReuseTime = 5, KickReuseTime = 5,
@@ -204,7 +204,7 @@ enum { //some random constants
#define MIN_LEVEL_ALCHEMY 25 #define MIN_LEVEL_ALCHEMY 25
//chance ratio that a //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 //max factions per npc faction list
#define MAX_NPC_FACTIONS 20 #define MAX_NPC_FACTIONS 20
@@ -218,14 +218,14 @@ enum { //some random constants
#define HARD_LEVEL_CAP 127 #define HARD_LEVEL_CAP 127
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc) //the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
#define USE_NPC_RANGE2 40000 //arbitrary right now #define USE_NPC_RANGE2 200*200 //arbitrary right now
// Squared range for rampage 75.0 * 75.0 for now // Squared range for rampage 75.0 * 75.0 for now
#define NPC_RAMPAGE_RANGE2 5625.0f #define NPC_RAMPAGE_RANGE2 5625.0f
//the formula for experience for killing a mob. //the formula for experience for killing a mob.
//level is the only valid variable to use //level is the only valid variable to use
#define EXP_FORMULA (level * level * 75 * 35 / 10) #define EXP_FORMULA level*level*75*35/10
#define HIGHEST_AA_VALUE 35 #define HIGHEST_AA_VALUE 35
@@ -244,14 +244,30 @@ enum {
minStatusToUseGMCommands = 80, minStatusToUseGMCommands = 80,
minStatusToKick = 150, minStatusToKick = 150,
minStatusToAvoidFalling = 100, minStatusToAvoidFalling = 100,
minStatusToHaveInvalidSpells = 80,
minStatusToHaveInvalidSkills = 80,
minStatusToIgnoreZoneFlags = 80, minStatusToIgnoreZoneFlags = 80,
minStatusToSeeOthersZoneFlags = 80, minStatusToSeeOthersZoneFlags = 80,
minStatusToEditOtherGuilds = 80, minStatusToEditOtherGuilds = 80,
commandMovecharSelfOnly = 80, //below this == only self move allowed commandMovecharSelfOnly = 80, //below this == only self move allowed
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
commandZoneToSpecials = 80, //zone to cshome, out of load zones
commandToggleAI = 250, //can turn NPC AI on and off
commandCastSpecials = 100, //can cast special spells commandCastSpecials = 100, //can cast special spells
commandInstacast = 100, //insta-cast all #casted spells
commandLevelAboveCap = 100, //can #level players above level cap
commandLevelNPCAboveCap = 100, //can #level NPCs above level cap
commandSetSkillsOther = 100, //ability to setskills on others
commandRaceOthers = 100, //ability to #race on others
commandGenderOthers = 100, //ability to #gender on others
commandTextureOthers = 100, //ability to #texture on others
commandDoAnimOthers = 100, //can #doanim on others commandDoAnimOthers = 100, //can #doanim on others
commandLockZones = 101, //can lock or unlock zones
commandEditPlayerCorpses = 150, //can Edit Player Corpses commandEditPlayerCorpses = 150, //can Edit Player Corpses
commandChangeFlags = 200, //ability to set/refresh flags
commandBanPlayers = 100, //can set bans on players
commandChangeDatarate = 201, //edit client's data rate
commandZoneToCoords = 0, //can #zone with coords
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
commandInvSnapshot = 150 //ability to clear/restore snapshots commandInvSnapshot = 150 //ability to clear/restore snapshots
}; };
@@ -279,7 +295,7 @@ Developer configuration
#define COMMON_PROFILE #define COMMON_PROFILE
#define PROFILE_DUMP_TIME 180 #define PROFILE_DUMP_TIME 3*60
#endif //EQPROFILE #endif //EQPROFILE
-112
View File
@@ -1,112 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* 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
*
*/
#include <fstream>
#include "file.h"
#ifdef _WINDOWS
#include <direct.h>
#include <conio.h>
#include <iostream>
#include <dos.h>
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#include <sys/stat.h>
#endif
#include <fmt/format.h>
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
/**
* @param name
* @return
*/
bool File::Exists(const std::string &name)
{
return fs::exists(fs::path{name});
}
/**
* @param directory_name
*/
void File::Makedir(const std::string &directory_name)
{
try {
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
}
catch (const fs::filesystem_error &ex) {
std::cout << "Failed to create directory: " << directory_name << std::endl;
std::cout << ex.what() << std::endl;
}
}
std::string File::FindEqemuConfigPath()
{
if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) {
return File::GetCwd();
}
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();
}
FileContentsResult File::GetContents(const std::string &file_name)
{
std::string error;
std::ifstream f;
f.open(file_name);
std::string line;
std::string lines;
if (f.is_open()) {
while (f) {
std::getline(f, line);
lines += line + "\n";
}
}
else {
error = fmt::format("Couldn't open file [{}]", file_name);
}
return FileContentsResult{
.contents = lines,
.error = error,
};
}
+67
View File
@@ -0,0 +1,67 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* 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
*
*/
#include <fstream>
#include "file_util.h"
#ifdef _WINDOWS
#include <direct.h>
#include <conio.h>
#include <iostream>
#include <dos.h>
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#include <sys/stat.h>
#endif
/**
* @param name
* @return
*/
bool FileUtil::exists(const std::string &name)
{
std::ifstream f(name.c_str());
return f.good();
}
/**
* @param directory_name
*/
void FileUtil::mkdir(const std::string& directory_name)
{
#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;
}
::mkdir(directory_name.c_str(), 0755);
#endif
}
+6 -18
View File
@@ -18,27 +18,15 @@
* *
*/ */
#ifndef EQEMU_FILE_H #ifndef EQEMU_FILE_UTIL_H
#define EQEMU_FILE_H #define EQEMU_FILE_UTIL_H
#include <filesystem>
namespace fs = std::filesystem; class FileUtil {
struct FileContentsResult {
std::string contents;
std::string error;
};
class File {
public: public:
static bool Exists(const std::string &name); static bool exists(const std::string &name);
static void Makedir(const std::string& directory_name); static void mkdir(const std::string& directory_name);
static FileContentsResult GetContents(const std::string &file_name);
static std::string FindEqemuConfigPath();
static std::string GetCwd();
}; };
bool Exists(const std::string& name);
#endif //EQEMU_FILE_H #endif //EQEMU_FILE_UTIL_H
+42 -86
View File
@@ -20,7 +20,7 @@
#include "database.h" #include "database.h"
//#include "misc_functions.h" //#include "misc_functions.h"
#include "strings.h" #include "string_util.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@@ -61,11 +61,9 @@ bool BaseGuildManager::LoadGuilds() {
} }
for (auto row=results.begin();row!=results.end();++row) for (auto row=results.begin();row!=results.end();++row)
_CreateGuild(Strings::ToUnsignedInt(row[0]), row[1], Strings::ToUnsignedInt(row[2]), Strings::ToUnsignedInt(row[3]), row[4], row[5], row[6], row[7]); _CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]);
LogInfo("Loaded [{}] Guilds", Strings::Commify(std::to_string(results.RowCount()))); 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); results = m_db->QueryDatabase(query);
if (!results.Success()) if (!results.Success())
@@ -75,8 +73,8 @@ bool BaseGuildManager::LoadGuilds() {
for (auto row=results.begin();row!=results.end();++row) for (auto row=results.begin();row!=results.end();++row)
{ {
uint32 guild_id = Strings::ToUnsignedInt(row[0]); uint32 guild_id = atoi(row[0]);
uint8 rankn = Strings::ToUnsignedInt(row[1]); uint8 rankn = atoi(row[1]);
if(rankn > GUILD_MAX_RANK) { if(rankn > GUILD_MAX_RANK) {
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id); LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
@@ -131,9 +129,9 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
auto row = results.begin(); auto row = results.begin();
info = _CreateGuild(guild_id, row[0], Strings::ToUnsignedInt(row[1]), Strings::ToUnsignedInt(row[2]), row[3], row[4], row[5], row[6]); 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); "FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id);
results = m_db->QueryDatabase(query); results = m_db->QueryDatabase(query);
@@ -144,7 +142,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
for (auto row=results.begin();row!=results.end();++row) for (auto row=results.begin();row!=results.end();++row)
{ {
uint8 rankn = Strings::ToUnsignedInt(row[1]); uint8 rankn = atoi(row[1]);
if(rankn > GUILD_MAX_RANK) { if(rankn > GUILD_MAX_RANK) {
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id); LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
@@ -270,7 +268,7 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length()); m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length());
query = StringFormat("INSERT INTO guild_ranks " 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)", " VALUES(%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d)",
guild_id, rank, title_esc, guild_id, rank, title_esc,
rankInfo.permissions[GUILD_HEAR], rankInfo.permissions[GUILD_HEAR],
@@ -740,7 +738,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
std::string query; std::string query;
if(guild_id != GUILD_NONE) { 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); auto results = m_db->QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
@@ -760,7 +758,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
} }
bool BaseGuildManager::DBSetGuildRank(uint32 charid, 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")); return(QueryWithLogging(query, "setting a guild member's rank"));
} }
@@ -787,7 +785,9 @@ bool BaseGuildManager::GetBankerFlag(uint32 CharID)
auto row = results.begin(); auto row = results.begin();
return Strings::ToBool(row[0]); bool IsBanker = atoi(row[0]);
return IsBanker;
} }
bool BaseGuildManager::DBSetAltFlag(uint32 charid, bool is_alt) bool BaseGuildManager::DBSetAltFlag(uint32 charid, bool is_alt)
@@ -815,7 +815,9 @@ bool BaseGuildManager::GetAltFlag(uint32 CharID)
auto row = results.begin(); auto row = results.begin();
return Strings::ToBool(row[0]); bool IsAlt = atoi(row[0]);
return IsAlt;
} }
bool BaseGuildManager::DBSetTributeFlag(uint32 charid, bool enabled) { bool BaseGuildManager::DBSetTributeFlag(uint32 charid, bool enabled) {
@@ -862,26 +864,35 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
return(true); return(true);
} }
//factored out so I dont have to copy this crap.
#ifdef BOTS
#define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt`" \
" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` "
#else
#define GuildMemberBaseQuery \ #define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \ "SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \ " g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt` " \ " g.`banker`, g.`public_note`, g.`alt` " \
" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` " " FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` "
#endif
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) { static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
//fields from `characer_` //fields from `characer_`
into.char_id = Strings::ToUnsignedInt(row[0]); into.char_id = atoi(row[0]);
into.char_name = row[1]; into.char_name = row[1];
into.class_ = Strings::ToUnsignedInt(row[2]); into.class_ = atoi(row[2]);
into.level = Strings::ToUnsignedInt(row[3]); into.level = atoi(row[3]);
into.time_last_on = Strings::ToUnsignedInt(row[4]); into.time_last_on = atoul(row[4]);
into.zone_id = Strings::ToUnsignedInt(row[5]); into.zone_id = atoi(row[5]);
//fields from `guild_members`, leave at defaults if missing //fields from `guild_members`, leave at defaults if missing
into.guild_id = row[6] ? Strings::ToUnsignedInt(row[6]) : GUILD_NONE; into.guild_id = row[6] ? atoi(row[6]) : GUILD_NONE;
into.rank = row[7] ? Strings::ToUnsignedInt(row[7]) : (GUILD_MAX_RANK+1); into.rank = row[7] ? atoi(row[7]) : (GUILD_MAX_RANK+1);
into.tribute_enable = row[8] ? (row[8][0] == '0'?false:true) : false; into.tribute_enable = row[8] ? (row[8][0] == '0'?false:true) : false;
into.total_tribute = row[9] ? Strings::ToUnsignedInt(row[9]) : 0; into.total_tribute = row[9] ? atoi(row[9]) : 0;
into.last_tribute = row[10]? Strings::ToUnsignedInt(row[10]) : 0; //timestamp into.last_tribute = row[10]? atoul(row[10]) : 0; //timestamp
into.banker = row[11]? (row[11][0] == '0'?false:true) : false; into.banker = row[11]? (row[11][0] == '0'?false:true) : false;
into.public_note = row[12]? row[12] : ""; into.public_note = row[12]? row[12] : "";
into.alt = row[13]? (row[13][0] == '0'?false:true) : false; into.alt = row[13]? (row[13][0] == '0'?false:true) : false;
@@ -956,7 +967,12 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
} }
//load up the rank info for each guild. //load up the rank info for each guild.
std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id); std::string query;
#ifdef BOTS
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C' AND c.deleted_at IS NULL", char_id);
#else
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id);
#endif
auto results = m_db->QueryDatabase(query); auto results = m_db->QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return false; return false;
@@ -1192,7 +1208,7 @@ BaseGuildManager::RankInfo::RankInfo() {
BaseGuildManager::GuildInfo::GuildInfo() { BaseGuildManager::GuildInfo::GuildInfo() {
leader_char_id = 0; leader_char_id = 0;
minstatus = AccountStatus::Player; minstatus = 0;
} }
uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID) uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
@@ -1209,66 +1225,6 @@ uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
return results.RowCount(); 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 = Strings::ToUnsignedInt(row[0]);
return guild_id;
}
bool BaseGuildManager::IsCharacterInGuild(uint32 character_id, uint32 guild_id)
{
auto current_guild_id = GetGuildIDByCharacterID(character_id);
if (current_guild_id == GUILD_NONE) {
return false;
}
if (guild_id && current_guild_id != guild_id) {
return false;
}
return true;
}
-4
View File
@@ -76,12 +76,8 @@ class BaseGuildManager
bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const; bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const;
const char *GetRankName(uint32 guild_id, uint8 rank) const; const char *GetRankName(uint32 guild_id, uint8 rank) const;
const char *GetGuildName(uint32 guild_id) 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; bool GetGuildNameByID(uint32 guild_id, std::string &into) const;
uint32 GetGuildIDByName(const char *GuildName); uint32 GetGuildIDByName(const char *GuildName);
uint32 GetGuildIDByCharacterID(uint32 character_id);
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const; bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const; uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
bool CheckGMStatus(uint32 guild_id, uint8 status) const; bool CheckGMStatus(uint32 guild_id, uint8 status) const;
+1424 -2149
View File
File diff suppressed because it is too large Load Diff
+9 -86
View File
@@ -25,7 +25,7 @@
//#include "races.h" //#include "races.h"
//#include "rulesys.h" //#include "rulesys.h"
//#include "shareddb.h" //#include "shareddb.h"
#include "strings.h" #include "string_util.h"
#include "../common/light_source.h" #include "../common/light_source.h"
@@ -353,7 +353,7 @@ bool EQ::InventoryProfile::SwapItem(
fail_state = swapRaceClass; fail_state = swapRaceClass;
return false; return false;
} }
if (deity_id && source_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & source_item->Deity)) { if (deity_id && source_item->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & source_item->Deity)) {
fail_state = swapDeity; fail_state = swapDeity;
return false; return false;
} }
@@ -379,7 +379,7 @@ bool EQ::InventoryProfile::SwapItem(
fail_state = swapRaceClass; fail_state = swapRaceClass;
return false; return false;
} }
if (deity_id && destination_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & destination_item->Deity)) { if (deity_id && destination_item->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & destination_item->Deity)) {
fail_state = swapDeity; fail_state = swapDeity;
return false; return false;
} }
@@ -399,7 +399,7 @@ bool EQ::InventoryProfile::SwapItem(
} }
// Remove item from inventory (with memory delete) // 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) // Pop item out of inventory map (or queue)
ItemInstance *item_to_delete = PopItem(slot_id); ItemInstance *item_to_delete = PopItem(slot_id);
@@ -412,11 +412,10 @@ bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
// If there are no charges left on the item, // If there are no charges left on the item,
if (item_to_delete->GetCharges() <= 0) { if (item_to_delete->GetCharges() <= 0) {
// If the item is stackable (e.g arrows), or // If the item is stackable (e.g arrows), or
// the item is not a charged item, or is expendable, delete it // the item is not stackable, and is not a charged item, or is expendable, delete it
if ( if (item_to_delete->IsStackable() ||
item_to_delete->IsStackable() || (!item_to_delete->IsStackable() &&
item_to_delete->GetItem()->MaxCharges == 0 || ((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable()))
item_to_delete->IsExpendable()
) { ) {
// Item can now be destroyed // Item can now be destroyed
InventoryProfile::MarkDirty(item_to_delete); InventoryProfile::MarkDirty(item_to_delete);
@@ -591,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 // 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 // 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 //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. //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) int16 EQ::InventoryProfile::HasItem(uint32 item_id, uint8 quantity, uint8 where)
@@ -1444,7 +1381,7 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
} }
if (result == INVALID_INDEX) { if (result == INVALID_INDEX) {
LogError("Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot); LogError("InventoryProfile::_PutItem: Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
InventoryProfile::MarkDirty(inst); // Slot not found, clean up InventoryProfile::MarkDirty(inst); // Slot not found, clean up
} }
@@ -1719,17 +1656,3 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 lo
return EQ::invslot::SLOT_INVALID; return EQ::invslot::SLOT_INVALID;
} }
std::vector<uint32> EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id)
{
std::vector<uint32> augments;
const auto* item = GetItem(slot_id);
if (item) {
for (uint8 i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
augments.push_back(item->GetAugment(i) ? item->GetAugmentItemID(i) : 0);
}
}
return augments;
}
+8 -26
View File
@@ -26,11 +26,8 @@
#include "item_instance.h" #include "item_instance.h"
#include "classes.h"
#include "races.h"
#include <list> #include <list>
#include <vector>
//FatherNitwit: location bits for searching specific //FatherNitwit: location bits for searching specific
@@ -132,10 +129,10 @@ namespace EQ
// Swap items in inventory // Swap items in inventory
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel }; enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = RACE_DOUG_0, uint8 class_id = NO_CLASS, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0); 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 // 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 // Checks All items in a bag for No Drop
bool CheckNoDrop(int16 slot_id, bool recurse = true); bool CheckNoDrop(int16 slot_id, bool recurse = true);
@@ -143,21 +140,6 @@ namespace EQ
// Remove item from inventory (and take control of memory) // Remove item from inventory (and take control of memory)
ItemInstance* PopItem(int16 slot_id); ItemInstance* PopItem(int16 slot_id);
// Check if player has a specific item equipped by Item ID
bool HasItemEquippedByID(uint32 item_id);
// Check how many of a specific item the player has equipped by Item ID
int CountItemEquippedByID(uint32 item_id);
// Check if player has a specific augment equipped by Item ID
bool HasAugmentEquippedByID(uint32 item_id);
// Check how many of a specific augment the player has equipped by Item ID
int CountAugmentEquippedByID(uint32 item_id);
// Get a list of augments from a specific slot ID
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
// Check whether there is space for the specified number of the specified item. // Check whether there is space for the specified number of the specified item.
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity); bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
@@ -203,12 +185,12 @@ namespace EQ
void dumpBankItems(); void dumpBankItems();
void dumpSharedBankItems(); void dumpSharedBankItems();
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, const std::string& value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, int value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, float value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, bool value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value);
std::string GetCustomItemData(int16 slot_id, const std::string& identifier); std::string GetCustomItemData(int16 slot_id, std::string identifier);
static const int GetItemStatValue(uint32 item_id, const std::string& identifier); static int GetItemStatValue(uint32 item_id, const char* identifier);
protected: protected:
/////////////////////////////// ///////////////////////////////
// Protected Methods // Protected Methods
+1 -1
View File
@@ -19,7 +19,7 @@
#include "inventory_slot.h" #include "inventory_slot.h"
#include "textures.h" #include "textures.h"
#include "strings.h" #include "string_util.h"
int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index) int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index)
-155
View File
@@ -18,17 +18,7 @@
* *
*/ */
#include <cstring>
#include <fmt/format.h>
#include <csignal>
#include <vector>
#include "ip_util.h" #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 * @param ip
@@ -80,148 +70,3 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0") 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(
"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;
}
-7
View File
@@ -30,13 +30,6 @@ public:
static uint32_t IPToUInt(const std::string &ip); 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 IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask);
static bool IsIpInPrivateRfc1918(const std::string &ip); 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);
}; };
+6 -4
View File
@@ -30,7 +30,6 @@
#include "types.h" #include "types.h"
#include "eqemu_exception.h" #include "eqemu_exception.h"
#include "eqemu_config.h" #include "eqemu_config.h"
#include "path_manager.h"
namespace EQ { namespace EQ {
struct IPCMutex::Implementation { struct IPCMutex::Implementation {
@@ -41,11 +40,12 @@ namespace EQ {
#endif #endif
}; };
IPCMutex::IPCMutex(const std::string& name) : locked_(false) { IPCMutex::IPCMutex(std::string name) : locked_(false) {
imp_ = new Implementation; imp_ = new Implementation;
#ifdef _WINDOWS #ifdef _WINDOWS
auto Config = EQEmuConfig::get(); 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, imp_->mut_ = CreateMutex(nullptr,
FALSE, FALSE,
@@ -55,7 +55,9 @@ namespace EQ {
EQ_EXCEPT("IPC Mutex", "Could not create mutex."); EQ_EXCEPT("IPC Mutex", "Could not create mutex.");
} }
#else #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 #ifdef __DARWIN
#if __DARWIN_C_LEVEL < 200809L #if __DARWIN_C_LEVEL < 200809L
+1 -1
View File
@@ -37,7 +37,7 @@ namespace EQ {
Creates a named binary semaphore, basically a semaphore that is init S <- 1 Creates a named binary semaphore, basically a semaphore that is init S <- 1
\param name The name of this mutex. \param name The name of this mutex.
*/ */
IPCMutex(const std::string& name); IPCMutex(std::string name);
//! Destructor //! Destructor
~IPCMutex(); ~IPCMutex();
+2 -28
View File
@@ -169,33 +169,11 @@ uint8 EQ::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit)
bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const
{ {
if (!(Races & GetPlayerRaceBit(race_id))) { if (!(Races & GetPlayerRaceBit(race_id)))
return false; return false;
}
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) { if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id))))
return false; return false;
}
return true;
}
bool EQ::ItemData::IsClassEquipable(uint16 class_id) const
{
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
return false;
}
return true;
}
bool EQ::ItemData::IsRaceEquipable(uint16 race_id) const
{
if (!(Races & GetPlayerRaceBit(race_id))) {
return false;
}
return true; return true;
} }
@@ -230,10 +208,6 @@ bool EQ::ItemData::IsTypeShield() const
return (ItemType == item::ItemTypeShield); return (ItemType == item::ItemTypeShield);
} }
bool EQ::ItemData::IsQuestItem() const {
return QuestItemFlag;
}
bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item) bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item)
{ {
if (!l_item || !r_item) if (!l_item || !r_item)
+159 -167
View File
@@ -355,198 +355,190 @@ namespace EQ
struct ItemData { struct ItemData {
// Non packet based fields // Non packet based fields
uint8 MinStatus {}; uint8 MinStatus;
// Packet based fields // Packet based fields
uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book
char Name[64] {}; // Name char Name[64]; // Name
char Lore[80] {}; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
char IDFile[30] {}; // Visible model char IDFile[30]; // Visible model
uint32 ID {}; // Unique ID (also PK for DB) uint32 ID; // Unique ID (also PK for DB)
int32 Weight {}; // Item weight * 10 int32 Weight; // Item weight * 10
uint8 NoRent{} ; // No Rent: 0=norent, 255=not norent uint8 NoRent; // No Rent: 0=norent, 255=not norent
uint8 NoDrop {}; // No Drop: 0=nodrop, 255=not nodrop uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop
uint8 Size {}; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant uint8 Size; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant
uint32 Slots {}; // Bitfield for which slots this item can be used in uint32 Slots; // Bitfield for which slots this item can be used in
uint32 Price {}; // Item cost (?) uint32 Price; // Item cost (?)
uint32 Icon {}; // Icon Number 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 LoreFlag; // This will be true if LoreGroup is non-zero
bool PendingLoreFlag {}; bool PendingLoreFlag;
bool ArtifactFlag {}; bool ArtifactFlag;
bool SummonedFlag {}; bool SummonedFlag;
uint8 FVNoDrop {}; // Firiona Vie nodrop flag uint8 FVNoDrop; // Firiona Vie nodrop flag
uint32 Favor {}; // Individual favor uint32 Favor; // Individual favor
uint32 GuildFavor {}; // Guild favor uint32 GuildFavor; // Guild favor
uint32 PointType {}; uint32 PointType;
//uint32 Unk117; //uint32 Unk117;
//uint32 Unk118; //uint32 Unk118;
//uint32 Unk121; //uint32 Unk121;
//uint32 Unk124; //uint32 Unk124;
uint8 BagType {}; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
uint8 BagSlots {}; // Number of slots: can only be 2, 4, 6, 8, or 10 uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10
uint8 BagSize {}; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
uint8 BagWR {}; // 0->100 uint8 BagWR; // 0->100
bool BenefitFlag {}; bool BenefitFlag;
bool Tradeskills {}; // Is this a tradeskill item? bool Tradeskills; // Is this a tradeskill item?
int8 CR {}; // Save vs Cold int8 CR; // Save vs Cold
int8 DR {}; // Save vs Disease int8 DR; // Save vs Disease
int8 PR {}; // Save vs Poison int8 PR; // Save vs Poison
int8 MR {}; // Save vs Magic int8 MR; // Save vs Magic
int8 FR {}; // Save vs Fire int8 FR; // Save vs Fire
int8 AStr {}; // Strength int8 AStr; // Strength
int8 ASta {}; // Stamina int8 ASta; // Stamina
int8 AAgi {}; // Agility int8 AAgi; // Agility
int8 ADex {}; // Dexterity int8 ADex; // Dexterity
int8 ACha {}; // Charisma int8 ACha; // Charisma
int8 AInt {}; // Intelligence int8 AInt; // Intelligence
int8 AWis {}; // Wisdom int8 AWis; // Wisdom
int32 HP {}; // HP int32 HP; // HP
int32 Mana {}; // Mana int32 Mana; // Mana
int32 AC {}; // AC int32 AC; // AC
uint32 Deity {}; // Bitmask of Deities that can equip this item uint32 Deity; // Bitmask of Deities that can equip this item
//uint32 Unk033 //uint32 Unk033
int32 SkillModValue {}; // % Mod to skill specified in SkillModType int32 SkillModValue; // % Mod to skill specified in SkillModType
int32 SkillModMax {}; // Max skill point modification int32 SkillModMax; // Max skill point modification
uint32 SkillModType {}; // Type of skill for SkillModValue to apply to uint32 SkillModType; // Type of skill for SkillModValue to apply to
uint32 BaneDmgRace {}; // Bane Damage Race uint32 BaneDmgRace; // Bane Damage Race
int32 BaneDmgAmt {}; // Bane Damage Body Amount int32 BaneDmgAmt; // Bane Damage Body Amount
uint32 BaneDmgBody {}; // Bane Damage Body uint32 BaneDmgBody; // Bane Damage Body
bool Magic {}; // True=Magic Item, False=not bool Magic; // True=Magic Item, False=not
int32 CastTime_ {}; int32 CastTime_;
uint8 ReqLevel {}; // Required Level to use item uint8 ReqLevel; // Required Level to use item
uint32 BardType {}; // Bard Skill Type uint32 BardType; // Bard Skill Type
int32 BardValue {}; // Bard Skill Amount int32 BardValue; // Bard Skill Amount
int8 Light {}; // Light int8 Light; // Light
uint8 Delay {}; // Delay * 10 uint8 Delay; // Delay * 10
uint8 RecLevel {}; // Recommended level to use item uint8 RecLevel; // Recommended level to use item
uint8 RecSkill {}; // Recommended skill to use item (refers to primary skill of item) uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item)
uint8 ElemDmgType {}; // Elemental Damage Type (1=magic, 2=fire) uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire)
uint8 ElemDmgAmt {}; // Elemental Damage uint8 ElemDmgAmt; // Elemental Damage
uint8 Range {}; // Range of item uint8 Range; // Range of item
uint32 Damage {}; // Delay between item usage (in 0.1 sec increments) uint32 Damage; // Delay between item usage (in 0.1 sec increments)
uint32 Color {}; // RR GG BB 00 <-- as it appears in pc uint32 Color; // RR GG BB 00 <-- as it appears in pc
uint32 Classes {}; // Bitfield of classes that can equip item (1 << class#) uint32 Classes; // Bitfield of classes that can equip item (1 << class#)
uint32 Races {}; // Bitfield of races that can equip item (1 << race#) uint32 Races; // Bitfield of races that can equip item (1 << race#)
//uint32 Unk054 {}; //uint32 Unk054;
int16 MaxCharges {}; // Maximum charges items can hold: -1 if not a chargeable item int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
uint8 ItemType {}; // Item Type/Skill (itemClass* from above) uint8 ItemType; // Item Type/Skill (itemClass* from above)
int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass) int32 SubType; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
uint8 Material {}; // Item material type uint8 Material; // Item material type
uint32 HerosForgeModel {};// Hero's Forge Armor Model Type (2-13?) uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
float SellRate {}; // Sell rate float SellRate; // Sell rate
//uint32 Unk059 {}; //uint32 Unk059;
union { union {
uint32 Fulfilment; // Food fulfilment (How long it lasts) uint32 Fulfilment; // Food fulfilment (How long it lasts)
uint32 CastTime; // Cast Time for clicky effects, in milliseconds uint32 CastTime; // Cast Time for clicky effects, in milliseconds
}; };
uint32 EliteMaterial {}; uint32 EliteMaterial;
int32 ProcRate {}; int32 ProcRate;
int8 CombatEffects {}; // PoP: Combat Effects + int8 CombatEffects; // PoP: Combat Effects +
int8 Shielding {}; // PoP: Shielding % int8 Shielding; // PoP: Shielding %
int8 StunResist {}; // PoP: Stun Resist % int8 StunResist; // PoP: Stun Resist %
int8 StrikeThrough {}; // PoP: Strike Through % int8 StrikeThrough; // PoP: Strike Through %
int32 ExtraDmgSkill {}; uint32 ExtraDmgSkill;
int32 ExtraDmgAmt {}; uint32 ExtraDmgAmt;
int8 SpellShield {}; // PoP: Spell Shield % int8 SpellShield; // PoP: Spell Shield %
int8 Avoidance {}; // PoP: Avoidance + int8 Avoidance; // PoP: Avoidance +
int8 Accuracy {}; // PoP: Accuracy + int8 Accuracy; // PoP: Accuracy +
uint32 CharmFileID {}; uint32 CharmFileID;
int32 FactionMod1 {}; // Faction Mod 1 int32 FactionMod1; // Faction Mod 1
int32 FactionMod2 {}; // Faction Mod 2 int32 FactionMod2; // Faction Mod 2
int32 FactionMod3 {}; // Faction Mod 3 int32 FactionMod3; // Faction Mod 3
int32 FactionMod4 {}; // Faction Mod 4 int32 FactionMod4; // Faction Mod 4
int32 FactionAmt1 {}; // Faction Amt 1 int32 FactionAmt1; // Faction Amt 1
int32 FactionAmt2 {}; // Faction Amt 2 int32 FactionAmt2; // Faction Amt 2
int32 FactionAmt3 {}; // Faction Amt 3 int32 FactionAmt3; // Faction Amt 3
int32 FactionAmt4 {}; // Faction Amt 4 int32 FactionAmt4; // Faction Amt 4
char CharmFile[32] {}; // ? char CharmFile[32]; // ?
uint32 AugType {}; uint32 AugType;
uint8 AugSlotType[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Type uint8 AugSlotType[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Type
uint8 AugSlotVisible[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Visible uint8 AugSlotVisible[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Visible
uint8 AugSlotUnk2[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related uint8 AugSlotUnk2[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
uint32 LDoNTheme {}; uint32 LDoNTheme;
uint32 LDoNPrice {}; uint32 LDoNPrice;
uint32 LDoNSold {}; uint32 LDoNSold;
uint32 BaneDmgRaceAmt {}; uint32 BaneDmgRaceAmt;
uint32 AugRestrict {}; uint32 AugRestrict;
int32 Endur {}; uint32 Endur;
int32 DotShielding {}; uint32 DotShielding;
int32 Attack {}; uint32 Attack;
int32 Regen {}; uint32 Regen;
int32 ManaRegen {}; uint32 ManaRegen;
int32 EnduranceRegen {}; uint32 EnduranceRegen;
int32 Haste {}; uint32 Haste;
int32 DamageShield {}; uint32 DamageShield;
uint32 RecastDelay {}; uint32 RecastDelay;
int RecastType {}; int RecastType;
uint32 AugDistiller {}; uint32 AugDistiller;
bool Attuneable {}; bool Attuneable;
bool NoPet {}; bool NoPet;
bool PotionBelt {}; bool PotionBelt;
bool Stackable {}; bool Stackable;
bool NoTransfer {}; bool NoTransfer;
bool QuestItemFlag {}; bool QuestItemFlag;
int16 StackSize {}; int16 StackSize;
uint8 PotionBeltSlots {}; uint8 PotionBeltSlots;
item::ItemEffect_Struct Click {}; item::ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
item::ItemEffect_Struct Proc {};
item::ItemEffect_Struct Worn {};
item::ItemEffect_Struct Focus {};
item::ItemEffect_Struct Scroll {};
item::ItemEffect_Struct Bard {};
uint8 Book {}; // 0=Not book, 1=Book uint8 Book; // 0=Not book, 1=Book
uint32 BookType {}; uint32 BookType;
char Filename[33] {}; // Filename for book data char Filename[33]; // Filename for book data
// Begin SoF Fields // Begin SoF Fields
int32 SVCorruption {}; int32 SVCorruption;
uint32 Purity {}; uint32 Purity;
uint8 EvolvingItem {}; uint8 EvolvingItem;
uint32 EvolvingID {}; uint32 EvolvingID;
uint8 EvolvingLevel {}; uint8 EvolvingLevel;
uint8 EvolvingMax {}; uint8 EvolvingMax;
uint32 BackstabDmg {}; uint32 BackstabDmg;
uint32 DSMitigation {}; uint32 DSMitigation;
int32 HeroicStr {}; int32 HeroicStr;
int32 HeroicInt {}; int32 HeroicInt;
int32 HeroicWis {}; int32 HeroicWis;
int32 HeroicAgi {}; int32 HeroicAgi;
int32 HeroicDex {}; int32 HeroicDex;
int32 HeroicSta {}; int32 HeroicSta;
int32 HeroicCha {}; int32 HeroicCha;
int32 HeroicMR {}; int32 HeroicMR;
int32 HeroicFR {}; int32 HeroicFR;
int32 HeroicCR {}; int32 HeroicCR;
int32 HeroicDR {}; int32 HeroicDR;
int32 HeroicPR {}; int32 HeroicPR;
int32 HeroicSVCorrup {}; int32 HeroicSVCorrup;
int32 HealAmt {}; int32 HealAmt;
int32 SpellDmg {}; int32 SpellDmg;
uint32 LDoNSellBackRate {}; uint32 LDoNSellBackRate;
uint32 ScriptFileID {}; uint32 ScriptFileID;
uint16 ExpendableArrow {}; uint16 ExpendableArrow;
uint32 Clairvoyance {}; uint32 Clairvoyance;
char ClickName[65] {}; char ClickName[65];
char ProcName[65] {}; char ProcName[65];
char WornName[65] {}; char WornName[65];
char FocusName[65] {}; char FocusName[65];
char ScrollName[65] {}; char ScrollName[65];
//BardName //BardName
bool IsEquipable(uint16 Race, uint16 Class) const; bool IsEquipable(uint16 Race, uint16 Class) const;
bool IsClassEquipable(uint16 Class) const;
bool IsRaceEquipable(uint16 Race) const;
bool IsClassCommon() const; bool IsClassCommon() const;
bool IsClassBag() const; bool IsClassBag() const;
bool IsClassBook() const; bool IsClassBook() const;
bool IsType1HWeapon() const; bool IsType1HWeapon() const;
bool IsType2HWeapon() const; bool IsType2HWeapon() const;
bool IsTypeShield() const; bool IsTypeShield() const;
bool IsQuestItem() const;
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item); static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); } bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); }
+176 -285
View File
@@ -17,14 +17,13 @@
*/ */
#include "inventory_profile.h" #include "inventory_profile.h"
#include "../common/data_verification.h"
//#include "classes.h" //#include "classes.h"
//#include "global_define.h" //#include "global_define.h"
//#include "item_instance.h" //#include "item_instance.h"
//#include "races.h" //#include "races.h"
#include "rulesys.h" #include "rulesys.h"
#include "shareddb.h" #include "shareddb.h"
#include "strings.h" #include "string_util.h"
//#include "../common/light_source.h" //#include "../common/light_source.h"
@@ -58,62 +57,108 @@ static inline int32 GetNextItemInstSerialNumber() {
// class EQ::ItemInstance // class EQ::ItemInstance
// //
EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) { EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
m_use_type = ItemInstNormal;
if (item) { if(item) {
m_item = new ItemData(*item); m_item = new ItemData(*item);
} else {
m_item = nullptr;
} }
m_charges = charges; m_charges = charges;
m_price = 0;
if (m_item && m_item->IsClassCommon()) { m_attuned = false;
m_merchantslot = 0;
if (m_item && m_item->IsClassCommon())
m_color = m_item->Color; m_color = m_item->Color;
} else
m_color = 0;
m_merchantcount = 1;
m_SerialNumber = GetNextItemInstSerialNumber(); m_SerialNumber = GetNextItemInstSerialNumber();
m_exp = 0;
m_evolveLvl = 0;
m_activated = false;
m_scaledItem = nullptr;
m_evolveInfo = nullptr;
m_scaling = false;
m_ornamenticon = 0;
m_ornamentidfile = 0;
m_ornament_hero_model = 0;
m_recast_timestamp = 0;
m_new_id_file = 0;
} }
EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) { EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) {
m_use_type = ItemInstNormal;
m_item = db->GetItem(item_id); m_item = db->GetItem(item_id);
if(m_item) {
if (m_item) {
m_item = new ItemData(*m_item); m_item = new ItemData(*m_item);
} }
else {
m_item = nullptr;
}
m_charges = charges; m_charges = charges;
m_price = 0;
if (m_item && m_item->IsClassCommon()) { m_merchantslot = 0;
m_attuned=false;
if (m_item && m_item->IsClassCommon())
m_color = m_item->Color; m_color = m_item->Color;
} else { else
m_color = 0; m_color = 0;
} m_merchantcount = 1;
m_SerialNumber = GetNextItemInstSerialNumber(); m_SerialNumber = GetNextItemInstSerialNumber();
m_exp = 0;
m_evolveLvl = 0;
m_activated = false;
m_scaledItem = nullptr;
m_evolveInfo = nullptr;
m_scaling = false;
m_ornamenticon = 0;
m_ornamentidfile = 0;
m_ornament_hero_model = 0;
m_recast_timestamp = 0;
m_new_id_file = 0;
} }
EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) { EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) {
m_use_type = use_type; m_use_type = use_type;
m_item = nullptr;
m_charges = 0;
m_price = 0;
m_attuned = false;
m_merchantslot = 0;
m_color = 0;
m_exp = 0;
m_evolveLvl = 0;
m_activated = false;
m_scaledItem = nullptr;
m_evolveInfo = nullptr;
m_scaling = false;
m_ornamenticon = 0;
m_ornamentidfile = 0;
m_ornament_hero_model = 0;
m_recast_timestamp = 0;
m_new_id_file = 0;
} }
// Make a copy of an EQ::ItemInstance object // Make a copy of an EQ::ItemInstance object
EQ::ItemInstance::ItemInstance(const ItemInstance& copy) EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
{ {
m_use_type = copy.m_use_type; m_use_type=copy.m_use_type;
if(copy.m_item)
if (copy.m_item) {
m_item = new ItemData(*copy.m_item); m_item = new ItemData(*copy.m_item);
} else { else
m_item = nullptr; m_item = nullptr;
}
m_charges = copy.m_charges;
m_price = copy.m_price;
m_color = copy.m_color;
m_merchantslot = copy.m_merchantslot;
m_currentslot = copy.m_currentslot;
m_attuned = copy.m_attuned;
m_merchantcount = copy.m_merchantcount;
m_charges=copy.m_charges;
m_price=copy.m_price;
m_color=copy.m_color;
m_merchantslot=copy.m_merchantslot;
m_currentslot=copy.m_currentslot;
m_attuned=copy.m_attuned;
m_merchantcount=copy.m_merchantcount;
// Copy container contents // Copy container contents
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) { for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
ItemInstance* inst_old = it->second; ItemInstance* inst_old = it->second;
@@ -123,16 +168,14 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
inst_new = inst_old->Clone(); inst_new = inst_old->Clone();
} }
if (inst_new) { if (inst_new != nullptr) {
m_contents[it->first] = inst_new; m_contents[it->first] = inst_new;
} }
} }
std::map<std::string, std::string>::const_iterator iter; std::map<std::string, std::string>::const_iterator iter;
for (iter = copy.m_custom_data.begin(); iter != copy.m_custom_data.end(); ++iter) { for (iter = copy.m_custom_data.begin(); iter != copy.m_custom_data.end(); ++iter) {
m_custom_data[iter->first] = iter->second; m_custom_data[iter->first] = iter->second;
} }
m_SerialNumber = copy.m_SerialNumber; m_SerialNumber = copy.m_SerialNumber;
m_custom_data = copy.m_custom_data; m_custom_data = copy.m_custom_data;
m_timers = copy.m_timers; m_timers = copy.m_timers;
@@ -140,18 +183,15 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
m_exp = copy.m_exp; m_exp = copy.m_exp;
m_evolveLvl = copy.m_evolveLvl; m_evolveLvl = copy.m_evolveLvl;
m_activated = copy.m_activated; m_activated = copy.m_activated;
if (copy.m_scaledItem)
if (copy.m_scaledItem) {
m_scaledItem = new ItemData(*copy.m_scaledItem); m_scaledItem = new ItemData(*copy.m_scaledItem);
} else { else
m_scaledItem = nullptr; m_scaledItem = nullptr;
}
if (copy.m_evolveInfo) { if(copy.m_evolveInfo)
m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo); m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo);
} else { else
m_evolveInfo = nullptr; m_evolveInfo = nullptr;
}
m_scaling = copy.m_scaling; m_scaling = copy.m_scaling;
m_ornamenticon = copy.m_ornamenticon; m_ornamenticon = copy.m_ornamenticon;
@@ -176,13 +216,11 @@ bool EQ::ItemInstance::IsType(item::ItemClass item_class) const
// IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr' // IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr'
// Check usage type // Check usage type
if (m_use_type == ItemInstWorldContainer && item_class == item::ItemClassBag) { if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag))
return true; return true;
}
if (!m_item) { if (!m_item)
return false; return false;
}
return (m_item->ItemClass == item_class); return (m_item->ItemClass == item_class);
} }
@@ -205,144 +243,95 @@ bool EQ::ItemInstance::IsClassBook() const
// Is item stackable? // Is item stackable?
bool EQ::ItemInstance::IsStackable() const bool EQ::ItemInstance::IsStackable() const
{ {
return (m_item && m_item->Stackable); if (!m_item)
return false;
return m_item->Stackable;
} }
bool EQ::ItemInstance::IsCharged() const bool EQ::ItemInstance::IsCharged() const
{ {
if (!m_item) { if (!m_item)
return false; return false;
}
if (m_item->MaxCharges > 1) { if (m_item->MaxCharges > 1)
return true; return true;
} else { else
return false; return false;
}
} }
// Can item be equipped? // Can item be equipped?
bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const
{ {
if (!m_item || !m_item->Slots) { if (!m_item || (m_item->Slots == 0))
return false; return false;
}
return m_item->IsEquipable(race, class_); return m_item->IsEquipable(race, class_);
} }
// Can item be equipped by Class?
bool EQ::ItemInstance::IsClassEquipable(uint16 class_) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsClassEquipable(class_);
}
// Can item be equipped by Race?
bool EQ::ItemInstance::IsRaceEquipable(uint16 race) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsRaceEquipable(race);
}
// Can equip at this slot? // Can equip at this slot?
bool EQ::ItemInstance::IsEquipable(int16 slot_id) const bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
{ {
if (!m_item || !m_item->Slots) { if (!m_item)
return false; return false;
}
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) { if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END)
return false; return false;
}
return ((m_item->Slots & (1 << slot_id)) != 0); return ((m_item->Slots & (1 << slot_id)) != 0);
} }
bool EQ::ItemInstance::IsAugmentable() const bool EQ::ItemInstance::IsAugmentable() const
{ {
if (!m_item) { if (!m_item)
return false; return false;
}
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
if (m_item->AugSlotType[index] != 0) { if (m_item->AugSlotType[index] != 0)
return true; return true;
} }
}
return false; return false;
} }
bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const { bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
if (!m_item || !m_item->IsClassCommon()) { if (!m_item || !m_item->IsClassCommon())
return false; return false;
}
int index = invslot::EQUIPMENT_BEGIN; int index = invslot::EQUIPMENT_BEGIN;
for (; index <= invslot::EQUIPMENT_END; ++index) { for (; index <= invslot::EQUIPMENT_END; ++index) {
if (m_item->Slots & (1 << index)) { if (m_item->Slots & (1 << index)) {
if (aug_wear_slots & (1 << index)) { if (aug_wear_slots & (1 << index))
break; break;
} }
} }
}
return (index <= EQ::invslot::EQUIPMENT_END); return (index <= EQ::invslot::EQUIPMENT_END);
} }
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augtype) const
{ {
if (!m_item || !m_item->IsClassCommon()) { if (!m_item || !m_item->IsClassCommon())
return INVALID_INDEX; return INVALID_INDEX;
}
auto i = invaug::SOCKET_BEGIN; int index = invaug::SOCKET_BEGIN;
for (; i <= invaug::SOCKET_END; ++i) { for (; index <= invaug::SOCKET_END; ++index) {
if (GetItem(i)) { if (GetItem(index)) { continue; }
continue; if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype)))
}
if (
augment_type == -1 ||
(
m_item->AugSlotType[i] &&
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
)
) {
break; break;
} }
}
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX; return (index <= invaug::SOCKET_END) ? index : INVALID_INDEX;
} }
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
{ {
if (!m_item || !m_item->IsClassCommon()) { if (!m_item || !m_item->IsClassCommon())
return false; return false;
}
if ( if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) {
(
!GetItem(slot) &&
m_item->AugSlotVisible[slot]
) &&
augment_type == -1 ||
(
m_item->AugSlotType[slot] &&
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
)
) {
return true; return true;
} }
return false; return false;
} }
@@ -359,10 +348,9 @@ EQ::ItemInstance* EQ::ItemInstance::GetItem(uint8 index) const
uint32 EQ::ItemInstance::GetItemID(uint8 slot) const uint32 EQ::ItemInstance::GetItemID(uint8 slot) const
{ {
const auto item = GetItem(slot); ItemInstance *item = GetItem(slot);
if (item) { if (item)
return item->GetID(); return item->GetID();
}
return 0; return 0;
} }
@@ -486,21 +474,14 @@ uint8 EQ::ItemInstance::FirstOpenSlot() const
uint8 EQ::ItemInstance::GetTotalItemCount() const uint8 EQ::ItemInstance::GetTotalItemCount() const
{ {
if (!m_item) { if (!m_item)
return 0; return 0;
}
uint8 item_count = 1; uint8 item_count = 1;
if (!m_item->IsClassBag()) { if (m_item && !m_item->IsClassBag()) { return item_count; }
return item_count;
}
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) { for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } }
if (GetItem(index)) {
++item_count;
}
}
return item_count; return item_count;
} }
@@ -519,108 +500,86 @@ bool EQ::ItemInstance::IsNoneEmptyContainer()
} }
// Retrieve augment inside item // Retrieve augment inside item
EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 augment_index) const EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 slot) const
{ {
if (m_item && m_item->IsClassCommon()) { if (m_item && m_item->IsClassCommon())
return GetItem(augment_index); return GetItem(slot);
}
return nullptr; return nullptr;
} }
bool EQ::ItemInstance::IsOrnamentationAugment(EQ::ItemInstance* augment) const EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugtype) const
{ {
if (!m_item || !m_item->IsClassCommon() || !augment) { if (!m_item || !m_item->IsClassCommon()) { return nullptr; }
return false; if (ornamentationAugtype == 0) { return nullptr; }
}
const auto augment_item = augment->GetItem();
if (!augment_item) {
return false;
}
const std::string& idfile = augment_item->IDFile;
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++)
{
if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype)
{
const char *item_IDFile = GetAugment(i)->GetItem()->IDFile;
if ( if (
EQ::ValueWithin( (strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0
augment->GetAugmentType(), || strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0)
OrnamentationAugmentTypes::StandardOrnamentation, && GetAugment(i)->GetItem()->HerosForgeModel == 0
OrnamentationAugmentTypes::SpecialOrnamentation )
) || {
( continue;
idfile != "IT63" &&
idfile != "IT64"
) ||
augment_item->HerosForgeModel
) {
return true;
} }
return this->GetAugment(i);
return false;
}
EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAugment() const
{
if (!m_item || !m_item->IsClassCommon()) {
return nullptr;
}
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
const auto augment = GetAugment(i);
if (augment && IsOrnamentationAugment(augment)) {
return augment;
} }
} }
return nullptr; return nullptr;
} }
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const {
{
// Not a Hero Forge item. // Not a Hero Forge item.
if (m_ornament_hero_model == 0 || material_slot < 0) { if (m_ornament_hero_model == 0 || material_slot < 0)
return 0; return 0;
}
// Item is using an explicit Hero Forge ID // Item is using an explicit Hero Forge ID
if (m_ornament_hero_model >= 1000) { if (m_ornament_hero_model >= 1000)
return m_ornament_hero_model; return m_ornament_hero_model;
}
// Item is using a shorthand ID // Item is using a shorthand ID
return (m_ornament_hero_model * 100) + material_slot; return (m_ornament_hero_model * 100) + material_slot;
} }
bool EQ::ItemInstance::UpdateOrnamentationInfo() bool EQ::ItemInstance::UpdateOrnamentationInfo() {
{ if (!m_item || !m_item->IsClassCommon())
if (!m_item || !m_item->IsClassCommon()) {
return false; return false;
bool ornamentSet = false;
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
if (GetOrnamentationAug(ornamentationAugtype))
{
const ItemData* ornamentItem;
ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem();
if (ornamentItem != nullptr)
{
SetOrnamentIcon(ornamentItem->Icon);
SetOrnamentHeroModel(ornamentItem->HerosForgeModel);
if (strlen(ornamentItem->IDFile) > 2)
{
SetOrnamentationIDFile(atoi(&ornamentItem->IDFile[2]));
} }
else
const auto augment = GetOrnamentationAugment(); {
if (augment) {
const auto augment_item = GetOrnamentationAugment()->GetItem();
if (augment_item) {
SetOrnamentIcon(augment_item->Icon);
SetOrnamentHeroModel(augment_item->HerosForgeModel);
if (strlen(augment_item->IDFile) > 2) {
SetOrnamentationIDFile(Strings::ToUnsignedInt(&augment_item->IDFile[2]));
} else {
SetOrnamentationIDFile(0); SetOrnamentationIDFile(0);
} }
ornamentSet = true;
return true;
} }
} }
else
{
SetOrnamentIcon(0); SetOrnamentIcon(0);
SetOrnamentHeroModel(0); SetOrnamentHeroModel(0);
SetOrnamentationIDFile(0); SetOrnamentationIDFile(0);
}
return false; return ornamentSet;
} }
bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) { bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) {
@@ -670,13 +629,12 @@ bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *C
return false; return false;
} }
uint32 EQ::ItemInstance::GetAugmentItemID(uint8 augment_index) const uint32 EQ::ItemInstance::GetAugmentItemID(uint8 slot) const
{ {
if (!m_item || !m_item->IsClassCommon()) { if (!m_item || !m_item->IsClassCommon())
return 0; return 0;
}
return GetItemID(augment_index); return GetItemID(slot);
} }
// Add an augment to the item // Add an augment to the item
@@ -720,58 +678,17 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
bool EQ::ItemInstance::IsAugmented() bool EQ::ItemInstance::IsAugmented()
{ {
if (!m_item || !m_item->IsClassCommon()) { if (!m_item || !m_item->IsClassCommon())
return false; return false;
}
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) { for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
if (GetAugmentItemID(slot_id)) { if (GetAugmentItemID(index))
return true; return true;
} }
}
return false; 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? // Has attack/delay?
bool EQ::ItemInstance::IsWeapon() const bool EQ::ItemInstance::IsWeapon() const
{ {
@@ -836,20 +753,7 @@ std::string EQ::ItemInstance::GetCustomDataString() const {
return ret_val; return ret_val;
} }
void EQ::ItemInstance::SetCustomDataString(const std::string& str) std::string EQ::ItemInstance::GetCustomData(std::string identifier) {
{
auto components = Strings::Split(str, "^");
auto value_count = components.size() / 2;
for (auto i = 0; i < value_count; i++) {
auto identifier = components[i * 2];
auto value = components[(i * 2) + 1];
SetCustomData(identifier, value);
}
}
std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) {
std::map<std::string, std::string>::const_iterator iter = m_custom_data.find(identifier); std::map<std::string, std::string>::const_iterator iter = m_custom_data.find(identifier);
if (iter != m_custom_data.end()) { if (iter != m_custom_data.end()) {
return iter->second; return iter->second;
@@ -858,33 +762,33 @@ std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) {
return ""; return "";
} }
void EQ::ItemInstance::SetCustomData(const std::string& identifier, const std::string& value) { void EQ::ItemInstance::SetCustomData(std::string identifier, std::string value) {
DeleteCustomData(identifier); DeleteCustomData(identifier);
m_custom_data[identifier] = value; m_custom_data[identifier] = value;
} }
void EQ::ItemInstance::SetCustomData(const std::string& identifier, int value) { void EQ::ItemInstance::SetCustomData(std::string identifier, int value) {
DeleteCustomData(identifier); DeleteCustomData(identifier);
std::stringstream ss; std::stringstream ss;
ss << value; ss << value;
m_custom_data[identifier] = ss.str(); m_custom_data[identifier] = ss.str();
} }
void EQ::ItemInstance::SetCustomData(const std::string& identifier, float value) { void EQ::ItemInstance::SetCustomData(std::string identifier, float value) {
DeleteCustomData(identifier); DeleteCustomData(identifier);
std::stringstream ss; std::stringstream ss;
ss << value; ss << value;
m_custom_data[identifier] = ss.str(); m_custom_data[identifier] = ss.str();
} }
void EQ::ItemInstance::SetCustomData(const std::string& identifier, bool value) { void EQ::ItemInstance::SetCustomData(std::string identifier, bool value) {
DeleteCustomData(identifier); DeleteCustomData(identifier);
std::stringstream ss; std::stringstream ss;
ss << value; ss << value;
m_custom_data[identifier] = ss.str(); m_custom_data[identifier] = ss.str();
} }
void EQ::ItemInstance::DeleteCustomData(const std::string& identifier) { void EQ::ItemInstance::DeleteCustomData(std::string identifier) {
auto iter = m_custom_data.find(identifier); auto iter = m_custom_data.find(identifier);
if (iter != m_custom_data.end()) { if (iter != m_custom_data.end()) {
m_custom_data.erase(iter); m_custom_data.erase(iter);
@@ -936,9 +840,8 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
void EQ::ItemInstance::Initialize(SharedDatabase *db) { void EQ::ItemInstance::Initialize(SharedDatabase *db) {
// if there's no actual item, don't do anything // if there's no actual item, don't do anything
if (!m_item) { if (!m_item)
return; return;
}
// initialize scaling items // initialize scaling items
if (m_item->CharmFileID != 0) { if (m_item->CharmFileID != 0) {
@@ -947,7 +850,7 @@ void EQ::ItemInstance::Initialize(SharedDatabase *db) {
} }
// initialize evolving items // initialize evolving items
else if (db && m_item->LoreGroup >= 1000) { else if ((db) && m_item->LoreGroup >= 1000 && m_item->LoreGroup != -1) {
// not complete yet // not complete yet
} }
} }
@@ -1155,7 +1058,7 @@ int EQ::ItemInstance::GetItemElementalFlag(bool augments) const
int EQ::ItemInstance::GetItemElementalDamage(bool augments) const int EQ::ItemInstance::GetItemElementalDamage(bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
damage = item->ElemDmgAmt; damage = item->ElemDmgAmt;
@@ -1220,7 +1123,7 @@ int EQ::ItemInstance::GetItemRequiredLevel(bool augments) const
int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
damage = item->Damage; damage = item->Damage;
@@ -1236,7 +1139,7 @@ int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
int EQ::ItemInstance::GetItemBackstabDamage(bool augments) const int EQ::ItemInstance::GetItemBackstabDamage(bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
damage = item->BackstabDmg; damage = item->BackstabDmg;
@@ -1273,7 +1176,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
{ {
int race = RACE_DOUG_0; int race = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
race = item->BaneDmgRace; race = item->BaneDmgRace;
@@ -1294,7 +1197,7 @@ int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
if (item->BaneDmgBody == against) if (item->BaneDmgBody == against)
@@ -1311,7 +1214,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) con
int EQ::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) const int EQ::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
if (item->BaneDmgRace == against) if (item->BaneDmgRace == against)
@@ -1779,18 +1682,6 @@ int EQ::ItemInstance::GetItemHaste(bool augments) const
return total; return total;
} }
int EQ::ItemInstance::RemoveTaskDeliveredItems()
{
int count = IsStackable() ? GetCharges() : 1;
count -= GetTaskDeliveredCount();
if (IsStackable())
{
SetCharges(count);
}
SetTaskDeliveredCount(0);
return count;
}
// //
// class EvolveInfo // class EvolveInfo
// //

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