Compare commits

..

2 Commits

Author SHA1 Message Date
hg 4a66c3918a Convert perl apis to perlbind 2022-06-12 19:56:46 -04:00
hg a2c6252c58 Add perlbind library 2022-06-12 19:56:45 -04:00
1194 changed files with 91462 additions and 131922 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}"
}
}
+8 -81
View File
@@ -1,8 +1,7 @@
--- ---
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:
@@ -11,88 +10,16 @@ concurrency:
volumes: volumes:
- name: cache - name: cache
host: host:
path: /var/lib/cache-release path: /var/lib/cache
steps: steps:
- name: Build Linux X64 - name: server-build
image: akkadius/eqemu-server:v11 # 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
- sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R
- git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O0 -g -DNDEBUG" -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
volumes: volumes:
- name: cache - name: cache
path: /home/eqemu/.ccache/ 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
-15
View File
@@ -56,18 +56,3 @@ bin/
/client_files/**/CMakeFiles/ /client_files/**/CMakeFiles/
.idea .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
+16
View File
@@ -0,0 +1,16 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/mysql"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++17"
}
],
"version": 4
}
+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": "cd bin && make",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "make clean",
"type": "shell",
"command": "cd bin && make clean",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "cmake",
"type": "shell",
"command": "mkdir -p bin && cd bin && 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 bin && cd 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 bin && cd 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 bin && cd 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 bin && cd bin && docker run -i --rm --privileged -v ${HOST_PROJECT_PATH}/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 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}/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}/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}/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}/bin:/src --network=eqemu --name sharedmemory eqemu/server:0.0.3 ./shared_memory && docker run --rm -v ${HOST_PROJECT_PATH}/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}/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}/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}/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
-1068
View File
File diff suppressed because it is too large Load Diff
+12 -6
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,7 +12,7 @@ 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)
@@ -20,10 +20,8 @@ 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")
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
ELSE(MSVC) ELSE(MSVC)
ADD_DEFINITIONS(-DHAS_UNION_SEMUN) ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC) ENDIF(MSVC)
@@ -123,6 +121,8 @@ ENDIF()
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)
@@ -176,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:
@@ -336,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})
+3 -3
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) |
*** ***
+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')",
+34 -57
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
@@ -33,13 +33,11 @@ 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 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
@@ -63,10 +61,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
proc_launcher.cpp proc_launcher.cpp
profanity_manager.cpp profanity_manager.cpp
ptimer.cpp ptimer.cpp
@@ -81,14 +77,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/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
@@ -125,9 +120,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
@@ -147,7 +139,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
@@ -164,7 +155,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
@@ -172,37 +162,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
@@ -212,14 +197,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
@@ -260,12 +249,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
@@ -325,7 +312,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
@@ -342,7 +328,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
@@ -350,37 +335,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
@@ -390,14 +370,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
@@ -438,12 +422,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
@@ -484,10 +466,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
@@ -509,7 +494,7 @@ SET(common_headers
dbcore.h dbcore.h
deity.h deity.h
discord/discord.h discord/discord.h
discord/discord_manager.h discord_manager.h
dynamic_zone_base.h dynamic_zone_base.h
emu_constants.h emu_constants.h
emu_limits.h emu_limits.h
@@ -532,15 +517,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
@@ -576,9 +558,7 @@ 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
proc_launcher.h proc_launcher.h
profanity_manager.h profanity_manager.h
profiler.h profiler.h
@@ -599,7 +579,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
@@ -609,11 +589,9 @@ SET(common_headers
useperl.h useperl.h
version.h version.h
zone_numbers.h zone_numbers.h
zone_store.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
@@ -662,12 +640,11 @@ 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
util/uuid.h) util/uuid.h
)
SOURCE_GROUP(Event FILES SOURCE_GROUP(Event FILES
event/event_loop.h event/event_loop.h
+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
-1
View File
@@ -20,7 +20,6 @@
#include "../common/types.h" #include "../common/types.h"
#define NO_CLASS 0
#define WARRIOR 1 #define WARRIOR 1
#define CLERIC 2 #define CLERIC 2
#define PALADIN 3 #define PALADIN 3
+6 -6
View File
@@ -158,25 +158,25 @@ bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f) bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f)
{ {
// if we're not set to (-1 All) then fail when we aren't within minimum expansion // 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) { if (f.min_expansion > Expansion::EXPANSION_ALL && current_expansion < f.min_expansion) {
return false; return false;
} }
// if we're not set to (-1 All) then fail when we aren't within max expansion // 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) { if (f.max_expansion > Expansion::EXPANSION_ALL && current_expansion > f.max_expansion) {
return false; return false;
} }
// if we don't have any enabled flag in enabled flags, we fail // if we don't have any enabled flag in enabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags)) { for (const auto& flag: SplitString(f.content_flags)) {
if (!Strings::Contains(GetContentFlagsEnabled(), flag)) { if (!contains(GetContentFlagsEnabled(), flag)) {
return false; return false;
} }
} }
// if we don't have any disabled flag in disabled flags, we fail // if we don't have any disabled flag in disabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags_disabled)) { for (const auto& flag: SplitString(f.content_flags_disabled)) {
if (!Strings::Contains(GetContentFlagsDisabled(), flag)) { if (!contains(GetContentFlagsDisabled(), flag)) {
return false; return false;
} }
} }
+5 -141
View File
@@ -1,98 +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);
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
// 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"
@@ -112,22 +20,14 @@ public:
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>& const 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)
@@ -201,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;
@@ -238,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());
@@ -267,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) {
@@ -281,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)
{ {
+248 -130
View File
@@ -45,13 +45,12 @@
#include "database.h" #include "database.h"
#include "eq_packet_structs.h" #include "eq_packet_structs.h"
#include "extprofile.h" #include "extprofile.h"
#include "strings.h" #include "string_util.h"
#include "database_schema.h" #include "database_schema.h"
#include "http/httplib.h" #include "http/httplib.h"
#include "http/uri.h" #include "http/uri.h"
#include "repositories/zone_repository.h" #include "repositories/zone_repository.h"
#include "zone_store.h"
extern Client client; extern Client client;
@@ -71,11 +70,11 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c
uint32 errnum= 0; uint32 errnum= 0;
char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf[MYSQL_ERRMSG_SIZE];
if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { if (!Open(host, user, passwd, database, port, &errnum, errbuf)) {
LogError("Connection [{}] Failed to connect to database Error [{}]", connection_label, errbuf); LogError("[MySQL] Connection [{}] Failed to connect to database: Error [{}]", connection_label, errbuf);
return false; return false;
} }
else { else {
LogInfo("Connected to database [{}] [{}] @ [{}:{}]", connection_label, database, host,port); LogInfo("[MySQL] Connection [{}] database [{}] at [{}]:[{}]", connection_label, database, host,port);
return true; return true;
} }
} }
@@ -108,7 +107,7 @@ uint32 Database::CheckLogin(const char* name, const char* password, const char *
"SELECT id, status FROM account WHERE `name` = '{}' AND ls_id = '{}' AND password is NOT NULL " "SELECT id, status FROM account WHERE `name` = '{}' AND ls_id = '{}' AND password is NOT NULL "
"AND length(password) > 0 AND (password = '{}' OR password = MD5('{}'))", "AND length(password) > 0 AND (password = '{}' OR password = MD5('{}'))",
temporary_username, temporary_username,
Strings::Escape(loginserver), EscapeString(loginserver),
temporary_password, temporary_password,
temporary_password temporary_password
); );
@@ -121,10 +120,10 @@ uint32 Database::CheckLogin(const char* name, const char* password, const char *
auto row = results.begin(); auto row = results.begin();
auto id = Strings::ToUnsignedInt(row[0]); auto id = std::stoul(row[0]);
if (oStatus) { if (oStatus) {
*oStatus = Strings::ToInt(row[1]); *oStatus = std::stoi(row[1]);
} }
return id; return id;
@@ -149,8 +148,8 @@ bool Database::CheckBannedIPs(std::string login_ip)
bool Database::AddBannedIP(std::string banned_ip, std::string notes) { bool Database::AddBannedIP(std::string banned_ip, std::string notes) {
auto query = fmt::format( auto query = fmt::format(
"INSERT into banned_ips SET ip_address = '{}', notes = '{}'", "INSERT into banned_ips SET ip_address = '{}', notes = '{}'",
Strings::Escape(banned_ip), EscapeString(banned_ip),
Strings::Escape(notes) EscapeString(notes)
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -202,11 +201,11 @@ int16 Database::CheckStatus(uint32 account_id)
} }
auto row = results.begin(); auto row = results.begin();
int16 status = Strings::ToInt(row[0]); int16 status = std::stoi(row[0]);
int32 date_diff = 0; int32 date_diff = 0;
if (row[1]) { if (row[1]) {
date_diff = Strings::ToInt(row[1]); date_diff = std::stoi(row[1]);
} }
if (date_diff > 0) { if (date_diff > 0) {
@@ -281,7 +280,7 @@ bool Database::DeleteAccount(const char* name, const char *loginserver) {
} }
bool Database::SetLocalPassword(uint32 accid, const char* password) { bool Database::SetLocalPassword(uint32 accid, const char* password) {
std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", Strings::Escape(password).c_str(), accid); std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", EscapeString(password).c_str(), accid);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -345,7 +344,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
std::string query = StringFormat("SELECT `account_id`, `name` FROM `character_data` WHERE `name` = '%s'", name); std::string query = StringFormat("SELECT `account_id`, `name` FROM `character_data` WHERE `name` = '%s'", name);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
if (row[0] && Strings::ToInt(row[0]) > 0){ if (row[0] && atoi(row[0]) > 0){
LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name); LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name);
return false; return false;
} }
@@ -376,8 +375,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
* @param character_name * @param character_name
* @return * @return
*/ */
bool Database::DeleteCharacter(char *character_name) bool Database::DeleteCharacter(char *character_name) {
{
uint32 character_id = 0; uint32 character_id = 0;
if(!character_name || !strlen(character_name)) { if(!character_name || !strlen(character_name)) {
LogInfo("DeleteCharacter: request to delete without a name (empty char slot)"); LogInfo("DeleteCharacter: request to delete without a name (empty char slot)");
@@ -387,18 +385,18 @@ bool Database::DeleteCharacter(char *character_name)
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", character_name); std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", character_name);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
character_id = Strings::ToInt(row[0]); character_id = atoi(row[0]);
} }
if (character_id <= 0) { if (character_id <= 0) {
LogError("Invalid Character ID [{}]", character_name); LogError("DeleteCharacter | Invalid Character ID [{}]", character_name);
return false; return false;
} }
std::string delete_type = "hard-deleted"; std::string delete_type = "hard-deleted";
if (RuleB(Character, SoftDeletes)) { if (RuleB(Character, SoftDeletes)) {
delete_type = "soft-deleted"; delete_type = "soft-deleted";
query = fmt::format( std::string query = fmt::format(
SQL( SQL(
UPDATE UPDATE
character_data character_data
@@ -413,30 +411,11 @@ bool Database::DeleteCharacter(char *character_name)
QueryDatabase(query); QueryDatabase(query);
if (RuleB(Bots, Enabled)) {
query = fmt::format(
SQL(
UPDATE
bot_data
SET
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64)
WHERE
owner_id = '{}'
),
character_id
);
QueryDatabase(query);
LogInfo(
"[DeleteCharacter] character_name [{}] ({}) bots are being [{}]",
character_name,
character_id,
delete_type
);
}
return true; return true;
} }
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
for (const auto& iter : DatabaseSchema::GetCharacterTables()) { for (const auto& iter : DatabaseSchema::GetCharacterTables()) {
std::string table_name = iter.first; std::string table_name = iter.first;
std::string character_id_column_name = iter.second; std::string character_id_column_name = iter.second;
@@ -444,7 +423,11 @@ bool Database::DeleteCharacter(char *character_name)
QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id)); QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id));
} }
LogInfo("character_name [{}] ({}) is being [{}]", character_name, character_id, delete_type); #ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
QueryDatabase(query);
#endif
return true; return true;
} }
@@ -636,8 +619,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
")", ")",
character_id, // " id, " character_id, // " id, "
account_id, // " account_id, " account_id, // " account_id, "
Strings::Escape(pp->name).c_str(), // " `name`, " EscapeString(pp->name).c_str(), // " `name`, "
Strings::Escape(pp->last_name).c_str(), // " last_name, " EscapeString(pp->last_name).c_str(), // " last_name, "
pp->gender, // " gender, " pp->gender, // " gender, "
pp->race, // " race, " pp->race, // " race, "
pp->class_, // " class, " pp->class_, // " class, "
@@ -661,8 +644,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
pp->ability_number, // " ability_number, " pp->ability_number, // " ability_number, "
pp->ability_time_minutes, // " ability_time_minutes, " pp->ability_time_minutes, // " ability_time_minutes, "
pp->ability_time_hours, // " ability_time_hours, " pp->ability_time_hours, // " ability_time_hours, "
Strings::Escape(pp->title).c_str(), // " title, " EscapeString(pp->title).c_str(), // " title, "
Strings::Escape(pp->suffix).c_str(), // " suffix, " EscapeString(pp->suffix).c_str(), // " suffix, "
pp->exp, // " exp, " pp->exp, // " exp, "
pp->points, // " points, " pp->points, // " points, "
pp->mana, // " mana, " pp->mana, // " mana, "
@@ -787,7 +770,7 @@ uint32 Database::GetCharacterID(const char *name) {
auto row = results.begin(); auto row = results.begin();
if (results.RowCount() == 1) if (results.RowCount() == 1)
{ {
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
return 0; return 0;
} }
@@ -798,7 +781,7 @@ uint32 Database::GetCharacterID(const char *name) {
Zero will also be returned if there is a database error. Zero will also be returned if there is a database error.
*/ */
uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) {
std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", Strings::Escape(charname).c_str()); std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", EscapeString(charname).c_str());
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -812,10 +795,10 @@ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) {
auto row = results.begin(); auto row = results.begin();
uint32 accountId = Strings::ToInt(row[0]); uint32 accountId = atoi(row[0]);
if (oCharID) if (oCharID)
*oCharID = Strings::ToInt(row[1]); *oCharID = atoi(row[1]);
return accountId; return accountId;
} }
@@ -832,7 +815,7 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) {
return 0; return 0;
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
uint32 Database::GetAccountIDByName(std::string account_name, std::string loginserver, int16* status, uint32* lsid) { uint32 Database::GetAccountIDByName(std::string account_name, std::string loginserver, int16* status, uint32* lsid) {
@@ -842,8 +825,8 @@ uint32 Database::GetAccountIDByName(std::string account_name, std::string logins
auto query = fmt::format( auto query = fmt::format(
"SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '{}' AND `ls_id` = '{}' LIMIT 1", "SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '{}' AND `ls_id` = '{}' LIMIT 1",
Strings::Escape(account_name), EscapeString(account_name),
Strings::Escape(loginserver) EscapeString(loginserver)
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -852,14 +835,14 @@ uint32 Database::GetAccountIDByName(std::string account_name, std::string logins
} }
auto row = results.begin(); auto row = results.begin();
auto account_id = Strings::ToUnsignedInt(row[0]); auto account_id = std::stoul(row[0]);
if (status) { if (status) {
*status = static_cast<int16>(Strings::ToInt(row[1])); *status = static_cast<int16>(std::stoi(row[1]));
} }
if (lsid) { if (lsid) {
*lsid = row[2] ? Strings::ToUnsignedInt(row[2]) : 0; *lsid = row[2] ? std::stoul(row[2]) : 0;
} }
return account_id; return account_id;
@@ -880,7 +863,7 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID
strcpy(name, row[0]); strcpy(name, row[0]);
if (row[1] && oLSAccountID) { if (row[1] && oLSAccountID) {
*oLSAccountID = Strings::ToInt(row[1]); *oLSAccountID = atoi(row[1]);
} }
} }
@@ -968,15 +951,13 @@ bool Database::LoadVariables() {
std::string key, value; std::string key, value;
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
varcache.last_update = Strings::ToInt(row[2]); // ahh should we be comparing if this is newer? varcache.last_update = atoi(row[2]); // ahh should we be comparing if this is newer?
key = row[0]; key = row[0];
value = row[1]; value = row[1];
std::transform(std::begin(key), std::end(key), std::begin(key), ::tolower); // keys are lower case, DB doesn't have to be std::transform(std::begin(key), std::end(key), std::begin(key), ::tolower); // keys are lower case, DB doesn't have to be
varcache.Add(key, value); varcache.Add(key, value);
} }
LogInfo("Loaded [{}] variable(s)", Strings::Commify(std::to_string(results.RowCount())));
return true; return true;
} }
@@ -1001,8 +982,8 @@ bool Database::GetVariable(std::string varname, std::string &varvalue)
bool Database::SetVariable(const std::string varname, const std::string &varvalue) bool Database::SetVariable(const std::string varname, const std::string &varvalue)
{ {
std::string escaped_name = Strings::Escape(varname); std::string escaped_name = EscapeString(varname);
std::string escaped_value = Strings::Escape(varvalue); std::string escaped_value = EscapeString(varvalue);
std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str()); std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str());
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -1037,6 +1018,97 @@ void Database::SetAccountCRCField(uint32 account_id, std::string field_name, uin
); );
} }
// Get zone starting points from DB
bool Database::GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x, float* safe_y, float* safe_z, float* safe_heading, int16* min_status, uint8* min_level, char *flag_needed) {
if (zone_short_name == nullptr)
return false;
std::string query = fmt::format(
SQL(
SELECT
`safe_x`, `safe_y`, `safe_z`, `safe_heading`, `min_status`, `min_level`, `flag_needed`
FROM
zone
WHERE
`short_name` = '{}'
AND
(`version` = {} OR `version` = 0)
ORDER BY `version` DESC
), zone_short_name, instance_version
);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() == 0)
return false;
auto row = results.begin();
if (safe_x != nullptr)
*safe_x = atof(row[0]);
if (safe_y != nullptr)
*safe_y = atof(row[1]);
if (safe_z != nullptr)
*safe_z = atof(row[2]);
if (safe_heading != nullptr)
*safe_heading = atof(row[3]);
if (min_status != nullptr)
*min_status = atoi(row[4]);
if (min_level != nullptr)
*min_level = atoi(row[5]);
if (flag_needed != nullptr)
strcpy(flag_needed, row[6]);
return true;
}
bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) {
std::string query = StringFormat("SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
if (results.RowCount() == 0)
return false;
auto row = results.begin();
if (long_name != nullptr)
*long_name = strcpy(new char[strlen(row[0])+1], row[0]);
if (file_name != nullptr) {
if (row[1] == nullptr)
strcpy(file_name, short_name);
else
strcpy(file_name, row[1]);
}
if (safe_x != nullptr)
*safe_x = atof(row[2]);
if (safe_y != nullptr)
*safe_y = atof(row[3]);
if (safe_z != nullptr)
*safe_z = atof(row[4]);
if (graveyard_id != nullptr)
*graveyard_id = atoi(row[5]);
if (maxclients != nullptr)
*maxclients = atoi(row[6]);
return true;
}
bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) {
std::string query = StringFormat("SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id); std::string query = StringFormat("SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id);
@@ -1052,29 +1124,39 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon
auto row = results.begin(); auto row = results.begin();
if(graveyard_zoneid != nullptr) if(graveyard_zoneid != nullptr)
*graveyard_zoneid = Strings::ToInt(row[0]); *graveyard_zoneid = atoi(row[0]);
if(graveyard_x != nullptr) if(graveyard_x != nullptr)
*graveyard_x = Strings::ToFloat(row[1]); *graveyard_x = atof(row[1]);
if(graveyard_y != nullptr) if(graveyard_y != nullptr)
*graveyard_y = Strings::ToFloat(row[2]); *graveyard_y = atof(row[2]);
if(graveyard_z != nullptr) if(graveyard_z != nullptr)
*graveyard_z = Strings::ToFloat(row[3]); *graveyard_z = atof(row[3]);
if(graveyard_heading != nullptr) if(graveyard_heading != nullptr)
*graveyard_heading = Strings::ToFloat(row[4]); *graveyard_heading = atof(row[4]);
return true; return true;
} }
uint8 Database::GetPEQZone(uint32 zone_id, uint32 version){ uint8 Database::GetPEQZone(uint32 zone_id, uint32 version){
std::string query = fmt::format(
"SELECT peqzone FROM zone WHERE zoneidnumber = {} AND (version = {} OR version = 0) ORDER BY version DESC LIMIT 1",
zone_id,
version
);
auto results = QueryDatabase(query);
auto z = GetZoneVersionWithFallback(zone_id, version); if (!results.Success() || !results.RowCount()) {
return 0;
}
return z ? z->peqzone : 0; auto row = results.begin();
return static_cast<uint8>(std::stoi(row[0]));
} }
bool Database::CheckNameFilter(std::string name, bool surname) bool Database::CheckNameFilter(std::string name, bool surname)
{ {
name = Strings::ToLower(name); name = str_tolower(name);
// the minimum 4 is enforced by the client too // the minimum 4 is enforced by the client too
if (name.empty() || name.size() < 4) { if (name.empty() || name.size() < 4) {
@@ -1114,7 +1196,7 @@ bool Database::CheckNameFilter(std::string name, bool surname)
} }
for (auto row : results) { for (auto row : results) {
std::string current_row = Strings::ToLower(row[0]); std::string current_row = str_tolower(row[0]);
if (name.find(current_row) != std::string::npos) { if (name.find(current_row) != std::string::npos) {
return false; return false;
} }
@@ -1168,13 +1250,13 @@ uint32 Database::GetAccountIDFromLSID(
} }
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
account_id = Strings::ToInt(row[0]); account_id = std::stoi(row[0]);
if (in_account_name) { if (in_account_name) {
strcpy(in_account_name, row[1]); strcpy(in_account_name, row[1]);
} }
if (in_status) { if (in_status) {
*in_status = Strings::ToInt(row[2]); *in_status = std::stoi(row[2]);
} }
} }
@@ -1198,7 +1280,7 @@ void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) {
if (oAccountName) if (oAccountName)
strcpy(oAccountName, row[0]); strcpy(oAccountName, row[0]);
if (oStatus) if (oStatus)
*oStatus = Strings::ToInt(row[1]); *oStatus = atoi(row[1]);
} }
void Database::ClearMerchantTemp(){ void Database::ClearMerchantTemp(){
@@ -1244,7 +1326,7 @@ uint8 Database::GetServerType() {
return 0; return 0;
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
bool Database::MoveCharacterToZone(uint32 character_id, uint32 zone_id) bool Database::MoveCharacterToZone(uint32 character_id, uint32 zone_id)
@@ -1281,6 +1363,44 @@ bool Database::MoveCharacterToZone(const char *charname, uint32 zone_id)
return results.RowsAffected() != 0; return results.RowsAffected() != 0;
} }
bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) {
std::string query = StringFormat("INSERT INTO `hackers` (account, name, hacked) values('%s','%s','%s')", accountname, charactername, hacked);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
return results.RowsAffected() != 0;
}
bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) {
//Utilize the "hacker" table, but also give zone information.
std::string query = StringFormat("INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone);
auto results = QueryDatabase(query);
if (!results.Success())
{
return false;
}
return results.RowsAffected() != 0;
}
bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const std::string &hacked, const char* zone) {
//Utilize the "hacker" table, but also give zone information.
auto query = fmt::format("INSERT INTO hackers(account, name, hacked, zone) values('{}', '{}', '{}', '{}')",
accountname, charactername, hacked, zone);
auto results = QueryDatabase(query);
if (!results.Success())
{
return false;
}
return results.RowsAffected() != 0;
}
uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race)
{ {
uint16 race_cap = 0; uint16 race_cap = 0;
@@ -1296,7 +1416,7 @@ uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race)
return 0; return 0;
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level) uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level)
@@ -1312,12 +1432,12 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16
if (results.Success() && results.RowsAffected() != 0) if (results.Success() && results.RowsAffected() != 0)
{ {
auto row = results.begin(); auto row = results.begin();
skill_level = Strings::ToInt(row[0]); skill_level = atoi(row[0]);
skill_formula = Strings::ToInt(row[1]); skill_formula = atoi(row[1]);
skill_cap = Strings::ToInt(row[2]); skill_cap = atoi(row[2]);
if (Strings::ToInt(row[3]) > skill_cap) if (atoi(row[3]) > skill_cap)
skill_cap2 = (Strings::ToInt(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level. skill_cap2 = (atoi(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level.
skill_cap3 = Strings::ToInt(row[4]); skill_cap3 = atoi(row[4]);
} }
int race_skill = GetRaceSkill(skillid,in_race); int race_skill = GetRaceSkill(skillid,in_race);
@@ -1353,7 +1473,7 @@ uint32 Database::GetCharacterInfo(std::string character_name, uint32 *account_id
{ {
auto query = fmt::format( auto query = fmt::format(
"SELECT `id`, `account_id`, `zone_id`, `zone_instance` FROM `character_data` WHERE `name` = '{}'", "SELECT `id`, `account_id`, `zone_id`, `zone_instance` FROM `character_data` WHERE `name` = '{}'",
Strings::Escape(character_name) EscapeString(character_name)
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -1362,10 +1482,10 @@ uint32 Database::GetCharacterInfo(std::string character_name, uint32 *account_id
} }
auto row = results.begin(); auto row = results.begin();
auto character_id = Strings::ToUnsignedInt(row[0]); auto character_id = std::stoul(row[0]);
*account_id = Strings::ToUnsignedInt(row[1]); *account_id = std::stoul(row[1]);
*zone_id = Strings::ToUnsignedInt(row[2]); *zone_id = std::stoul(row[2]);
*instance_id = Strings::ToUnsignedInt(row[3]); *instance_id = std::stoul(row[3]);
return character_id; return character_id;
} }
@@ -1426,7 +1546,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines
auto escape_str = new char[lines.size() * 2 + 1]; auto escape_str = new char[lines.size() * 2 + 1];
DoEscapeString(escape_str, lines.c_str(), lines.size()); DoEscapeString(escape_str, lines.c_str(), lines.size());
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", Strings::Escape(who).c_str(), Strings::Escape(against).c_str(), escape_str); std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str);
QueryDatabase(query); QueryDatabase(query);
safe_delete_array(escape_str); safe_delete_array(escape_str);
} }
@@ -1488,7 +1608,7 @@ uint32 Database::GetGroupID(const char* name){
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
std::string Database::GetGroupLeaderForLogin(std::string character_name) { std::string Database::GetGroupLeaderForLogin(std::string character_name) {
@@ -1502,7 +1622,7 @@ std::string Database::GetGroupLeaderForLogin(std::string character_name) {
if (results.Success() && results.RowCount()) { if (results.Success() && results.RowCount()) {
auto row = results.begin(); auto row = results.begin();
group_id = Strings::ToUnsignedInt(row[0]); group_id = std::stoul(row[0]);
} }
if (!group_id) { if (!group_id) {
@@ -1524,7 +1644,7 @@ std::string Database::GetGroupLeaderForLogin(std::string character_name) {
} }
void Database::SetGroupLeaderName(uint32 gid, const char* name) { void Database::SetGroupLeaderName(uint32 gid, const char* name) {
std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", Strings::Escape(name).c_str(), gid); std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", EscapeString(name).c_str(), gid);
auto result = QueryDatabase(query); auto result = QueryDatabase(query);
if(result.RowsAffected() != 0) { if(result.RowsAffected() != 0) {
@@ -1532,7 +1652,7 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) {
} }
query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')", query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')",
gid, Strings::Escape(name).c_str()); gid, EscapeString(name).c_str());
result = QueryDatabase(query); result = QueryDatabase(query);
if(!result.Success()) { if(!result.Success()) {
@@ -1591,7 +1711,7 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta
strcpy(mentoree, row[5]); strcpy(mentoree, row[5]);
if (mentor_percent) if (mentor_percent)
*mentor_percent = Strings::ToInt(row[6]); *mentor_percent = atoi(row[6]);
if(GLAA && results.LengthOfColumn(7) == sizeof(GroupLeadershipAA_Struct)) if(GLAA && results.LengthOfColumn(7) == sizeof(GroupLeadershipAA_Struct))
memcpy(GLAA, row[7], sizeof(GroupLeadershipAA_Struct)); memcpy(GLAA, row[7], sizeof(GroupLeadershipAA_Struct));
@@ -1638,7 +1758,7 @@ uint8 Database::GetAgreementFlag(uint32 acctid) {
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
void Database::SetAgreementFlag(uint32 acctid) { void Database::SetAgreementFlag(uint32 acctid) {
@@ -1724,7 +1844,7 @@ uint32 Database::GetRaidID(const char* name)
} }
if (row[0]) // would it ever be possible to have a null here? if (row[0]) // would it ever be possible to have a null here?
return Strings::ToInt(row[0]); return atoi(row[0]);
return 0; return 0;
} }
@@ -1807,7 +1927,7 @@ void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank,
strcpy(mentoree, row[4]); strcpy(mentoree, row[4]);
if (mentor_percent) if (mentor_percent)
*mentor_percent = Strings::ToInt(row[5]); *mentor_percent = atoi(row[5]);
if (GLAA && results.LengthOfColumn(6) == sizeof(GroupLeadershipAA_Struct)) if (GLAA && results.LengthOfColumn(6) == sizeof(GroupLeadershipAA_Struct))
memcpy(GLAA, row[6], sizeof(GroupLeadershipAA_Struct)); memcpy(GLAA, row[6], sizeof(GroupLeadershipAA_Struct));
@@ -1980,16 +2100,16 @@ bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as)
auto row = results.begin(); auto row = results.begin();
as->success.guk = Strings::ToInt(row[0]); as->success.guk = atoi(row[0]);
as->success.mir = Strings::ToInt(row[1]); as->success.mir = atoi(row[1]);
as->success.mmc = Strings::ToInt(row[2]); as->success.mmc = atoi(row[2]);
as->success.ruj = Strings::ToInt(row[3]); as->success.ruj = atoi(row[3]);
as->success.tak = Strings::ToInt(row[4]); as->success.tak = atoi(row[4]);
as->failure.guk = Strings::ToInt(row[5]); as->failure.guk = atoi(row[5]);
as->failure.mir = Strings::ToInt(row[6]); as->failure.mir = atoi(row[6]);
as->failure.mmc = Strings::ToInt(row[7]); as->failure.mmc = atoi(row[7]);
as->failure.ruj = Strings::ToInt(row[8]); as->failure.ruj = atoi(row[8]);
as->failure.tak = Strings::ToInt(row[9]); as->failure.tak = atoi(row[9]);
as->failure.total = as->failure.guk + as->failure.mir + as->failure.mmc + as->failure.ruj + as->failure.tak; as->failure.total = as->failure.guk + as->failure.mir + as->failure.mmc + as->failure.ruj + as->failure.tak;
as->success.total = as->success.guk + as->success.mir + as->success.mmc + as->success.ruj + as->success.tak; as->success.total = as->success.guk + as->success.mir + as->success.mmc + as->success.ruj + as->success.tak;
@@ -2008,7 +2128,7 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
return 0; return 0;
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
uint32 Database::GetGroupIDByCharID(uint32 character_id) uint32 Database::GetGroupIDByCharID(uint32 character_id)
@@ -2030,7 +2150,7 @@ uint32 Database::GetGroupIDByCharID(uint32 character_id)
return 0; return 0;
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
uint32 Database::GetRaidIDByCharID(uint32 character_id) { uint32 Database::GetRaidIDByCharID(uint32 character_id) {
@@ -2044,7 +2164,7 @@ uint32 Database::GetRaidIDByCharID(uint32 character_id) {
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
return Strings::ToInt(row[0]); return atoi(row[0]);
} }
return 0; return 0;
} }
@@ -2058,7 +2178,7 @@ int Database::CountInvSnapshots() {
auto row = results.begin(); auto row = results.begin();
int64 count = Strings::ToBigInt(row[0]); int64 count = atoll(row[0]);
if (count > 2147483647) if (count > 2147483647)
return -2; return -2;
if (count < 0) if (count < 0)
@@ -2094,12 +2214,12 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
else{ else{
auto row = results.begin(); auto row = results.begin();
eqTime.minute = Strings::ToInt(row[0]); eqTime.minute = atoi(row[0]);
eqTime.hour = Strings::ToInt(row[1]); eqTime.hour = atoi(row[1]);
eqTime.day = Strings::ToInt(row[2]); eqTime.day = atoi(row[2]);
eqTime.month = Strings::ToInt(row[3]); eqTime.month = atoi(row[3]);
eqTime.year = Strings::ToInt(row[4]); eqTime.year = atoi(row[4]);
realtime = Strings::ToInt(row[5]); realtime = atoi(row[5]);
} }
return eqTime; return eqTime;
@@ -2126,7 +2246,7 @@ int Database::GetIPExemption(std::string account_ip) {
} }
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]); return std::stoi(row[0]);
} }
void Database::SetIPExemption(std::string account_ip, int exemption_amount) { void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
@@ -2140,7 +2260,7 @@ void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (results.Success() && results.RowCount()) { if (results.Success() && results.RowCount()) {
auto row = results.begin(); auto row = results.begin();
exemption_id = Strings::ToUnsignedInt(row[0]); exemption_id = std::stoul(row[0]);
} }
query = fmt::format( query = fmt::format(
@@ -2166,7 +2286,7 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
if (results.Success() && results.RowCount() > 0) { if (results.Success() && results.RowCount() > 0) {
auto row = results.begin(); auto row = results.begin();
return Strings::ToInt(row[0]);; return atoi(row[0]);;
} }
return 0; return 0;
@@ -2179,9 +2299,9 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
* @return * @return
*/ */
bool Database::CopyCharacter( bool Database::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
) )
{ {
auto results = QueryDatabase( auto results = QueryDatabase(
@@ -2193,7 +2313,6 @@ bool Database::CopyCharacter(
if (results.RowCount() == 0) { if (results.RowCount() == 0) {
LogError("No character found with name [{}]", source_character_name); LogError("No character found with name [{}]", source_character_name);
return false;
} }
auto row = results.begin(); auto row = results.begin();
@@ -2208,7 +2327,6 @@ bool Database::CopyCharacter(
if (results.RowCount() == 0) { if (results.RowCount() == 0) {
LogError("No account found with name [{}]", destination_account_name); LogError("No account found with name [{}]", destination_account_name);
return false;
} }
row = results.begin(); row = results.begin();
@@ -2240,7 +2358,7 @@ bool Database::CopyCharacter(
results = QueryDatabase( results = QueryDatabase(
fmt::format( fmt::format(
"SELECT {} FROM {} WHERE {} = {}", "SELECT {} FROM {} WHERE {} = {}",
Strings::Implode(",", Strings::Wrap(columns, "`")), implode(",", wrap(columns, "`")),
table_name, table_name,
character_id_column_name, character_id_column_name,
source_character_id source_character_id
@@ -2276,7 +2394,7 @@ bool Database::CopyCharacter(
std::vector<std::string> insert_rows; std::vector<std::string> insert_rows;
for (auto &r: new_rows) { for (auto &r: new_rows) {
std::string insert_row = "(" + Strings::Implode(",", Strings::Wrap(r, "'")) + ")"; std::string insert_row = "(" + implode(",", wrap(r, "'")) + ")";
insert_rows.emplace_back(insert_row); insert_rows.emplace_back(insert_row);
} }
@@ -2294,8 +2412,8 @@ bool Database::CopyCharacter(
fmt::format( fmt::format(
"INSERT INTO {} ({}) VALUES {}", "INSERT INTO {} ({}) VALUES {}",
table_name, table_name,
Strings::Implode(",", Strings::Wrap(columns, "`")), implode(",", wrap(columns, "`")),
Strings::Implode(",", insert_rows) implode(",", insert_rows)
) )
); );
@@ -2318,7 +2436,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
uri request_uri(url); uri request_uri(url);
LogHTTP( LogHTTP(
"parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]", "[SourceDatabaseTableFromUrl] parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]",
url, url,
request_uri.get_path(), request_uri.get_path(),
request_uri.get_host(), request_uri.get_host(),
@@ -2347,8 +2465,8 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
if (auto res = cli.Get(request_uri.get_path().c_str())) { if (auto res = cli.Get(request_uri.get_path().c_str())) {
if (res->status == 200) { if (res->status == 200) {
for (auto &s: Strings::Split(res->body, ';')) { for (auto &s: SplitString(res->body, ';')) {
if (!Strings::Trim(s).empty()) { if (!trim(s).empty()) {
auto results = QueryDatabase(s); auto results = QueryDatabase(s);
if (!results.ErrorMessage().empty()) { if (!results.ErrorMessage().empty()) {
LogError("Error sourcing SQL [{}]", results.ErrorMessage()); LogError("Error sourcing SQL [{}]", results.ErrorMessage());
@@ -2372,7 +2490,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
} }
catch (std::invalid_argument iae) { catch (std::invalid_argument iae) {
LogError("URI parser error [{}]", iae.what()); LogError("[SourceDatabaseTableFromUrl] URI parser error [{}]", iae.what());
} }
} }
+21 -13
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;
@@ -106,11 +108,14 @@ 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 */
@@ -140,30 +145,31 @@ public:
/* 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);
@@ -240,7 +246,9 @@ public:
/* 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); uint8 GetPEQZone(uint32 zone_id, uint32 version);
+120 -48
View File
@@ -23,11 +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 <ctime> #include <ctime>
@@ -41,6 +40,38 @@
#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
*/ */
@@ -57,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;
} }
@@ -68,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;
} }
@@ -86,9 +117,9 @@ 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);
} }
/** /**
@@ -118,53 +149,109 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
); );
} }
/**
* @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) {
tables_list += table + " ";
} }
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetBotTablesList() std::string DatabaseDumpService::GetBotTablesList()
{ {
return Strings::Join(DatabaseSchema::GetBotTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetBotTables();
for (const auto &table : tables) {
tables_list += table + " ";
} }
std::string DatabaseDumpService::GetMercTablesList() return trim(tables_list);
{
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);
} }
/** /**
@@ -250,11 +337,6 @@ void DatabaseDumpService::Dump()
dump_descriptor += "-bots"; 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";
@@ -301,12 +383,12 @@ void DatabaseDumpService::Dump()
pipe_file pipe_file
); );
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
File::Makedir(GetSetDumpPath()); FileUtil::mkdir(GetSetDumpPath());
} }
if (IsDumpDropTableSyntaxOnly()) { if (IsDumpDropTableSyntaxOnly()) {
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' '); std::vector<std::string> tables = SplitString(tables_to_dump, ' ');
for (auto &table : tables) { for (auto &table : tables) {
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl; std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
@@ -317,14 +399,14 @@ void DatabaseDumpService::Dump()
} }
} }
else { else {
std::string execution_result = Process::execute(execute_command); std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
if (!execution_result.empty() && IsDumpOutputToConsole()) { if (!execution_result.empty()) {
std::cout << execution_result; std::cout << execution_result;
} }
} }
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());
@@ -334,7 +416,7 @@ void DatabaseDumpService::Dump()
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(),
@@ -345,7 +427,7 @@ void DatabaseDumpService::Dump()
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath()); LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
} }
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(),
@@ -525,13 +607,3 @@ void DatabaseDumpService::SetDumpBotTables(bool dump_bot_tables)
{ {
DatabaseDumpService::dump_bot_tables = 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;
}
+1 -4
View File
@@ -55,8 +55,6 @@ public:
void SetDumpStateTables(bool dump_state_tables); void SetDumpStateTables(bool dump_state_tables);
bool IsDumpBotTables() const; bool IsDumpBotTables() const;
void SetDumpBotTables(bool dump_bot_tables); void SetDumpBotTables(bool dump_bot_tables);
bool IsDumpMercTables() const;
void SetDumpMercTables(bool dump_bot_tables);
private: private:
bool dump_all_tables = false; bool dump_all_tables = false;
@@ -72,16 +70,15 @@ private:
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_bot_tables = false;
bool dump_merc_tables = 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 GetBotTablesList();
std::string GetMercTablesList();
std::string GetSystemTablesList(); std::string GetSystemTablesList();
std::string GetStateTablesList(); std::string GetStateTablesList();
std::string GetContentTablesList(); std::string GetContentTablesList();
+23 -33
View File
@@ -18,12 +18,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h" #include "../common/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 "database.h" #include "database.h"
#include "extprofile.h" #include "extprofile.h"
#include "path_manager.h"
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
@@ -476,17 +475,8 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertPPDeblob(); CheckDatabaseConvertPPDeblob();
CheckDatabaseConvertCorpseDeblob(); CheckDatabaseConvertCorpseDeblob();
auto *r = RuleManager::Instance();
r->LoadRules(this, "default", false);
if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) {
LogInfo("Bot tables found but rule not enabled, enabling");
r->SetRule("Bots:Enabled", "true", this, true, true);
}
/* Run EQEmu Server script (Checks for database updates) */ /* Run EQEmu Server script (Checks for database updates) */
system("perl eqemu_server.pl ran_from_world");
const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath());
system(fmt::format("perl {} ran_from_world", file).c_str());
return true; return true;
} }
@@ -530,7 +520,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
rquery = StringFormat("SELECT COUNT(`id`) FROM `character_`"); rquery = StringFormat("SELECT COUNT(`id`) FROM `character_`");
results = QueryDatabase(rquery); results = QueryDatabase(rquery);
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
number_of_characters = Strings::ToInt(row[0]); number_of_characters = atoi(row[0]);
printf("Number of Characters in Database: %i \n", number_of_characters); printf("Number of Characters in Database: %i \n", number_of_characters);
} }
@@ -929,19 +919,19 @@ bool Database::CheckDatabaseConvertPPDeblob(){
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
char_iter_count++; char_iter_count++;
squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", Strings::ToInt(row[0])); squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", atoi(row[0]));
auto results2 = QueryDatabase(squery); auto results2 = QueryDatabase(squery);
auto row2 = results2.begin(); auto row2 = results2.begin();
pp = (Convert::PlayerProfile_Struct*)row2[1]; pp = (Convert::PlayerProfile_Struct*)row2[1];
e_pp = (ExtendedProfile_Struct*)row2[11]; e_pp = (ExtendedProfile_Struct*)row2[11];
character_id = Strings::ToInt(row[0]); character_id = atoi(row[0]);
account_id = Strings::ToInt(row2[4]); account_id = atoi(row2[4]);
/* Convert some data from the character_ table that is still relevant */ /* Convert some data from the character_ table that is still relevant */
firstlogon = Strings::ToInt(row2[5]); firstlogon = atoi(row2[5]);
lfg = Strings::ToInt(row2[6]); lfg = atoi(row2[6]);
lfp = Strings::ToInt(row2[7]); lfp = atoi(row2[7]);
mailkey = row2[8]; mailkey = row2[8];
xtargets = Strings::ToInt(row2[9]); xtargets = atoi(row2[9]);
inspectmessage = row2[10]; inspectmessage = row2[10];
/* Verify PP Integrity */ /* Verify PP Integrity */
@@ -971,7 +961,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)" std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)"
"VALUES (%u, '%s')", "VALUES (%u, '%s')",
character_id, character_id,
Strings::Escape(inspectmessage).c_str() EscapeString(inspectmessage).c_str()
); );
auto results = QueryDatabase(rquery); auto results = QueryDatabase(rquery);
} }
@@ -1208,8 +1198,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
")", ")",
character_id, character_id,
account_id, account_id,
Strings::Escape(pp->name).c_str(), EscapeString(pp->name).c_str(),
Strings::Escape(pp->last_name).c_str(), EscapeString(pp->last_name).c_str(),
pp->gender, pp->gender,
pp->race, pp->race,
pp->class_, pp->class_,
@@ -1233,8 +1223,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
pp->ability_number, pp->ability_number,
pp->ability_time_minutes, pp->ability_time_minutes,
pp->ability_time_hours, pp->ability_time_hours,
Strings::Escape(pp->title).c_str(), EscapeString(pp->title).c_str(),
Strings::Escape(pp->suffix).c_str(), EscapeString(pp->suffix).c_str(),
pp->exp, pp->exp,
pp->points, pp->points,
pp->mana, pp->mana,
@@ -1567,7 +1557,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
rquery = StringFormat("SELECT DISTINCT charid FROM character_corpses"); rquery = StringFormat("SELECT DISTINCT charid FROM character_corpses");
results = QueryDatabase(rquery); results = QueryDatabase(rquery);
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
std::string squery = StringFormat("SELECT id, charname, data, time_of_death, is_rezzed FROM character_corpses WHERE `charid` = %i", Strings::ToInt(row[0])); std::string squery = StringFormat("SELECT id, charname, data, time_of_death, is_rezzed FROM character_corpses WHERE `charid` = %i", atoi(row[0]));
auto results2 = QueryDatabase(squery); auto results2 = QueryDatabase(squery);
for (auto row2 = results2.begin(); row2 != results2.end(); ++row2) { for (auto row2 = results2.begin(); row2 != results2.end(); ++row2) {
in_datasize = results2.LengthOfColumn(2); in_datasize = results2.LengthOfColumn(2);
@@ -1599,7 +1589,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
c_type = "NULL"; c_type = "NULL";
continue; continue;
} }
std::cout << "Converting Corpse: [OK] [" << c_type << "]: " << "ID: " << Strings::ToInt(row2[0]) << std::endl; std::cout << "Converting Corpse: [OK] [" << c_type << "]: " << "ID: " << atoi(row2[0]) << std::endl;
if (is_sof){ if (is_sof){
scquery = StringFormat("UPDATE `character_corpses` SET \n" scquery = StringFormat("UPDATE `character_corpses` SET \n"
@@ -1670,7 +1660,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
dbpc->item_tint[6].color, dbpc->item_tint[6].color,
dbpc->item_tint[7].color, dbpc->item_tint[7].color,
dbpc->item_tint[8].color, dbpc->item_tint[8].color,
Strings::ToInt(row2[0]) atoi(row2[0])
); );
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } if (scquery != ""){ auto sc_results = QueryDatabase(scquery); }
@@ -1682,7 +1672,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" scquery = StringFormat("REPLACE INTO `character_corpse_items` \n"
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n"
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
Strings::ToInt(row2[0]), atoi(row2[0]),
dbpc->items[i].equipSlot, dbpc->items[i].equipSlot,
dbpc->items[i].item_id, dbpc->items[i].item_id,
dbpc->items[i].charges, dbpc->items[i].charges,
@@ -1698,7 +1688,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
} }
else{ else{
scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
Strings::ToInt(row2[0]), atoi(row2[0]),
dbpc->items[i].equipSlot, dbpc->items[i].equipSlot,
dbpc->items[i].item_id, dbpc->items[i].item_id,
dbpc->items[i].charges, dbpc->items[i].charges,
@@ -1778,7 +1768,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
dbpc_c->item_tint[6].color, dbpc_c->item_tint[6].color,
dbpc_c->item_tint[7].color, dbpc_c->item_tint[7].color,
dbpc_c->item_tint[8].color, dbpc_c->item_tint[8].color,
Strings::ToInt(row2[0]) atoi(row2[0])
); );
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } if (scquery != ""){ auto sc_results = QueryDatabase(scquery); }
@@ -1791,7 +1781,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" scquery = StringFormat("REPLACE INTO `character_corpse_items` \n"
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n"
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
Strings::ToInt(row2[0]), atoi(row2[0]),
dbpc_c->items[i].equipSlot, dbpc_c->items[i].equipSlot,
dbpc_c->items[i].item_id, dbpc_c->items[i].item_id,
dbpc_c->items[i].charges, dbpc_c->items[i].charges,
@@ -1807,7 +1797,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
} }
else{ else{
scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
Strings::ToInt(row2[0]), atoi(row2[0]),
dbpc_c->items[i].equipSlot, dbpc_c->items[i].equipSlot,
dbpc_c->items[i].item_id, dbpc_c->items[i].item_id,
dbpc_c->items[i].charges, dbpc_c->items[i].charges,
+310 -249
View File
@@ -18,18 +18,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h" #include "../common/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 "database.h" #include "database.h"
@@ -49,83 +41,115 @@ 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) "
e.id = instance_id; "VALUES "
e.charid = character_id; "(%lu, %lu)",
(unsigned long) instance_id,
return InstanceListPlayerRepository::ReplaceOne(*this, e); (unsigned long) char_id
}
bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id)
{
if (!instance_id) {
return false;
}
auto l = InstanceListPlayerRepository::GetWhere(
*this,
fmt::format(
"id = {} AND charid = {}",
instance_id,
character_id
)
); );
if (l.empty()) {
return false; auto results = QueryDatabase(query);
return results.Success();
} }
bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id)
{
std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() != 1)
return false;
return true; 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)
@@ -133,8 +157,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances); uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max = 32000; uint32 max = 32000;
auto query = fmt::format( std::string query = StringFormat(
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}", "SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
max_reserved_instance_id, max_reserved_instance_id,
max_reserved_instance_id max_reserved_instance_id
); );
@@ -167,8 +191,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
auto row = results.begin(); auto row = results.begin();
if (Strings::ToInt(row[0]) <= max) { if (atoi(row[0]) <= max) {
instance_id = Strings::ToInt(row[0]); instance_id = atoi(row[0]);
return true; return true;
} }
@@ -178,7 +202,7 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true; return true;
} }
query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id); query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id);
results = QueryDatabase(query); results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
@@ -192,9 +216,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
} }
max_reserved_instance_id++; max_reserved_instance_id++;
for (auto row = results.begin(); row != results.end(); ++row) {
for (auto row : results) { if (max_reserved_instance_id < atoi(row[0])) {
if (max_reserved_instance_id < Strings::ToUnsignedInt(row[0])) {
instance_id = max_reserved_instance_id; instance_id = max_reserved_instance_id;
return true; return true;
} }
@@ -212,45 +235,57 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true; 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;
} }
@@ -260,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 "
"instance_list.zone = %u "
"AND instance_list.version = %u "
"AND instance_list.id = instance_list_player.id "
"AND instance_list_player.charid = %u "
"LIMIT 1; ", "LIMIT 1; ",
zone_id, 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;
} }
@@ -364,175 +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) {
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
} }
auto i = InstanceListRepository::FindOne(*this, instance_id); uint32 Database::ZoneIDFromInstanceID(uint16 instance_id)
if (!i.id) { {
return 0;
}
return i.zone; 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)
{ {
std::string query; std::string query;
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id)); query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id);
QueryDatabase(query);
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id);
QueryDatabase(query);
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
QueryDatabase(query);
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id); 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(l_id, charid);
} }
AddClientToInstance(group_leader_instance_id, character_id); void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid)
}
void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id)
{ {
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(l_id, charid);
} }
AddClientToInstance(raid_leader_instance_id, character_id); void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list) {
}
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids) std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id);
{ auto results = QueryDatabase(query);
auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id));
if (l.empty()) { if (!results.Success())
return; return;
}
for (const auto& e : l) { for (auto row = results.begin(); row != results.end(); ++row)
character_ids.push_back(e.charid); 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));
} }
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 -30
View File
@@ -189,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",
@@ -225,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",
@@ -318,21 +318,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",
@@ -341,8 +340,6 @@ namespace DatabaseSchema {
"respawn_times", "respawn_times",
"saylink", "saylink",
"server_scheduled_events", "server_scheduled_events",
"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",
@@ -405,31 +402,11 @@ namespace DatabaseSchema {
"bot_pet_inventories", "bot_pet_inventories",
"bot_pets", "bot_pets",
"bot_spell_casting_chances", "bot_spell_casting_chances",
"bot_spell_settings",
"bot_spells_entries", "bot_spells_entries",
"bot_stances", "bot_stances",
"bot_timers" "bot_timers",
}; "vw_bot_character_mobs",
} "vw_bot_groups"
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"
}; };
} }
+43 -49
View File
@@ -34,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;
@@ -43,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()
@@ -53,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);
@@ -66,18 +70,17 @@ 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(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(std::string table_name) bool DBcore::DoesTableExist(std::string table_name)
@@ -92,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;
@@ -125,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 && strlen(query) > 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) {
@@ -153,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",
@@ -171,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",
@@ -202,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(
@@ -217,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);
@@ -237,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;
@@ -260,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;
@@ -270,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;
@@ -289,19 +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;
}
+4 -14
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:
@@ -28,22 +27,16 @@ public:
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(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(
const char *iHost, const char *iHost,
@@ -60,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;
+15 -95
View File
@@ -1,29 +1,34 @@
#include <cereal/archives/json.hpp>
#include <cereal/archives/binary.hpp>
#include "discord.h" #include "discord.h"
#include "../http/httplib.h" #include "../http/httplib.h"
#include "../json/json.h" #include "../json/json.h"
#include "../strings.h" #include "../string_util.h"
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../events/player_event_logs.h"
constexpr int MAX_RETRIES = 10; constexpr int MAX_RETRIES = 10;
void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url) void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url)
{ {
if (!ValidateWebhookUrl(webhook_url)) { // validate
if (webhook_url.empty()) {
LogDiscord("[webhook_url] is empty");
return;
}
// validate
if (webhook_url.find("http://") == std::string::npos && webhook_url.find("https://") == std::string::npos) {
LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url);
return; return;
} }
// split // split
auto s = Strings::Split(webhook_url, '/'); auto s = SplitString(webhook_url, '/');
// url // url
std::string base_url = fmt::format("{}//{}", s[0], s[2]); std::string base_url = fmt::format("{}//{}", s[0], s[2]);
std::string endpoint = Strings::Replace(webhook_url, base_url, ""); std::string endpoint = replace_string(webhook_url, base_url, "");
// client // client
httplib::Client cli(base_url); httplib::Client cli(base_url.c_str());
cli.set_connection_timeout(0, 15000000); // 15 sec cli.set_connection_timeout(0, 15000000); // 15 sec
cli.set_read_timeout(15, 0); // 15 seconds cli.set_read_timeout(15, 0); // 15 seconds
cli.set_write_timeout(15, 0); // 15 seconds cli.set_write_timeout(15, 0); // 15 seconds
@@ -41,7 +46,7 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
int retries = 0; int retries = 0;
int retry_timer = 1000; int retry_timer = 1000;
while (retry) { while (retry) {
if (auto res = cli.Post(endpoint, payload.str(), "application/json")) { if (auto res = cli.Post(endpoint.c_str(), payload.str(), "application/json")) {
if (res->status != 200 && res->status != 204) { if (res->status != 200 && res->status != 204) {
LogError("[Discord Client] Code [{}] Error [{}]", res->status, res->body); LogError("[Discord Client] Code [{}] Error [{}]", res->status, res->body);
} }
@@ -57,7 +62,7 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body); LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body);
} }
retry_timer = Strings::ToInt(response["retry_after"].asString()) + 500; retry_timer = std::stoi(response["retry_after"].asString()) + 500;
} }
LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer); LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer);
@@ -76,74 +81,6 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
} }
} }
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
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
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) std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string &message)
{ {
if (category_id == Logs::LogCategory::MySQLQuery) { if (category_id == Logs::LogCategory::MySQLQuery) {
@@ -152,20 +89,3 @@ std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string
return message + "\n"; 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;
}
-5
View File
@@ -4,16 +4,11 @@
#include <string> #include <string>
#include "../types.h" #include "../types.h"
#include "../http/httplib.h"
#include "../repositories/player_event_logs_repository.h"
#include "../events/player_events.h"
class Discord { class Discord {
public: public:
static void SendWebhookMessage(const std::string& message, const std::string& webhook_url); static void SendWebhookMessage(const std::string& message, const std::string& webhook_url);
static std::string FormatDiscordMessage(uint16 category_id, const std::string& message); 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);
}; };
@@ -1,6 +1,7 @@
#include "discord_manager.h" #include "discord_manager.h"
#include "../../common/discord/discord.h" #include "../common/discord/discord.h"
#include "../events/player_event_logs.h" #include "../common/eqemu_logsys.h"
#include "../common/string_util.h"
void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message) void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message)
{ {
@@ -21,12 +22,7 @@ void DiscordManager::ProcessMessageQueue()
for (auto &q: webhook_message_queue) { for (auto &q: webhook_message_queue) {
LogDiscord("Processing [{}] messages in queue for webhook ID [{}]...", q.second.size(), q.first); LogDiscord("Processing [{}] messages in queue for webhook ID [{}]...", q.second.size(), q.first);
if (q.first >= MAX_DISCORD_WEBHOOK_ID) { auto webhook = LogSys.discord_webhooks[q.first];
LogDiscord("Out of bounds webhook ID [{}] max [{}]", q.first, MAX_DISCORD_WEBHOOK_ID);
continue;
}
auto webhook = LogSys.GetDiscordWebhooks()[q.first];
std::string message; std::string message;
for (auto &m: q.second) { for (auto &m: q.second) {
@@ -54,6 +50,7 @@ void DiscordManager::ProcessMessageQueue()
message = ""; message = "";
} }
} }
// final flush // final flush
if (!message.empty()) { if (!message.empty()) {
Discord::SendWebhookMessage( Discord::SendWebhookMessage(
@@ -61,15 +58,8 @@ void DiscordManager::ProcessMessageQueue()
webhook.webhook_url webhook.webhook_url
); );
} }
webhook_message_queue.erase(q.first);
} }
webhook_message_queue.clear();
webhook_queue_lock.unlock(); 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);
}
}
@@ -4,15 +4,12 @@
#include <mutex> #include <mutex>
#include <map> #include <map>
#include <vector> #include <vector>
#include "../../common/types.h" #include "../common/types.h"
#include "../repositories/player_event_logs_repository.h"
#include "../events/player_events.h"
class DiscordManager { class DiscordManager {
public: public:
void QueueWebhookMessage(uint32 webhook_id, const std::string& message); void QueueWebhookMessage(uint32 webhook_id, const std::string& message);
void ProcessMessageQueue(); void ProcessMessageQueue();
void QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e);
private: private:
std::mutex webhook_queue_lock{}; std::mutex webhook_queue_lock{};
std::map<uint32, std::vector<std::string>> webhook_message_queue{}; std::map<uint32, std::vector<std::string>> webhook_message_queue{};
-49
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)
{ {
@@ -622,28 +598,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,
+2 -149
View File
@@ -18,12 +18,9 @@
*/ */
#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" #include "data_verification.h"
#include "bodytypes.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[] = {
@@ -435,147 +432,3 @@ std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
return std::string(); return std::string();
} }
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
{
static const std::map<int, std::string> object_type_map = {
{ ObjectTypes::SmallBag, "Small Bag" },
{ ObjectTypes::LargeBag, "Large Bag" },
{ ObjectTypes::Quiver, "Quiver" },
{ ObjectTypes::BeltPouch, "Belt Pouch" },
{ ObjectTypes::WristPouch, "Wrist Pouch" },
{ ObjectTypes::Backpack, "Backpack" },
{ ObjectTypes::SmallChest, "Small Chest" },
{ ObjectTypes::LargeChest, "Large Chest" },
{ ObjectTypes::Bandolier, "Bandolier" },
{ ObjectTypes::Medicine, "Medicine" },
{ ObjectTypes::Tinkering, "Tinkering" },
{ ObjectTypes::Lexicon, "Lexicon" },
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
{ ObjectTypes::Quest, "Quest" },
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
{ ObjectTypes::Baking, "Baking" },
{ ObjectTypes::Tailoring, "Tailoring" },
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
{ ObjectTypes::Fletching, "Fletching" },
{ ObjectTypes::Brewing, "Brewing" },
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
{ ObjectTypes::Pottery, "Pottery" },
{ ObjectTypes::Kiln, "Kiln" },
{ ObjectTypes::KeyMaker, "Key Maker" },
{ ObjectTypes::ResearchWIZ, "Lexicon" },
{ ObjectTypes::ResearchMAG, "Lexicon" },
{ ObjectTypes::ResearchNEC, "Lexicon" },
{ ObjectTypes::ResearchENC, "Lexicon" },
{ ObjectTypes::Unknown, "Unknown" },
{ ObjectTypes::ResearchPractice, "Lexicon" },
{ ObjectTypes::Alchemy, "Alchemy" },
{ ObjectTypes::HighElfForge, "High Elf Forge" },
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
{ ObjectTypes::OgreForge, "Ogre Forge" },
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
{ ObjectTypes::GnomeForge, "Gnome Forge" },
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
{ ObjectTypes::IksarForge, "Iksar Forge" },
{ ObjectTypes::HumanForgeOne, "Human Forge" },
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
{ ObjectTypes::Fishing, "Fishing" },
{ ObjectTypes::TrollForge, "Troll Forge" },
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
{ ObjectTypes::HalflingForge, "Halfling Forge" },
{ ObjectTypes::EruditeForge, "Erudite Forge" },
{ ObjectTypes::Merchant, "Merchant" },
{ ObjectTypes::FroglokForge, "Froglok Forge" },
{ ObjectTypes::Augmenter, "Augmenter" },
{ ObjectTypes::Churn, "Churn" },
{ ObjectTypes::TransformationMold, "Transformation Mold" },
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
{ ObjectTypes::Unattuner, "Unattuner" },
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
{ ObjectTypes::NoDeposit, "No Deposit" }
};
return object_type_map;
}
std::string EQ::constants::GetObjectTypeName(int object_type)
{
if (EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
{
static const std::map<uint8, std::string> weather_type_map = {
{WeatherTypes::None, "None"},
{WeatherTypes::Raining, "Raining"},
{WeatherTypes::Snowing, "Snowing"}
};
return weather_type_map;
}
std::string EQ::constants::GetWeatherTypeName(uint8 weather_type)
{
if (EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
{
static const std::map<uint8, std::string> emote_event_type_map = {
{ EmoteEventTypes::LeaveCombat, "Leave Combat" },
{ EmoteEventTypes::EnterCombat, "Enter Combat" },
{ EmoteEventTypes::OnDeath, "On Death" },
{ EmoteEventTypes::AfterDeath, "After Death" },
{ EmoteEventTypes::Hailed, "Hailed" },
{ EmoteEventTypes::KilledPC, "Killed PC" },
{ EmoteEventTypes::KilledNPC, "Killed NPC" },
{ EmoteEventTypes::OnSpawn, "On Spawn" },
{ EmoteEventTypes::OnDespawn, "On Despawn" }
};
return emote_event_type_map;
}
std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type)
{
if (EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
{
static const std::map<uint8, std::string> emote_type_map = {
{ EmoteTypes::Emote, "Emote" },
{ EmoteTypes::Shout, "Shout" },
{ EmoteTypes::Proximity, "Proximity" }
};
return emote_type_map;
}
std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
{
if (EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
}
return std::string();
}
+5 -133
View File
@@ -33,6 +33,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,25 +221,6 @@ 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 { enum GravityBehavior : int8 {
Ground, Ground,
Flying, Flying,
@@ -267,94 +252,6 @@ namespace EQ
Looting 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);
@@ -385,18 +282,6 @@ namespace EQ
extern const std::map<uint8, std::string>& GetSpawnAnimationMap(); extern const std::map<uint8, std::string>& GetSpawnAnimationMap();
std::string GetSpawnAnimationName(uint8 animation_id); 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;
@@ -567,7 +452,7 @@ enum ReloadWorld : uint8 {
ForceRepop ForceRepop
}; };
enum BucketComparison : uint8 { enum MerchantBucketComparison : uint8 {
BucketEqualTo = 0, BucketEqualTo = 0,
BucketNotEqualTo, BucketNotEqualTo,
BucketGreaterThanOrEqualTo, BucketGreaterThanOrEqualTo,
@@ -580,17 +465,4 @@ enum BucketComparison : uint8 {
BucketIsNotBetween BucketIsNotBetween
}; };
enum class EntityFilterType {
All,
Bots,
Clients,
NPCs
};
enum class ApplySpellType {
Solo,
Group,
Raid
};
#endif /*COMMON_EMU_CONSTANTS_H*/ #endif /*COMMON_EMU_CONSTANTS_H*/
+1 -3
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),
@@ -71,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),
@@ -304,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),
+9 -45
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,46 +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
};
#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();
+15 -25
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*/
}; };
@@ -2192,19 +2192,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 {
@@ -3637,8 +3629,6 @@ 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;
@@ -4547,7 +4537,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*/
}; };
@@ -5008,7 +4998,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;
@@ -5165,10 +5155,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;
+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);
-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_*/
+18 -23
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().c_str()); 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::ToInt(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str()); 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::ToInt(_root["server"]["world"][str].get("port", "5998").asString().c_str()); 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();
@@ -86,32 +85,28 @@ void EQEmuConfig::parse_config()
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; }
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::ToInt(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str()); 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::ToInt(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str()); 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::ToInt(_root["server"]["world"]["http"].get("port", "9080").asString().c_str()); 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::ToInt(_root["server"]["chatserver"].get("port", "7778").asString().c_str()); 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::ToInt(_root["server"]["mailserver"].get("port", "7778").asString().c_str()); MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
/** /**
* Database * Database
@@ -119,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::ToInt(_root["server"]["database"].get("port", "3306").asString().c_str()); 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();
/** /**
@@ -128,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::ToInt(_root["server"]["content_database"].get("port", 0).asString().c_str()); 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::ToInt(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str()); 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();
@@ -143,9 +138,9 @@ void EQEmuConfig::parse_config()
/** /**
* Zones * Zones
*/ */
DefaultStatus = Strings::ToInt(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str()); DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
ZonePortLow = Strings::ToInt(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str()); ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
ZonePortHigh = Strings::ToInt(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str()); ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
/** /**
* Files * Files
@@ -175,10 +170,10 @@ void EQEmuConfig::parse_config()
/** /**
* Launcher * Launcher
*/ */
RestartWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str()); RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
TerminateWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str()); TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
InitialBootWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str()); InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
ZoneBootInterval = Strings::ToInt(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str()); 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
+5 -16
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;
@@ -154,31 +151,23 @@ class EQEmuConfig
} }
// 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();
+265 -329
View File
@@ -21,20 +21,22 @@
#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 "misc.h"
#include "discord/discord.h"
#include "repositories/discord_webhooks_repository.h" #include "repositories/discord_webhooks_repository.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>
@@ -50,13 +52,47 @@ std::ofstream process_log;
#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 log_type, const std::string &) {};
} }
/** /**
@@ -69,7 +105,7 @@ 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;
@@ -79,13 +115,19 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
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);
@@ -98,14 +140,16 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::ChecksumVerification].log_to_gmsay = 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::CombatRecord].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Discord].log_to_console = 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);
/** /**
@@ -125,31 +169,64 @@ 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 debug_level
* @param log_category * @param log_category
@@ -166,7 +243,7 @@ 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";
@@ -180,6 +257,64 @@ void EQEmuLogSys::ProcessLogWrite(
} }
} }
/**
* @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,8 +322,10 @@ void EQEmuLogSys::ProcessLogWrite(
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
{ {
switch (log_category) { switch (log_category) {
case Logs::Status:
case Logs::Normal:
return Chat::Yellow;
case Logs::MySQLError: case Logs::MySQLError:
case Logs::QuestErrors:
case Logs::Error: case Logs::Error:
return Chat::Red; return Chat::Red;
case Logs::MySQLQuery: case Logs::MySQLQuery:
@@ -206,146 +343,30 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
} }
} }
/** /**
* @param debug_level * @param debug_level
* @param log_category * @param log_category
* @param message * @param message
*/ */
void EQEmuLogSys::ProcessConsoleMessage( void EQEmuLogSys::ProcessConsoleMessage(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(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;
}
}
if (!is_upper) {
(!is_error ? std::cout : std::cerr)
<< rang::fgB::gray
<< "["
<< rang::style::bold
<< rang::fgB::yellow
<< e
<< 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);
} }
/** /**
@@ -357,6 +378,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
* *
@@ -375,55 +423,50 @@ void EQEmuLogSys::Out(
... ...
) )
{ {
auto l = GetLogsEnabled(debug_level, log_category); bool log_to_console = log_settings[log_category].log_to_console > 0 &&
log_settings[log_category].log_to_console >= debug_level;
bool log_to_file = log_settings[log_category].log_to_file > 0 &&
log_settings[log_category].log_to_file >= debug_level;
bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0 &&
log_settings[log_category].log_to_gmsay >= debug_level &&
log_category != Logs::LogCategory::Netcode &&
(EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld);
bool log_to_discord = EQEmuLogSys::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;
// bail out if nothing to log // bail out if nothing to log
if (!l.log_enabled) { const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay && !log_to_discord;
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::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(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); on_log_gmsay_hook(log_category, message);
} }
if (l.log_to_file_enabled) { if (log_to_file) {
EQEmuLogSys::ProcessLogWrite( EQEmuLogSys::ProcessLogWrite(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) { if (log_to_discord && on_log_discord_hook) {
m_on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message); on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message);
} }
} }
@@ -436,7 +479,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);
} }
/** /**
@@ -475,45 +518,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
); );
} }
@@ -528,8 +579,6 @@ void EQEmuLogSys::SilenceConsoleLogging()
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);
} }
/** /**
@@ -545,8 +594,6 @@ void EQEmuLogSys::EnableConsoleLogging()
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"
@@ -585,7 +632,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);
@@ -593,28 +640,15 @@ 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;
@@ -626,19 +660,14 @@ 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)); auto webhooks = DiscordWebhooksRepository::All(*m_database);
if (!webhooks.empty()) { if (!webhooks.empty()) {
for (auto &w: webhooks) { for (auto &w: webhooks) {
m_discord_webhooks[w.id] = {w.id, w.webhook_name, w.webhook_url}; discord_webhooks[w.id] = {w.id, w.webhook_name, w.webhook_url};
} }
LogInfo("Loaded [{}] Discord webhooks", webhooks.size()); 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;
} }
@@ -649,96 +678,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;
}
+64 -92
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,
@@ -130,13 +131,6 @@ namespace Logs {
CombatRecord, CombatRecord,
Hate, Hate,
Discord, Discord,
Faction,
PacketServerClient,
PacketClientServer,
PacketServerToServer,
Bugs,
QuestErrors,
PlayerEvents,
MaxCategoryID /* Don't Remove this */ MaxCategoryID /* Don't Remove this */
}; };
@@ -149,7 +143,7 @@ namespace Logs {
"AI", "AI",
"Aggro", "Aggro",
"Attack", "Attack",
"Deprecated", "Packet :: Client -> Server",
"Combat", "Combat",
"Commands", "Commands",
"Crash", "Crash",
@@ -160,36 +154,36 @@ 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",
@@ -199,13 +193,13 @@ namespace Logs {
"Mob Appearance", "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",
@@ -222,17 +216,10 @@ namespace Logs {
"DialogueWindow", "DialogueWindow",
"HTTP", "HTTP",
"Saylink", "Saylink",
"ChecksumVer", "ChecksumVerification",
"CombatRecord", "CombatRecord",
"Hate", "Hate",
"Discord", "Discord",
"Faction",
"Packet S->C",
"Packet C->S",
"Packet S->S",
"Bugs",
"QuestErrors",
"PlayerEvents",
}; };
} }
@@ -324,37 +311,32 @@ public:
*/ */
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{}; LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
struct LogEnabled {
bool log_to_file_enabled;
bool log_to_console_enabled;
bool log_to_gmsay_enabled;
bool log_to_discord_enabled;
bool log_enabled;
};
LogEnabled GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
bool IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
struct DiscordWebhooks { struct DiscordWebhooks {
int id; int id;
std::string webhook_name; std::string webhook_name;
std::string webhook_url; std::string webhook_url;
}; };
const DiscordWebhooks *GetDiscordWebhooks() const; DiscordWebhooks discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{};
bool file_logs_enabled = false;
int log_platform = 0;
std::string platform_file_name;
// 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)
{ {
m_on_log_gmsay_hook = f; on_log_gmsay_hook = f;
return this; return this;
} }
EQEmuLogSys *SetDiscordHandler(std::function<void(uint16 log_category, int webhook_id, const std::string &)> f) EQEmuLogSys *SetDiscordHandler(std::function<void(uint16 log_category, int webhook_id, const std::string &)> f)
{ {
m_on_log_discord_hook = f; on_log_discord_hook = f;
return this; return this;
} }
@@ -364,38 +346,28 @@ public:
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);
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, const std::string &)> 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, int webhook_id, const std::string &)> on_log_discord_hook;
std::function<void(uint16 log_category, const std::string &)> m_on_log_console_hook; std::function<void(uint16 log_category, const std::string &)> 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::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
uint16 log_category, std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
const std::string &message, uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
const char *file,
const char *func, void ProcessConsoleMessage(uint16 log_category, const std::string &message);
int line
);
void ProcessLogWrite(uint16 log_category, const std::string &message); void ProcessLogWrite(uint16 log_category, const std::string &message);
void InjectTablesIfNotExist(); bool IsRfc5424LogCategory(uint16 log_category);
}; };
extern EQEmuLogSys LogSys; extern EQEmuLogSys LogSys;
File diff suppressed because it is too large Load Diff
+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;
+2 -2
View File
@@ -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
-708
View File
@@ -1,708 +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: {
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_FAILURE: {
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
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::WENT_ONLINE:
case PlayerEvent::WENT_OFFLINE: {
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
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 {
int32 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>
+2 -2
View File
@@ -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;
} }
} }
-17
View File
@@ -75,23 +75,6 @@ struct NPCFaction
uint8 temp; uint8 temp;
}; };
// Faction Associations give a much more live like faction system
// Basically the primary faction and magnitude of a faction hit will generate the rest of them
// Largest faction I could find quickly was Lord Inquisitor Seru with 9 total hits (8 associations) so 8 + 2 for max for now
#define MAX_FACTION_ASSOC 10
// this is the ID of a faction association and it's multiplier
struct FactionAssociationHit {
int id;
float multiplier;
};
struct FactionAssociations {
// maybe there should be more data here, fine for now
FactionAssociationHit hits[MAX_FACTION_ASSOC];
};
const char *FactionValueToString(FACTION_VALUE faction_value); const char *FactionValueToString(FACTION_VALUE faction_value);
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value); FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
#endif #endif
+1 -1
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,
+22 -32
View File
@@ -19,7 +19,7 @@
*/ */
#include <fstream> #include <fstream>
#include "file.h" #include "file_util.h"
#ifdef _WINDOWS #ifdef _WINDOWS
#include <direct.h> #include <direct.h>
@@ -35,48 +35,38 @@
#endif #endif
#include <fmt/format.h>
#include <filesystem>
namespace fs = std::filesystem;
/** /**
* @param name * @param name
* @return * @return
*/ */
bool File::Exists(const std::string &name) bool FileUtil::exists(const std::string &name)
{ {
return fs::exists(fs::path{name}); std::ifstream f(name.c_str());
return f.good();
} }
/** /**
* @param directory_name * @param directory_name
*/ */
void File::Makedir(const std::string &directory_name) void FileUtil::mkdir(const std::string& directory_name)
{ {
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all); #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
} }
std::string File::FindEqemuConfigPath() bool file_exists(const std::string& name) {
{ std::ifstream f(name.c_str());
if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) { return f.good();
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();
} }
+7 -12
View File
@@ -18,21 +18,16 @@
* *
*/ */
#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 {
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 std::string FindEqemuConfigPath();
static std::string GetCwd();
}; };
bool Exists(const std::string& name); bool file_exists(const std::string& name);
#endif //EQEMU_FILE_H #endif //EQEMU_FILE_UTIL_H
+33 -21
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,9 +61,7 @@ bool BaseGuildManager::LoadGuilds() {
} }
for (auto row=results.begin();row!=results.end();++row) for (auto row=results.begin();row!=results.end();++row)
_CreateGuild(Strings::ToInt(row[0]), row[1], Strings::ToInt(row[2]), Strings::ToInt(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);
@@ -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::ToInt(row[0]); uint32 guild_id = atoi(row[0]);
uint8 rankn = Strings::ToInt(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,7 +129,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
auto row = results.begin(); auto row = results.begin();
info = _CreateGuild(guild_id, row[0], Strings::ToInt(row[1]), Strings::ToInt(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);
@@ -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::ToInt(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);
@@ -787,7 +785,7 @@ bool BaseGuildManager::GetBankerFlag(uint32 CharID)
auto row = results.begin(); auto row = results.begin();
bool IsBanker = Strings::ToInt(row[0]); bool IsBanker = atoi(row[0]);
return IsBanker; return IsBanker;
} }
@@ -817,7 +815,7 @@ bool BaseGuildManager::GetAltFlag(uint32 CharID)
auto row = results.begin(); auto row = results.begin();
bool IsAlt = Strings::ToInt(row[0]); bool IsAlt = atoi(row[0]);
return IsAlt; return IsAlt;
} }
@@ -866,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::ToInt(row[0]); into.char_id = atoi(row[0]);
into.char_name = row[1]; into.char_name = row[1];
into.class_ = Strings::ToInt(row[2]); into.class_ = atoi(row[2]);
into.level = Strings::ToInt(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::ToInt(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::ToInt(row[6]) : GUILD_NONE; into.guild_id = row[6] ? atoi(row[6]) : GUILD_NONE;
into.rank = row[7] ? Strings::ToInt(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::ToInt(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;
@@ -960,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;
@@ -1258,7 +1270,7 @@ uint32 BaseGuildManager::GetGuildIDByCharacterID(uint32 character_id)
} }
auto row = results.begin(); auto row = results.begin();
auto guild_id = Strings::ToUnsignedInt(row[0]); auto guild_id = std::stoul(row[0]);
return guild_id; return guild_id;
} }
+1300 -2025
View File
File diff suppressed because it is too large Load Diff
+1 -15
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"
@@ -1718,17 +1718,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;
}
+2 -8
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,7 +129,7 @@ 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, int16 quantity = 0);
@@ -155,9 +152,6 @@ namespace EQ
// Check how many of a specific augment the player has equipped by Item ID // Check how many of a specific augment the player has equipped by Item ID
int CountAugmentEquippedByID(uint32 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);
@@ -208,7 +202,7 @@ namespace EQ
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value);
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value);
std::string GetCustomItemData(int16 slot_id, std::string identifier); std::string GetCustomItemData(int16 slot_id, std::string identifier);
static const int GetItemStatValue(uint32 item_id, 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 -24
View File
@@ -169,33 +169,11 @@ uint8 EQ::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit)
bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const 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;
} }
-2
View File
@@ -533,8 +533,6 @@ namespace EQ
//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;
+33 -115
View File
@@ -23,17 +23,17 @@
//#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 "util/uuid.h"
//#include "../common/light_source.h" //#include "../common/light_source.h"
#include <limits.h> #include <limits.h>
//#include <iostream> //#include <iostream>
uint32 NextItemInstSerialNumber = 1; int32 NextItemInstSerialNumber = 1;
static inline uint32 GetNextItemInstSerialNumber() { static inline int32 GetNextItemInstSerialNumber() {
// The Bazaar relies on each item a client has up for Trade having a unique // The Bazaar relies on each item a client has up for Trade having a unique
// identifier. This 'SerialNumber' is sent in Serialized item packets and // identifier. This 'SerialNumber' is sent in Serialized item packets and
@@ -45,7 +45,7 @@ static inline uint32 GetNextItemInstSerialNumber() {
// NextItemInstSerialNumber is the next one to hand out. // NextItemInstSerialNumber is the next one to hand out.
// //
// It is very unlikely to reach 2,147,483,647. Maybe we should call abort(), rather than wrapping back to 1. // It is very unlikely to reach 2,147,483,647. Maybe we should call abort(), rather than wrapping back to 1.
if(NextItemInstSerialNumber >= UINT_MAX) if(NextItemInstSerialNumber >= INT_MAX)
NextItemInstSerialNumber = 1; NextItemInstSerialNumber = 1;
else else
NextItemInstSerialNumber++; NextItemInstSerialNumber++;
@@ -56,21 +56,13 @@ static inline uint32 GetNextItemInstSerialNumber() {
// //
// class EQ::ItemInstance // class EQ::ItemInstance
// //
EQ::ItemInstance::ItemInstance(const ItemData* item, const std::string& guid, int16 charges) { EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
m_use_type = ItemInstNormal; m_use_type = ItemInstNormal;
if(item) { if(item) {
m_item = new ItemData(*item); m_item = new ItemData(*item);
} else { } else {
m_item = nullptr; m_item = nullptr;
} }
if (guid.empty()) {
m_guid = EQ::Util::UUID::Generate().ToString();
}
else {
m_guid = guid;
}
m_charges = charges; m_charges = charges;
m_price = 0; m_price = 0;
m_attuned = false; m_attuned = false;
@@ -80,7 +72,7 @@ EQ::ItemInstance::ItemInstance(const ItemData* item, const std::string& guid, in
else else
m_color = 0; m_color = 0;
m_merchantcount = 1; m_merchantcount = 1;
m_serial_number = GetNextItemInstSerialNumber(); m_SerialNumber = GetNextItemInstSerialNumber();
m_exp = 0; m_exp = 0;
m_evolveLvl = 0; m_evolveLvl = 0;
@@ -93,10 +85,9 @@ EQ::ItemInstance::ItemInstance(const ItemData* item, const std::string& guid, in
m_ornament_hero_model = 0; m_ornament_hero_model = 0;
m_recast_timestamp = 0; m_recast_timestamp = 0;
m_new_id_file = 0; m_new_id_file = 0;
m_currentslot = 0;
} }
EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, const std::string& guid, int16 charges) { EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) {
m_use_type = ItemInstNormal; m_use_type = ItemInstNormal;
m_item = db->GetItem(item_id); m_item = db->GetItem(item_id);
if(m_item) { if(m_item) {
@@ -106,13 +97,6 @@ EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, const std::st
m_item = nullptr; m_item = nullptr;
} }
if (guid.empty()) {
m_guid = EQ::Util::UUID::Generate().ToString();
}
else {
m_guid = guid;
}
m_charges = charges; m_charges = charges;
m_price = 0; m_price = 0;
m_merchantslot = 0; m_merchantslot = 0;
@@ -122,7 +106,7 @@ EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, const std::st
else else
m_color = 0; m_color = 0;
m_merchantcount = 1; m_merchantcount = 1;
m_serial_number = GetNextItemInstSerialNumber(); m_SerialNumber = GetNextItemInstSerialNumber();
m_exp = 0; m_exp = 0;
m_evolveLvl = 0; m_evolveLvl = 0;
@@ -135,20 +119,17 @@ EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, const std::st
m_ornament_hero_model = 0; m_ornament_hero_model = 0;
m_recast_timestamp = 0; m_recast_timestamp = 0;
m_new_id_file = 0; m_new_id_file = 0;
m_currentslot = 0;
} }
EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) { EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) {
m_use_type = use_type; m_use_type = use_type;
m_guid = EQ::Util::UUID::Generate().ToString();
m_item = nullptr; m_item = nullptr;
m_charges = 0; m_charges = 0;
m_price = 0; m_price = 0;
m_attuned = false; m_attuned = false;
m_merchantslot = 0; m_merchantslot = 0;
m_color = 0; m_color = 0;
m_serial_number = 0;
m_exp = 0; m_exp = 0;
m_evolveLvl = 0; m_evolveLvl = 0;
m_activated = false; m_activated = false;
@@ -160,8 +141,6 @@ EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) {
m_ornament_hero_model = 0; m_ornament_hero_model = 0;
m_recast_timestamp = 0; m_recast_timestamp = 0;
m_new_id_file = 0; m_new_id_file = 0;
m_currentslot = 0;
m_merchantcount = 0;
} }
// Make a copy of an EQ::ItemInstance object // Make a copy of an EQ::ItemInstance object
@@ -173,7 +152,6 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
else else
m_item = nullptr; m_item = nullptr;
m_guid = copy.m_guid;
m_charges=copy.m_charges; m_charges=copy.m_charges;
m_price=copy.m_price; m_price=copy.m_price;
m_color=copy.m_color; m_color=copy.m_color;
@@ -198,7 +176,7 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
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_serial_number = copy.m_serial_number; 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;
@@ -285,43 +263,20 @@ bool EQ::ItemInstance::IsCharged() const
// 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);
} }
@@ -354,52 +309,29 @@ bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
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 (index <= invaug::SOCKET_END) ? index : INVALID_INDEX;
} }
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX; bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
}
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, 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;
} }
@@ -568,11 +500,10 @@ 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;
} }
@@ -632,7 +563,7 @@ bool EQ::ItemInstance::UpdateOrnamentationInfo() {
SetOrnamentHeroModel(ornamentItem->HerosForgeModel); SetOrnamentHeroModel(ornamentItem->HerosForgeModel);
if (strlen(ornamentItem->IDFile) > 2) if (strlen(ornamentItem->IDFile) > 2)
{ {
SetOrnamentationIDFile(Strings::ToInt(&ornamentItem->IDFile[2])); SetOrnamentationIDFile(atoi(&ornamentItem->IDFile[2]));
} }
else else
{ {
@@ -698,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
@@ -1285,7 +1215,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;
@@ -1791,18 +1721,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
// //
+9 -24
View File
@@ -69,9 +69,9 @@ namespace EQ
///////////////////////// /////////////////////////
// Constructors/Destructor // Constructors/Destructor
ItemInstance(const ItemData* item, const std::string& guid, int16 charges); ItemInstance(const ItemData* item = nullptr, int16 charges = 0);
ItemInstance(SharedDatabase *db, uint32 item_id, const std::string &guid, int16 charges); ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges = 0);
ItemInstance(ItemInstTypes use_type); ItemInstance(ItemInstTypes use_type);
@@ -79,8 +79,6 @@ namespace EQ
~ItemInstance(); ~ItemInstance();
inline std::string GetGuid() const { return m_guid; }
// Query item type // Query item type
bool IsType(item::ItemClass item_class) const; bool IsType(item::ItemClass item_class) const;
@@ -94,8 +92,6 @@ namespace EQ
// Can item be equipped by/at? // Can item be equipped by/at?
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 IsEquipable(int16 slot_id) const; bool IsEquipable(int16 slot_id) const;
// //
@@ -103,8 +99,8 @@ namespace EQ
// //
bool IsAugmentable() const; bool IsAugmentable() const;
bool AvailableWearSlot(uint32 aug_wear_slots) const; bool AvailableWearSlot(uint32 aug_wear_slots) const;
int8 AvailableAugmentSlot(int32 augment_type) const; int8 AvailableAugmentSlot(int32 augtype) const;
bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const; bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const;
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); } inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); }
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); } inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); }
@@ -129,8 +125,8 @@ namespace EQ
// //
// Augments // Augments
// //
ItemInstance* GetAugment(uint8 augment_index) const; ItemInstance* GetAugment(uint8 slot) const;
uint32 GetAugmentItemID(uint8 augment_index) const; uint32 GetAugmentItemID(uint8 slot) const;
void PutAugment(uint8 slot, const ItemInstance& inst); void PutAugment(uint8 slot, const ItemInstance& inst);
void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id); void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id);
void DeleteAugment(uint8 slot); void DeleteAugment(uint8 slot);
@@ -152,8 +148,6 @@ namespace EQ
const ItemData* GetItem() const; const ItemData* GetItem() const;
const ItemData* GetUnscaledItem() const; const ItemData* GetUnscaledItem() const;
const uint8 GetItemType() const { return m_item ? m_item->ItemType : 255; } // Return 255 so you know there's no valid item
int16 GetCharges() const { return m_charges; } int16 GetCharges() const { return m_charges; }
void SetCharges(int16 charges) { m_charges = charges; } void SetCharges(int16 charges) { m_charges = charges; }
@@ -227,21 +221,14 @@ namespace EQ
std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; } std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; }
void Serialize(OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } void Serialize(OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); }
inline int32 GetSerialNumber() const { return m_serial_number; } inline int32 GetSerialNumber() const { return m_SerialNumber; }
inline void SetSerialNumber(int32 id) { m_serial_number = id; } inline void SetSerialNumber(int32 id) { m_SerialNumber = id; }
std::map<std::string, ::Timer>& GetTimers() { return m_timers; } std::map<std::string, ::Timer>& GetTimers() { return m_timers; }
void SetTimer(std::string name, uint32 time); void SetTimer(std::string name, uint32 time);
void StopTimer(std::string name); void StopTimer(std::string name);
void ClearTimers(); void ClearTimers();
int GetTaskDeliveredCount() const { return m_task_delivered_count; }
void SetTaskDeliveredCount(int count) { m_task_delivered_count = count; }
// This function should only be used by trade return apis
// Removes delivered task items from stack count and returns remaining count
// Return value should be used to determine if an item still exists (for stackable and non-stackable)
int RemoveTaskDeliveredItems();
// Get a total of a stat, including augs // Get a total of a stat, including augs
// These functions should be used in place of other code manually totaling // These functions should be used in place of other code manually totaling
// to centralize where it is done to make future changes easier (ex. whenever powersources come around) // to centralize where it is done to make future changes easier (ex. whenever powersources come around)
@@ -305,7 +292,6 @@ namespace EQ
void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; } void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; }
std::string m_guid;
ItemInstTypes m_use_type; // Usage type for item ItemInstTypes m_use_type; // Usage type for item
const ItemData* m_item; // Ptr to item data const ItemData* m_item; // Ptr to item data
int16 m_charges; // # of charges for chargeable items int16 m_charges; // # of charges for chargeable items
@@ -315,7 +301,7 @@ namespace EQ
int16 m_currentslot; int16 m_currentslot;
bool m_attuned; bool m_attuned;
int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited
uint32 m_serial_number; // Unique identifier for this instance of an item. Needed for Bazaar. int32 m_SerialNumber; // Unique identifier for this instance of an item. Needed for Bazaar.
uint32 m_exp; uint32 m_exp;
int8 m_evolveLvl; int8 m_evolveLvl;
bool m_activated; bool m_activated;
@@ -327,7 +313,6 @@ namespace EQ
uint32 m_new_id_file; uint32 m_new_id_file;
uint32 m_ornament_hero_model; uint32 m_ornament_hero_model;
uint32 m_recast_timestamp; uint32 m_recast_timestamp;
int m_task_delivered_count = 0;
// //
// Items inside of this item (augs or contents); // Items inside of this item (augs or contents);
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -9,7 +9,7 @@
*/ */
#include <string.h> /* for memcpy() */ #include <string.h> /* for memcpy() */
#include "../common/md5.h" #include "../common/md5.h"
#include "../common/strings.h" #include "../common/string_util.h"
#include "../common/seperator.h" #include "../common/seperator.h"
MD5::MD5() { MD5::MD5() {
+2 -2
View File
@@ -71,13 +71,13 @@ namespace EQ
template<typename T> template<typename T>
void Write(T val) { void Write(T val) {
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types."); static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
Write((const char*)&val, sizeof(T)); Write((const char*)&val, sizeof(T));
} }
template<typename T> template<typename T>
T Read() { T Read() {
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types."); static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
T temp; T temp;
Read((uchar*)&temp, sizeof(T)); Read((uchar*)&temp, sizeof(T));
return temp; return temp;
-3
View File
@@ -33,9 +33,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#include <filesystem>
namespace fs = std::filesystem;
namespace EQ { namespace EQ {
struct MemoryMappedFile::Implementation { struct MemoryMappedFile::Implementation {
+1 -2
View File
@@ -18,7 +18,6 @@
#include "misc.h" #include "misc.h"
#include "types.h" #include "types.h"
#include <cstring> #include <cstring>
#include "strings.h"
std::map<int,std::string> DBFieldNames; std::map<int,std::string> DBFieldNames;
@@ -151,7 +150,7 @@ static char *temp=nullptr;
return false; return false;
} }
ptr++; ptr++;
uint32 id = Strings::ToInt(field[id_pos].c_str()); uint32 id = atoi(field[id_pos].c_str());
items[id]=field; items[id]=field;
for(i=0;i<10;i++) { for(i=0;i<10;i++) {
+1 -2
View File
@@ -21,7 +21,6 @@
#include "misc_functions.h" #include "misc_functions.h"
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "strings.h"
#ifndef WIN32 #ifndef WIN32
#include <netinet/in.h> #include <netinet/in.h>
@@ -131,7 +130,7 @@ bool ParseAddress(const char* iAddress, uint32* oIP, uint16* oPort, char* errbuf
if (*oIP == 0) if (*oIP == 0)
return false; return false;
if (oPort) if (oPort)
*oPort = Strings::ToInt(sep.arg[1]); *oPort = atoi(sep.arg[1]);
return true; return true;
} }
return false; return false;
+1 -7
View File
@@ -10,14 +10,8 @@
#include <iterator> #include <iterator>
#include "types.h" #include "types.h"
class MySQLRequestRow class MySQLRequestRow : public std::iterator<std::input_iterator_tag, MYSQL_ROW>
{ {
public:
using iterator_category = std::input_iterator_tag;
using value_type = MYSQL_ROW;
using difference_type = std::ptrdiff_t;
using pointer = MYSQL_ROW*;
using reference = MYSQL_ROW&;
private: private:
MYSQL_RES* m_Result; MYSQL_RES* m_Result;
+3 -3
View File
@@ -1,5 +1,5 @@
#include "console_server.h" #include "console_server.h"
#include "../strings.h" #include "../string_util.h"
#include <fmt/format.h> #include <fmt/format.h>
EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port) EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
@@ -52,11 +52,11 @@ void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c)
void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd) void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd)
{ {
auto split = Strings::Split(cmd, ' '); auto split = SplitString(cmd, ' ');
if (split.size() > 0) { if (split.size() > 0) {
auto command = split[0]; auto command = split[0];
command = Strings::ToLower(command); ToLowerString(command);
if (command == "help" || command == "?") { if (command == "help" || command == "?") {
c->SendLine("Commands:"); c->SendLine("Commands:");
+15 -14
View File
@@ -116,42 +116,43 @@ bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMes
} }
switch (scm->chan_num) { switch (scm->chan_num) {
case ChatChannel_Guild: { case 4: {
QueueMessage(fmt::format("{} tells the guild [{}], '{}'", scm->from, scm->guilddbid, scm->message));
break;
}
case ChatChannel_Auction: {
if (RuleB(Chat, ServerWideAuction)) { if (RuleB(Chat, ServerWideAuction)) {
QueueMessage(fmt::format("{} auctions, '{}'", scm->from, scm->message)); QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
break; break;
} else { // I think we want default action in this case? } else { // I think we want default action in this case?
return false; return false;
} }
} }
case ChatChannel_OOC: {
case 5: {
if (RuleB(Chat, ServerWideOOC)) { if (RuleB(Chat, ServerWideOOC)) {
QueueMessage(fmt::format("{} says ooc, '{}'", scm->from, scm->message)); QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
break; break;
} else { // I think we want default action in this case? } else { // I think we want default action in this case?
return false; return false;
} }
} }
case ChatChannel_Broadcast: {
QueueMessage(fmt::format("{} BROADCASTS, '{}'", scm->from, scm->message)); case 6: {
QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message));
break; break;
} }
case ChatChannel_Tell: {
QueueMessage(fmt::format("[{}] tells {}, '{}'", scm->from, scm->to, scm->message)); case 7: {
QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message));
if (onTell) { if (onTell) {
onTell(); onTell();
} }
break; break;
} }
case ChatChannel_GMSAY: {
QueueMessage(fmt::format("{} GMSAYS, '{}'", scm->from, scm->message)); case 11: {
QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message));
break; break;
} }
default: { default: {
return false; return false;
} }
+1 -19
View File
@@ -3,7 +3,6 @@
#include "../event/task.h" #include "../event/task.h"
#include "../data_verification.h" #include "../data_verification.h"
#include "crc32.h" #include "crc32.h"
#include "../eqemu_logsys.h"
#include <zlib.h> #include <zlib.h>
#include <fmt/format.h> #include <fmt/format.h>
#include <sstream> #include <sstream>
@@ -309,8 +308,6 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_combined[1] = OP_Combined; m_combined[1] = OP_Combined;
m_last_session_stats = Clock::now(); m_last_session_stats = Clock::now();
m_outgoing_budget = owner->m_options.outgoing_data_rate; m_outgoing_budget = owner->m_options.outgoing_data_rate;
LogNetcode("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
} }
//new connection made as client //new connection made as client
@@ -633,8 +630,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
DynamicPacket p; DynamicPacket p;
p.PutSerialize(0, reply); p.PutSerialize(0, reply);
InternalSend(p); InternalSend(p);
LogNetcode("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
} }
break; break;
@@ -652,12 +647,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2; m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
m_max_packet_size = reply.max_packet_size; m_max_packet_size = reply.max_packet_size;
ChangeStatus(StatusConnected); ChangeStatus(StatusConnected);
LogNetcode(
"[OP_SessionResponse] Session [{}] refresh with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
} }
} }
break; break;
@@ -782,12 +771,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
SendDisconnect(); SendDisconnect();
} }
LogNetcode(
"[OP_SessionDisconnect] Session [{}] disconnect with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
ChangeStatus(StatusDisconnecting); ChangeStatus(StatusDisconnecting);
break; break;
} }
@@ -852,7 +835,6 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
} }
if (p.Length() < (size_t)m_crc_bytes) { if (p.Length() < (size_t)m_crc_bytes) {
LogNetcode("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code);
return false; return false;
} }
@@ -1412,7 +1394,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length); first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length);
size_t used = 0; size_t used = 0;
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size() - 1; // -1 for compress flag size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size();
DynamicPacket first_packet; DynamicPacket first_packet;
first_packet.PutSerialize(0, first_header); first_packet.PutSerialize(0, first_header);
first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen); first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen);
-9
View File
@@ -65,15 +65,6 @@ EQ::Net::EQStream::~EQStream()
} }
void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) { void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
LogPacketServerClient(
"[{}] [{:#06x}] Size [{}] {}",
OpcodeManager::EmuToName(p->GetOpcode()),
(*m_opcode_manager)->EmuToEQ(p->GetOpcode()),
p->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
);
if (m_opcode_manager && *m_opcode_manager) { if (m_opcode_manager && *m_opcode_manager) {
uint16 opcode = 0; uint16 opcode = 0;
if (p->GetOpcodeBypass() != 0) { if (p->GetOpcodeBypass() != 0) {
-4
View File
@@ -57,10 +57,6 @@ namespace EQ
virtual void SetOpcodeManager(OpcodeManager **opm) { virtual void SetOpcodeManager(OpcodeManager **opm) {
m_opcode_manager = opm; m_opcode_manager = opm;
} }
virtual OpcodeManager * GetOpcodeManager() const
{
return (*m_opcode_manager);
};
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats(); virtual void ResetStats();
@@ -319,16 +319,6 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
size_t message_len = length; size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len); EQ::Net::StaticPacket packet(&data[0], message_len);
const auto is_detail_enabled = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
if (opcode != ServerOP_KeepAlive || is_detail_enabled) {
LogPacketServerToServer(
"[{:#06x}] Size [{}] {}",
opcode,
packet.Length(),
(is_detail_enabled ? "\n" + packet.ToString() : "")
);
}
auto cb = m_message_callbacks.find(opcode); auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) { if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet); cb->second(opcode, packet);
-3
View File
@@ -184,9 +184,6 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
MOpcodes.lock(); MOpcodes.lock();
res = emu_to_eq[emu_op]; res = emu_to_eq[emu_op];
MOpcodes.unlock(); MOpcodes.unlock();
LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res);
#ifdef DEBUG_TRANSLATE #ifdef DEBUG_TRANSLATE
fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res); fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
#endif #endif
+52 -25
View File
@@ -28,12 +28,10 @@
#include "../eq_packet_structs.h" #include "../eq_packet_structs.h"
#include "../misc_functions.h" #include "../misc_functions.h"
#include "../strings.h" #include "../string_util.h"
#include "../inventory_profile.h" #include "../inventory_profile.h"
#include "rof_structs.h" #include "rof_structs.h"
#include "../rulesys.h" #include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@@ -77,8 +75,12 @@ namespace RoF
{ {
//create our opcode manager if we havent already //create our opcode manager if we havent already
if (opcodes == nullptr) { if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
//load up the opcode manager. //load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches... //TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager(); opcodes = new RegularOpcodeManager();
@@ -116,7 +118,12 @@ namespace RoF
//we need to go to every stream and replace it's manager. //we need to go to every stream and replace it's manager.
if (opcodes != nullptr) { if (opcodes != nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
if (!opcodes->ReloadOpcodes(opfile.c_str())) { if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return; return;
@@ -665,7 +672,7 @@ namespace RoF
ENCODE(OP_DeleteCharge) ENCODE(OP_DeleteCharge)
{ {
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)"); Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem); ENCODE_FORWARD(OP_MoveItem);
} }
@@ -729,6 +736,30 @@ namespace RoF
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning) ENCODE(OP_DzExpeditionEndsWarning)
{ {
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1593,7 +1624,7 @@ namespace RoF
ENCODE_LENGTH_EXACT(LootingItem_Struct); ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_LootItem)");
OUT(lootee); OUT(lootee);
OUT(looter); OUT(looter);
@@ -1751,7 +1782,7 @@ namespace RoF
ENCODE_LENGTH_EXACT(MoveItem_Struct); ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToRoFSlot(emu->from_slot); eq->from_slot = ServerToRoFSlot(emu->from_slot);
eq->to_slot = ServerToRoFSlot(emu->to_slot); eq->to_slot = ServerToRoFSlot(emu->to_slot);
@@ -1807,10 +1838,10 @@ namespace RoF
OUT_str(zone_short_name2); OUT_str(zone_short_name2);
OUT(zone_id); OUT(zone_id);
OUT(zone_instance); OUT(zone_instance);
OUT(suspend_buffs); OUT(SuspendBuffs);
OUT(fast_regen_hp); OUT(FastRegenHP);
OUT(fast_regen_mana); OUT(FastRegenMana);
OUT(fast_regen_endurance); OUT(FastRegenEndurance);
OUT(underworld_teleport_index); OUT(underworld_teleport_index);
eq->FogDensity = emu->fog_density; eq->FogDensity = emu->fog_density;
@@ -1818,8 +1849,8 @@ namespace RoF
/*fill in some unknowns with observed values, hopefully it will help */ /*fill in some unknowns with observed values, hopefully it will help */
eq->unknown800 = -1; eq->unknown800 = -1;
eq->unknown844 = 600; eq->unknown844 = 600;
OUT(lava_damage); OUT(LavaDamage);
OUT(min_lava_damage); OUT(MinLavaDamage);
eq->unknown888 = 1; eq->unknown888 = 1;
eq->unknown889 = 0; eq->unknown889 = 0;
eq->unknown890 = 1; eq->unknown890 = 1;
@@ -3831,9 +3862,7 @@ namespace RoF
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{ {
PacketSize += 60; PacketSize += 60;
@@ -3965,9 +3994,7 @@ namespace RoF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{ {
@@ -4822,7 +4849,7 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::LootingItem_Struct); DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_LootItem)");
IN(lootee); IN(lootee);
IN(looter); IN(looter);
@@ -4837,7 +4864,7 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_MoveItem)");
emu->from_slot = RoFToServerSlot(eq->from_slot); emu->from_slot = RoFToServerSlot(eq->from_slot);
emu->to_slot = RoFToServerSlot(eq->to_slot); emu->to_slot = RoFToServerSlot(eq->to_slot);
@@ -6096,7 +6123,7 @@ namespace RoF
return; return;
} }
auto segments = Strings::Split(serverSayLink, '\x12'); auto segments = SplitString(serverSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
@@ -6135,7 +6162,7 @@ namespace RoF
return; return;
} }
auto segments = Strings::Split(rofSayLink, '\x12'); auto segments = SplitString(rofSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
+68 -45
View File
@@ -28,13 +28,10 @@
#include "../eq_packet_structs.h" #include "../eq_packet_structs.h"
#include "../misc_functions.h" #include "../misc_functions.h"
#include "../strings.h" #include "../string_util.h"
#include "../inventory_profile.h" #include "../inventory_profile.h"
#include "rof2_structs.h" #include "rof2_structs.h"
#include "../rulesys.h" #include "../rulesys.h"
#include "../path_manager.h"
#include "../classes.h"
#include "../races.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@@ -79,9 +76,12 @@ namespace RoF2
{ {
//create our opcode manager if we havent already //create our opcode manager if we havent already
if (opcodes == nullptr) { if (opcodes == nullptr) {
//TODO: get this file name from the config file
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
//load up the opcode manager. //load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches... //TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager(); opcodes = new RegularOpcodeManager();
@@ -122,7 +122,12 @@ namespace RoF2
//we need to go to every stream and replace it's manager. //we need to go to every stream and replace it's manager.
if (opcodes != nullptr) { if (opcodes != nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
if (!opcodes->ReloadOpcodes(opfile.c_str())) { if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return; return;
@@ -716,7 +721,7 @@ namespace RoF2
ENCODE(OP_DeleteCharge) ENCODE(OP_DeleteCharge)
{ {
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem); ENCODE_FORWARD(OP_MoveItem);
} }
@@ -780,6 +785,30 @@ namespace RoF2
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning) ENCODE(OP_DzExpeditionEndsWarning)
{ {
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1644,7 +1673,7 @@ namespace RoF2
ENCODE_LENGTH_EXACT(LootingItem_Struct); ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)");
OUT(lootee); OUT(lootee);
OUT(looter); OUT(looter);
@@ -1802,7 +1831,7 @@ namespace RoF2
ENCODE_LENGTH_EXACT(MoveItem_Struct); ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToRoF2Slot(emu->from_slot); eq->from_slot = ServerToRoF2Slot(emu->from_slot);
eq->to_slot = ServerToRoF2Slot(emu->to_slot); eq->to_slot = ServerToRoF2Slot(emu->to_slot);
@@ -1858,13 +1887,13 @@ namespace RoF2
OUT_str(zone_short_name2); OUT_str(zone_short_name2);
OUT(zone_id); OUT(zone_id);
OUT(zone_instance); OUT(zone_instance);
OUT(suspend_buffs); OUT(SuspendBuffs);
OUT(fast_regen_hp); OUT(FastRegenHP);
OUT(fast_regen_mana); OUT(FastRegenMana);
OUT(fast_regen_endurance); OUT(FastRegenEndurance);
OUT(underworld_teleport_index); OUT(underworld_teleport_index);
eq->fog_density = emu->fog_density; eq->FogDensity = emu->fog_density;
/*fill in some unknowns with observed values, hopefully it will help */ /*fill in some unknowns with observed values, hopefully it will help */
eq->ZoneTimeZone = 0; eq->ZoneTimeZone = 0;
@@ -1876,8 +1905,8 @@ namespace RoF2
eq->SkyRelated2 = -1; eq->SkyRelated2 = -1;
eq->NPCAggroMaxDist = 600; eq->NPCAggroMaxDist = 600;
eq->FilterID = 2008; // Guild Lobby observed value eq->FilterID = 2008; // Guild Lobby observed value
OUT(lava_damage); OUT(LavaDamage);
OUT(min_lava_damage); OUT(MinLavaDamage);
eq->bDisallowManaStone = 1; eq->bDisallowManaStone = 1;
eq->bNoBind = 0; eq->bNoBind = 0;
eq->bNoAttack = 0; eq->bNoAttack = 0;
@@ -1886,12 +1915,12 @@ namespace RoF2
eq->bNoFear = 0; eq->bNoFear = 0;
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0; eq->unknown895 = 0;
eq->can_place_campsite = 2; eq->CanPlaceCampsite = 2;
eq->can_place_guild_banner = 2; eq->CanPlaceGuildBanner = 2;
eq->fishing_related = -1; // Set from PoK Example eq->FishingRelated = -1; // Set from PoK Example
eq->forage_related = -1; // Set from PoK Example eq->ForageRelated = -1; // Set from PoK Example
eq->b_no_levitate = 0; eq->bNoLevitate = 0;
eq->blooming = 1.0; // Set from PoK Example eq->Blooming = 1.0; // Set from PoK Example
FINISH_ENCODE(); FINISH_ENCODE();
} }
@@ -3946,7 +3975,7 @@ namespace RoF2
if (strlen(emu->suffix)) if (strlen(emu->suffix))
PacketSize += strlen(emu->suffix) + 1; PacketSize += strlen(emu->suffix) + 1;
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) if (emu->DestructibleObject || emu->class_ == 62)
{ {
if (emu->DestructibleObject) if (emu->DestructibleObject)
PacketSize = PacketSize - 4; // No bodytype PacketSize = PacketSize - 4; // No bodytype
@@ -3967,9 +3996,7 @@ namespace RoF2
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{ {
PacketSize += 60; PacketSize += 60;
@@ -4036,19 +4063,17 @@ namespace RoF2
// actually part of bitfields // actually part of bitfields
uint8 OtherData = 0; uint8 OtherData = 0;
if (emu->class_ == LDON_TREASURE) //LDoN Chest if (emu->class_ == 62) //LDoN Chest
{
OtherData = OtherData | 0x04; OtherData = OtherData | 0x04;
}
if (strlen(emu->title)) { if (strlen(emu->title))
OtherData = OtherData | 16; OtherData = OtherData | 16;
}
if (strlen(emu->suffix)) { if (strlen(emu->suffix))
OtherData = OtherData | 32; OtherData = OtherData | 32;
}
if (emu->DestructibleObject) { if (emu->DestructibleObject)
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
// float EmitterScalingRadius // float EmitterScalingRadius
@@ -4064,7 +4089,7 @@ namespace RoF2
// int DefaultEmitterID // int DefaultEmitterID
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) if (emu->DestructibleObject || emu->class_ == 62)
{ {
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel);
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2);
@@ -4172,9 +4197,7 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{ {
@@ -5023,7 +5046,7 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::LootingItem_Struct); DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_LootItem)");
IN(lootee); IN(lootee);
IN(looter); IN(looter);
@@ -5038,7 +5061,7 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)");
emu->from_slot = RoF2ToServerSlot(eq->from_slot); emu->from_slot = RoF2ToServerSlot(eq->from_slot);
emu->to_slot = RoF2ToServerSlot(eq->to_slot); emu->to_slot = RoF2ToServerSlot(eq->to_slot);
@@ -6323,7 +6346,7 @@ namespace RoF2
return; return;
} }
auto segments = Strings::Split(server_saylink, '\x12'); auto segments = SplitString(server_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
@@ -6355,7 +6378,7 @@ namespace RoF2
return; return;
} }
auto segments = Strings::Split(rof2_saylink, '\x12'); auto segments = SplitString(rof2_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
+1 -1
View File
@@ -19,7 +19,7 @@
#include "rof2_limits.h" #include "rof2_limits.h"
#include "../strings.h" #include "../string_util.h"
int16 RoF2::invtype::GetInvTypeSize(int16 inv_type) int16 RoF2::invtype::GetInvTypeSize(int16 inv_type)
+1
View File
@@ -59,6 +59,7 @@ E(OP_DeleteItem)
E(OP_DeleteSpawn) E(OP_DeleteSpawn)
E(OP_DisciplineUpdate) E(OP_DisciplineUpdate)
E(OP_DzChooseZone) E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo) E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite) E(OP_DzExpeditionInvite)
+17 -17
View File
@@ -630,9 +630,9 @@ struct NewZone_Struct {
/*0864*/ uint32 scriptIDSomething; /*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions /*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3; /*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 suspend_buffs; // padded bool /*0876*/ uint32 SuspendBuffs; // padded bool
/*0880*/ uint32 lava_damage; // lava_damage value /*0880*/ uint32 LavaDamage; // LavaDamage value
/*0884*/ uint32 min_lava_damage; // min cap after resist calcs /*0884*/ uint32 MinLavaDamage; // min cap after resist calcs
/*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone /*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone
/*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can! /*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can!
/*0890*/ uint8 bNoAttack; // non-attack zone /*0890*/ uint8 bNoAttack; // non-attack zone
@@ -641,19 +641,19 @@ struct NewZone_Struct {
/*0893*/ uint8 bNoFear; // fear spells no worky /*0893*/ uint8 bNoFear; // fear spells no worky
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber /*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber
/*0895*/ uint8 unknown895; // padding /*0895*/ uint8 unknown895; // padding
/*0896*/ uint32 fast_regen_hp; // percentage I think? /*0896*/ uint32 FastRegenHP; // percentage I think?
/*0900*/ uint32 fast_regen_mana; // percentage I think? /*0900*/ uint32 FastRegenMana; // percentage I think?
/*0904*/ uint32 fast_regen_endurance; // percentage I think? /*0904*/ uint32 FastRegenEndurance; // percentage I think?
/*0908*/ uint32 can_place_campsite; // 0 = no, 1 = can place, 2 = place and goto /*0908*/ uint32 CanPlaceCampsite; // 0 = no, 1 = can place, 2 = place and goto
/*0912*/ uint32 can_place_guild_banner; // ^ /*0912*/ uint32 CanPlaceGuildBanner; // ^
/*0916*/ float fog_density; // Most zones have this set to 0.33 Blightfire had 0.16 /*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 b_adjust_gamma; // padded bool /*0920*/ uint32 bAdjustGamma; // padded bool
/*0924*/ uint32 time_string_id; // Seen 0 /*0924*/ uint32 TimeStringID; // Seen 0
/*0928*/ uint32 b_no_mercenaries; // padded bool /*0928*/ uint32 bNoMercenaries; // padded bool
/*0932*/ int32 fishing_related; // Seen -1 idk /*0932*/ int32 FishingRelated; // Seen -1 idk
/*0936*/ int32 forage_related; // Seen -1 idk /*0936*/ int32 ForageRelated; // Seen -1 idk
/*0940*/ uint32 b_no_levitate; // padded bool /*0940*/ uint32 bNoLevitate; // padded bool
/*0944*/ float blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby /*0944*/ float Blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
/*0948*/ /*0948*/
}; };
@@ -4989,7 +4989,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;
+1 -1
View File
@@ -19,7 +19,7 @@
#include "rof_limits.h" #include "rof_limits.h"
#include "../strings.h" #include "../string_util.h"
int16 RoF::invtype::GetInvTypeSize(int16 inv_type) int16 RoF::invtype::GetInvTypeSize(int16 inv_type)
+1
View File
@@ -45,6 +45,7 @@ E(OP_DeleteItem)
E(OP_DeleteSpawn) E(OP_DeleteSpawn)
E(OP_DisciplineUpdate) E(OP_DisciplineUpdate)
E(OP_DzChooseZone) E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo) E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite) E(OP_DzExpeditionInvite)

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