mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a66c3918a | |||
| a2c6252c58 |
@@ -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
@@ -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:v13
|
# Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20
|
||||||
environment:
|
image: akkadius/eqemu-server:latest
|
||||||
GITHUB_TOKEN:
|
|
||||||
from_secret: GH_RELEASE_GITHUB_API_TOKEN
|
|
||||||
RCLONE_CONFIG_REMOTE_TYPE: ftp
|
|
||||||
RCLONE_FTP_HOST: drone.akkadius.com
|
|
||||||
RCLONE_FTP_USER: artifacts
|
|
||||||
RCLONE_FTP_PASS:
|
|
||||||
from_secret: RCLONE_FTP_PASS
|
|
||||||
commands:
|
commands:
|
||||||
- ./utils/scripts/build/linux-build.sh
|
- sudo chown eqemu:eqemu /drone/src/ * -R
|
||||||
|
- 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
@@ -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
@@ -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
|
||||||
Vendored
+16
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/usr/include/mysql"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++17"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
Vendored
+164
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
-2276
File diff suppressed because it is too large
Load Diff
+12
-39
@@ -1,4 +1,4 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.7)
|
||||||
|
|
||||||
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
|
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
|
||||||
|
|
||||||
@@ -12,36 +12,16 @@ IF(NOT CMAKE_BUILD_TYPE)
|
|||||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
|
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
|
||||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||||
|
|
||||||
SET(CMAKE_CXX_STANDARD 20)
|
SET(CMAKE_CXX_STANDARD 14)
|
||||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
SET(CMAKE_CXX_EXTENSIONS OFF)
|
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF)
|
|
||||||
|
|
||||||
IF (EQEMU_BUILD_STATIC)
|
|
||||||
SET(BUILD_SHARED_LIBS OFF)
|
|
||||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
|
|
||||||
MESSAGE(STATUS "Building with static linking")
|
|
||||||
SET(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
|
|
||||||
IF (UNIX)
|
|
||||||
SET(PERL_LIBRARY "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/libperl.so")
|
|
||||||
SET(PERL_INCLUDE_PATH "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/")
|
|
||||||
SET(PERL_EXECUTABLE "/opt/eqemu-perl/bin/perl")
|
|
||||||
ENDIF ()
|
|
||||||
ENDIF (EQEMU_BUILD_STATIC)
|
|
||||||
|
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
ADD_DEFINITIONS(-DNOMINMAX)
|
ADD_DEFINITIONS(-DNOMINMAX)
|
||||||
ADD_DEFINITIONS(-DCRASH_LOGGING)
|
ADD_DEFINITIONS(-DCRASH_LOGGING)
|
||||||
ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17
|
|
||||||
|
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||||
|
|
||||||
OPTION(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON)
|
|
||||||
IF(EQEMU_DISABLE_MSVC_WARNINGS)
|
|
||||||
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
|
|
||||||
ENDIF(EQEMU_DISABLE_MSVC_WARNINGS)
|
|
||||||
ELSE(MSVC)
|
ELSE(MSVC)
|
||||||
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
|
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
@@ -138,16 +118,11 @@ ELSE()
|
|||||||
MESSAGE(STATUS "* mbedTLS: MISSING *")
|
MESSAGE(STATUS "* mbedTLS: MISSING *")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
MESSAGE(STATUS "PERL_INCLUDE_PATH: ${PERL_INCLUDE_PATH}")
|
|
||||||
MESSAGE(STATUS "PERL_LIBRARY: ${PERL_LIBRARY}")
|
|
||||||
MESSAGE(STATUS "PERL_INCLUDE_DIR: ${PERL_INCLUDE_DIR}")
|
|
||||||
MESSAGE(STATUS "PERL_INCLUDE_DIRS: ${PERL_INCLUDE_DIRS}")
|
|
||||||
MESSAGE(STATUS "PERL_LIBRARIES: ${PERL_LIBRARIES}")
|
|
||||||
MESSAGE(STATUS "PERL_VERSION: ${PERL_VERSION}")
|
|
||||||
|
|
||||||
MESSAGE(STATUS "**************************************************")
|
MESSAGE(STATUS "**************************************************")
|
||||||
|
|
||||||
#options
|
#options
|
||||||
|
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
|
||||||
|
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
|
||||||
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
|
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
|
||||||
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
|
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
|
||||||
OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
|
OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
|
||||||
@@ -201,6 +176,10 @@ IF(EQEMU_COMMANDS_LOGGING)
|
|||||||
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
|
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
|
||||||
ENDIF(EQEMU_COMMANDS_LOGGING)
|
ENDIF(EQEMU_COMMANDS_LOGGING)
|
||||||
|
|
||||||
|
IF(EQEMU_ENABLE_BOTS)
|
||||||
|
ADD_DEFINITIONS(-DBOTS)
|
||||||
|
ENDIF(EQEMU_ENABLE_BOTS)
|
||||||
|
|
||||||
#database
|
#database
|
||||||
IF(MySQL_FOUND AND MariaDB_FOUND)
|
IF(MySQL_FOUND AND MariaDB_FOUND)
|
||||||
SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use:
|
SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use:
|
||||||
@@ -332,10 +311,6 @@ ELSE()
|
|||||||
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF (EQEMU_BUILD_STATIC)
|
|
||||||
SET(ZLIB_LIBRARY_LIBS libz.a)
|
|
||||||
ENDIF(EQEMU_BUILD_STATIC)
|
|
||||||
|
|
||||||
MESSAGE(STATUS "")
|
MESSAGE(STATUS "")
|
||||||
MESSAGE(STATUS "**************************************************")
|
MESSAGE(STATUS "**************************************************")
|
||||||
MESSAGE(STATUS "* Library Usage *")
|
MESSAGE(STATUS "* Library Usage *")
|
||||||
@@ -365,8 +340,10 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat
|
|||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
|
||||||
|
|
||||||
# silence obnoxious deprecation message
|
OPTION(EQEMU_BUILD_LOGGING "Build Logging (To speed up compilation)" ON)
|
||||||
ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
|
IF(EQEMU_BUILD_LOGGING)
|
||||||
|
ADD_DEFINITIONS(-DBUILD_LOGGING)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF(TLS_LIBRARY_ENABLED)
|
IF(TLS_LIBRARY_ENABLED)
|
||||||
SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS})
|
SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS})
|
||||||
@@ -400,10 +377,6 @@ IF(PERL_LIBRARY_ENABLED)
|
|||||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
|
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
|
||||||
ADD_DEFINITIONS(-DEMBPERL)
|
ADD_DEFINITIONS(-DEMBPERL)
|
||||||
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
|
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
|
||||||
ADD_DEFINITIONS(-DPERLBIND_NO_STRICT_SCALAR_TYPES)
|
|
||||||
IF (UNIX AND EQEMU_BUILD_STATIC)
|
|
||||||
SET(SERVER_LIBS ${SERVER_LIBS} libcrypt.a)
|
|
||||||
ENDIF ()
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
|||||||
@@ -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) |
|
||||||
|:---:|:---:|
|
|:---:|:---:|:---:|
|
||||||
|[](http://drone.akkadius.com/EQEmu/Server) |[](http://drone.akkadius.com/EQEmu/Server) |
|
|[](https://travis-ci.org/EQEmu/Server) |[](https://ci.appveyor.com/project/KimLS/server) |[](https://ci.appveyor.com/project/KimLS/server-87crp) |
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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,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
|
||||||
|
|||||||
@@ -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,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
|
||||||
|
|||||||
@@ -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')",
|
||||||
|
|||||||
+734
-765
File diff suppressed because it is too large
Load Diff
+190
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
* obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
* this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
* execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
* Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
* do so, all subject to the following:
|
||||||
|
*
|
||||||
|
* The copyright notices in the Software and this entire statement, including
|
||||||
|
* the above license grant, this restriction and the following disclaimer,
|
||||||
|
* must be included in all copies of the Software, in whole or in part, and
|
||||||
|
* all derivative works of the Software, unless such copies or derivative
|
||||||
|
* works are solely in the form of machine-executable object code generated by
|
||||||
|
* a source language processor.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// EQ::Any is a modified version of Boost::Any and as such retains the Boost licensing.
|
||||||
|
|
||||||
|
#ifndef EQEMU_COMMON_ANY_H
|
||||||
|
#define EQEMU_COMMON_ANY_H
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
class Any
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Any()
|
||||||
|
: content(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
Any(const ValueType &value)
|
||||||
|
: content(new Holder<ValueType>(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Any(const Any &other)
|
||||||
|
: content(other.content ? other.content->clone() : 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~Any()
|
||||||
|
{
|
||||||
|
if(content)
|
||||||
|
delete content;
|
||||||
|
}
|
||||||
|
|
||||||
|
Any& swap(Any &rhs)
|
||||||
|
{
|
||||||
|
std::swap(content, rhs.content);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
Any& operator=(const ValueType &rhs)
|
||||||
|
{
|
||||||
|
Any(rhs).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Any& operator=(Any rhs)
|
||||||
|
{
|
||||||
|
rhs.swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return !content;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::type_info& type() const
|
||||||
|
{
|
||||||
|
return content ? content->type() : typeid(void);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Placeholder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Placeholder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const std::type_info& type() const = 0;
|
||||||
|
virtual Placeholder* clone() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
class Holder : public Placeholder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Holder(const ValueType &value)
|
||||||
|
: held(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const std::type_info& type() const
|
||||||
|
{
|
||||||
|
return typeid(ValueType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Placeholder* clone() const
|
||||||
|
{
|
||||||
|
return new Holder(held);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType held;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Holder& operator=(const Holder&);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename ValueType>
|
||||||
|
friend ValueType* any_cast(Any*);
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
friend ValueType* unsafe_any_cast(Any*);
|
||||||
|
|
||||||
|
Placeholder* content;
|
||||||
|
};
|
||||||
|
|
||||||
|
class bad_any_cast : public std::bad_cast
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const char * what() const throw()
|
||||||
|
{
|
||||||
|
return "DBI::bad_any_cast: failed conversion using DBI::any_cast";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
ValueType* any_cast(Any* operand)
|
||||||
|
{
|
||||||
|
return operand &&
|
||||||
|
operand->type() == typeid(ValueType) ? &static_cast<Any::Holder<ValueType>*>(operand->content)->held : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline const ValueType* any_cast(const Any* operand)
|
||||||
|
{
|
||||||
|
return any_cast<ValueType>(const_cast<Any*>(operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
ValueType any_cast(Any& operand)
|
||||||
|
{
|
||||||
|
typedef typename std::remove_reference<ValueType>::type nonref;
|
||||||
|
nonref* result = any_cast<nonref>(&operand);
|
||||||
|
if(!result)
|
||||||
|
throw bad_any_cast();
|
||||||
|
return *result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType any_cast(const Any& operand)
|
||||||
|
{
|
||||||
|
typedef typename std::remove_reference<ValueType>::type nonref;
|
||||||
|
return any_cast<const nonref&>(const_cast<Any&>(operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType* unsafe_any_cast(Any* operand)
|
||||||
|
{
|
||||||
|
return &static_cast<Any::Holder<ValueType>*>(operand->content)->held;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline const ValueType* unsafe_any_cast(const Any* operand)
|
||||||
|
{
|
||||||
|
return unsafe_any_cast<ValueType>(const_cast<Any*>(operand));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
#include "../common/global_define.h"
|
#include "../common/global_define.h"
|
||||||
#include "../common/classes.h"
|
#include "../common/classes.h"
|
||||||
#include "data_verification.h"
|
|
||||||
|
|
||||||
const char *GetClassIDName(uint8 class_id, uint8 level)
|
const char *GetClassIDName(uint8 class_id, uint8 level)
|
||||||
{
|
{
|
||||||
@@ -631,20 +630,6 @@ bool IsINTCasterClass(uint8 class_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsHeroicINTCasterClass(uint8 class_id)
|
|
||||||
{
|
|
||||||
switch (class_id) {
|
|
||||||
case NECROMANCER:
|
|
||||||
case WIZARD:
|
|
||||||
case MAGICIAN:
|
|
||||||
case ENCHANTER:
|
|
||||||
case SHADOWKNIGHT:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsWISCasterClass(uint8 class_id)
|
bool IsWISCasterClass(uint8 class_id)
|
||||||
{
|
{
|
||||||
switch (class_id) {
|
switch (class_id) {
|
||||||
@@ -657,21 +642,6 @@ bool IsWISCasterClass(uint8 class_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsHeroicWISCasterClass(uint8 class_id)
|
|
||||||
{
|
|
||||||
switch (class_id) {
|
|
||||||
case CLERIC:
|
|
||||||
case DRUID:
|
|
||||||
case SHAMAN:
|
|
||||||
case PALADIN:
|
|
||||||
case BEASTLORD:
|
|
||||||
case RANGER:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsPlateClass(uint8 class_id)
|
bool IsPlateClass(uint8 class_id)
|
||||||
{
|
{
|
||||||
switch (class_id) {
|
switch (class_id) {
|
||||||
@@ -751,51 +721,3 @@ uint8 ClassArmorType(uint8 class_id)
|
|||||||
return ARMOR_TYPE_UNKNOWN;
|
return ARMOR_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string GetPlayerClassAbbreviation(uint8 class_id)
|
|
||||||
{
|
|
||||||
if (!EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) {
|
|
||||||
return std::string("UNK");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (class_id) {
|
|
||||||
case WARRIOR:
|
|
||||||
return "WAR";
|
|
||||||
case CLERIC:
|
|
||||||
return "CLR";
|
|
||||||
case PALADIN:
|
|
||||||
return "PAL";
|
|
||||||
case RANGER:
|
|
||||||
return "RNG";
|
|
||||||
case SHADOWKNIGHT:
|
|
||||||
return "SHD";
|
|
||||||
case DRUID:
|
|
||||||
return "DRU";
|
|
||||||
case MONK:
|
|
||||||
return "MNK";
|
|
||||||
case BARD:
|
|
||||||
return "BRD";
|
|
||||||
case ROGUE:
|
|
||||||
return "ROG";
|
|
||||||
case SHAMAN:
|
|
||||||
return "SHM";
|
|
||||||
case NECROMANCER:
|
|
||||||
return "NEC";
|
|
||||||
case WIZARD:
|
|
||||||
return "WIZ";
|
|
||||||
case MAGICIAN:
|
|
||||||
return "MAG";
|
|
||||||
case ENCHANTER:
|
|
||||||
return "ENC";
|
|
||||||
case BEASTLORD:
|
|
||||||
return "BST";
|
|
||||||
case BERSERKER:
|
|
||||||
return "BER";
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string("UNK");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsPlayerClass(uint8 class_id) {
|
|
||||||
return EQ::ValueWithin(class_id, WARRIOR, BERSERKER);
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-7
@@ -19,9 +19,7 @@
|
|||||||
#define CLASSES_CH
|
#define CLASSES_CH
|
||||||
|
|
||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define NO_CLASS 0
|
|
||||||
#define WARRIOR 1
|
#define WARRIOR 1
|
||||||
#define CLERIC 2
|
#define CLERIC 2
|
||||||
#define PALADIN 3
|
#define PALADIN 3
|
||||||
@@ -128,9 +126,6 @@
|
|||||||
const char* GetClassIDName(uint8 class_id, uint8 level = 0);
|
const char* GetClassIDName(uint8 class_id, uint8 level = 0);
|
||||||
const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0);
|
const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0);
|
||||||
|
|
||||||
bool IsPlayerClass(uint8 class_id);
|
|
||||||
const std::string GetPlayerClassAbbreviation(uint8 class_id);
|
|
||||||
|
|
||||||
uint32 GetPlayerClassValue(uint8 class_id);
|
uint32 GetPlayerClassValue(uint8 class_id);
|
||||||
uint32 GetPlayerClassBit(uint8 class_id);
|
uint32 GetPlayerClassBit(uint8 class_id);
|
||||||
|
|
||||||
@@ -144,8 +139,7 @@ bool IsHybridClass(uint8 class_id);
|
|||||||
bool IsCasterClass(uint8 class_id);
|
bool IsCasterClass(uint8 class_id);
|
||||||
bool IsINTCasterClass(uint8 class_id);
|
bool IsINTCasterClass(uint8 class_id);
|
||||||
bool IsWISCasterClass(uint8 class_id);
|
bool IsWISCasterClass(uint8 class_id);
|
||||||
bool IsHeroicINTCasterClass(uint8 class_id);
|
|
||||||
bool IsHeroicWISCasterClass(uint8 class_id);
|
|
||||||
bool IsPlateClass(uint8 class_id);
|
bool IsPlateClass(uint8 class_id);
|
||||||
bool IsChainClass(uint8 class_id);
|
bool IsChainClass(uint8 class_id);
|
||||||
bool IsLeatherClass(uint8 class_id);
|
bool IsLeatherClass(uint8 class_id);
|
||||||
|
|||||||
@@ -39,15 +39,15 @@ namespace EQEmuCommand {
|
|||||||
{
|
{
|
||||||
if (cmd[{"-d", "--debug"}]) {
|
if (cmd[{"-d", "--debug"}]) {
|
||||||
std::cout << "Positional args:\n";
|
std::cout << "Positional args:\n";
|
||||||
for (auto &pos_arg: cmd.pos_args())
|
for (auto &pos_arg : cmd.pos_args())
|
||||||
std::cout << '\t' << pos_arg << std::endl;
|
std::cout << '\t' << pos_arg << std::endl;
|
||||||
|
|
||||||
std::cout << "\nFlags:\n";
|
std::cout << "\nFlags:\n";
|
||||||
for (auto &flag: cmd.flags())
|
for (auto &flag : cmd.flags())
|
||||||
std::cout << '\t' << flag << std::endl;
|
std::cout << '\t' << flag << std::endl;
|
||||||
|
|
||||||
std::cout << "\nParameters:\n";
|
std::cout << "\nParameters:\n";
|
||||||
for (auto ¶m: cmd.params())
|
for (auto ¶m : cmd.params())
|
||||||
std::cout << '\t' << param.first << " : " << param.second << std::endl;
|
std::cout << '\t' << param.first << " : " << param.second << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,22 +69,22 @@ namespace EQEmuCommand {
|
|||||||
{
|
{
|
||||||
bool arguments_filled = true;
|
bool arguments_filled = true;
|
||||||
|
|
||||||
int index = 2;
|
int index = 2;
|
||||||
for (auto &arg: arguments) {
|
for (auto &arg : arguments) {
|
||||||
if (cmd(arg).str().empty() && cmd(index).str().empty()) {
|
if (cmd(arg).str().empty() && cmd(index).str().empty()) {
|
||||||
arguments_filled = false;
|
arguments_filled = false;
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arguments_filled || (argc == 2 && !cmd[{"-h", "--help"}]) || (argc == 3 && cmd[{"-h", "--help"}])) {
|
if (!arguments_filled || argc == 2 || cmd[{"-h", "--help"}]) {
|
||||||
std::string arguments_string;
|
std::string arguments_string;
|
||||||
for (auto &arg: arguments) {
|
for (auto &arg : arguments) {
|
||||||
arguments_string += " " + arg;
|
arguments_string += " " + arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string options_string;
|
std::string options_string;
|
||||||
for (auto &opt: options) {
|
for (auto &opt : options) {
|
||||||
options_string += " " + opt + "\n";
|
options_string += " " + opt + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +124,14 @@ namespace EQEmuCommand {
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
std::string description;
|
std::string description;
|
||||||
|
bool ran_command = false;
|
||||||
|
for (auto &it: in_function_map) {
|
||||||
|
if (it.first == argv[1]) {
|
||||||
|
(it.second)(argc, argv, cmd, description);
|
||||||
|
ran_command = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd[{"-h", "--help"}]) {
|
if (cmd[{"-h", "--help"}]) {
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout <<
|
std::cout <<
|
||||||
@@ -134,7 +142,9 @@ namespace EQEmuCommand {
|
|||||||
<< std::endl
|
<< std::endl
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
// Get max command length for padding length
|
/**
|
||||||
|
* Get max command length for padding length
|
||||||
|
*/
|
||||||
int max_command_length = 0;
|
int max_command_length = 0;
|
||||||
|
|
||||||
for (auto &it: in_function_map) {
|
for (auto &it: in_function_map) {
|
||||||
@@ -145,14 +155,18 @@ namespace EQEmuCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display command menu
|
/**
|
||||||
|
* Display command menu
|
||||||
|
*/
|
||||||
std::string command_section;
|
std::string command_section;
|
||||||
for (auto &it: in_function_map) {
|
for (auto &it: in_function_map) {
|
||||||
description.clear();
|
description = "";
|
||||||
|
|
||||||
(it.second)(argc, argv, cmd, description);
|
(it.second)(argc, argv, cmd, description);
|
||||||
|
|
||||||
// Print section header
|
/**
|
||||||
|
* Print section header
|
||||||
|
*/
|
||||||
std::string command_prefix = it.first.substr(0, it.first.find(":"));
|
std::string command_prefix = it.first.substr(0, it.first.find(":"));
|
||||||
|
|
||||||
if (command_prefix.find("test") != std::string::npos) {
|
if (command_prefix.find("test") != std::string::npos) {
|
||||||
@@ -164,7 +178,9 @@ namespace EQEmuCommand {
|
|||||||
std::cout << termcolor::reset << command_prefix << std::endl;
|
std::cout << termcolor::reset << command_prefix << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print commands
|
/**
|
||||||
|
* Print commands
|
||||||
|
*/
|
||||||
std::stringstream command;
|
std::stringstream command;
|
||||||
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
|
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
|
||||||
printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str());
|
printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str());
|
||||||
@@ -175,15 +191,6 @@ namespace EQEmuCommand {
|
|||||||
std::exit(0);
|
std::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ran_command = false;
|
|
||||||
|
|
||||||
for (auto &it: in_function_map) {
|
|
||||||
if (it.first == argv[1]) {
|
|
||||||
(it.second)(argc, argv, cmd, description);
|
|
||||||
ran_command = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ran_command) {
|
if (ran_command) {
|
||||||
std::exit(0);
|
std::exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
|
|||||||
/**
|
/**
|
||||||
* @param content_flags
|
* @param content_flags
|
||||||
*/
|
*/
|
||||||
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags)
|
void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags)
|
||||||
{
|
{
|
||||||
WorldContentService::content_flags = content_flags;
|
WorldContentService::content_flags = content_flags;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ public:
|
|||||||
std::vector<std::string> GetContentFlagsDisabled();
|
std::vector<std::string> GetContentFlagsDisabled();
|
||||||
bool IsContentFlagEnabled(const std::string& content_flag);
|
bool IsContentFlagEnabled(const std::string& content_flag);
|
||||||
bool IsContentFlagDisabled(const std::string& content_flag);
|
bool IsContentFlagDisabled(const std::string& content_flag);
|
||||||
void SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags);
|
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
|
||||||
void ReloadContentFlags();
|
void ReloadContentFlags();
|
||||||
WorldContentService * SetExpansionContext();
|
WorldContentService * SetExpansionContext();
|
||||||
|
|
||||||
|
|||||||
+9
-142
@@ -1,95 +1,6 @@
|
|||||||
#include "global_define.h"
|
#include "global_define.h"
|
||||||
#include "eqemu_logsys.h"
|
#include "eqemu_logsys.h"
|
||||||
#include "crash.h"
|
#include "crash.h"
|
||||||
#include "strings.h"
|
|
||||||
#include "process/process.h"
|
|
||||||
#include "http/httplib.h"
|
|
||||||
#include "http/uri.h"
|
|
||||||
#include "json/json.h"
|
|
||||||
#include "version.h"
|
|
||||||
#include "eqemu_config.h"
|
|
||||||
#include "serverinfo.h"
|
|
||||||
#include "rulesys.h"
|
|
||||||
#include "platform.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#if WINDOWS
|
|
||||||
#define popen _popen
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SendCrashReport(const std::string &crash_report)
|
|
||||||
{
|
|
||||||
// can configure multiple endpoints if need be
|
|
||||||
std::vector<std::string> endpoints = {
|
|
||||||
"http://spire.akkadius.com/api/v1/analytics/server-crash-report",
|
|
||||||
// "http://localhost:3010/api/v1/analytics/server-crash-report", // development
|
|
||||||
};
|
|
||||||
|
|
||||||
auto config = EQEmuConfig::get();
|
|
||||||
for (auto &e: endpoints) {
|
|
||||||
uri u(e);
|
|
||||||
|
|
||||||
std::string base_url = fmt::format("{}://{}", u.get_scheme(), u.get_host());
|
|
||||||
if (u.get_port()) {
|
|
||||||
base_url += fmt::format(":{}", u.get_port());
|
|
||||||
}
|
|
||||||
|
|
||||||
// client
|
|
||||||
httplib::Client r(base_url);
|
|
||||||
r.set_connection_timeout(1, 0);
|
|
||||||
r.set_read_timeout(1, 0);
|
|
||||||
r.set_write_timeout(1, 0);
|
|
||||||
|
|
||||||
// os info
|
|
||||||
auto os = EQ::GetOS();
|
|
||||||
auto cpus = EQ::GetCPUs();
|
|
||||||
auto process_id = EQ::GetPID();
|
|
||||||
auto rss = EQ::GetRSS() / 1048576.0;
|
|
||||||
auto uptime = static_cast<uint32>(EQ::GetUptime());
|
|
||||||
|
|
||||||
// payload
|
|
||||||
Json::Value p;
|
|
||||||
p["platform_name"] = GetPlatformName();
|
|
||||||
p["crash_report"] = crash_report;
|
|
||||||
p["server_version"] = CURRENT_VERSION;
|
|
||||||
p["compile_date"] = COMPILE_DATE;
|
|
||||||
p["compile_time"] = COMPILE_TIME;
|
|
||||||
p["server_name"] = config->LongName;
|
|
||||||
p["server_short_name"] = config->ShortName;
|
|
||||||
p["uptime"] = uptime;
|
|
||||||
p["os_machine"] = os.machine;
|
|
||||||
p["os_release"] = os.release;
|
|
||||||
p["os_version"] = os.version;
|
|
||||||
p["os_sysname"] = os.sysname;
|
|
||||||
p["process_id"] = process_id;
|
|
||||||
p["rss_memory"] = rss;
|
|
||||||
p["cpus"] = cpus.size();
|
|
||||||
p["origination_info"] = "";
|
|
||||||
|
|
||||||
if (!LogSys.origination_info.zone_short_name.empty()) {
|
|
||||||
p["origination_info"] = fmt::format(
|
|
||||||
"{} ({}) instance_id [{}]",
|
|
||||||
LogSys.origination_info.zone_short_name,
|
|
||||||
LogSys.origination_info.zone_long_name,
|
|
||||||
LogSys.origination_info.instance_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream payload;
|
|
||||||
payload << p;
|
|
||||||
|
|
||||||
if (auto res = r.Post(e, payload.str(), "application/json")) {
|
|
||||||
if (res->status == 200) {
|
|
||||||
LogInfo("Sent crash report");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogError("Failed to send crash report to [{}]", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
|
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
|
||||||
#include "StackWalker.h"
|
#include "StackWalker.h"
|
||||||
@@ -101,30 +12,22 @@ public:
|
|||||||
EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { }
|
EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { }
|
||||||
virtual void OnOutput(LPCSTR szText) {
|
virtual void OnOutput(LPCSTR szText) {
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
for (int i = 0; i < 4096; ++i) {
|
for(int i = 0; i < 4096; ++i) {
|
||||||
if (szText[i] == 0) {
|
if(szText[i] == 0) {
|
||||||
buffer[i] = '\0';
|
buffer[i] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szText[i] == '\n' || szText[i] == '\r') {
|
if(szText[i] == '\n' || szText[i] == '\r') {
|
||||||
buffer[i] = ' ';
|
buffer[i] = ' ';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
buffer[i] = szText[i];
|
buffer[i] = szText[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string line = buffer;
|
|
||||||
_lines.push_back(line);
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::Crash, buffer);
|
Log(Logs::General, Logs::Crash, buffer);
|
||||||
StackWalker::OnOutput(szText);
|
StackWalker::OnOutput(szText);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& GetLines() { return _lines; }
|
|
||||||
private:
|
|
||||||
std::vector<std::string> _lines;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
||||||
@@ -198,20 +101,7 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
|||||||
|
|
||||||
if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
|
if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
|
||||||
{
|
{
|
||||||
EQEmuStackWalker sw;
|
EQEmuStackWalker sw; sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
|
||||||
sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
|
|
||||||
|
|
||||||
if (RuleB(Analytics, CrashReporting)) {
|
|
||||||
std::string crash_report;
|
|
||||||
auto& lines = sw.GetLines();
|
|
||||||
|
|
||||||
for (auto& line : lines) {
|
|
||||||
crash_report += line;
|
|
||||||
crash_report += "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
SendCrashReport(crash_report);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
@@ -235,27 +125,9 @@ void set_exception_handler() {
|
|||||||
|
|
||||||
void print_trace()
|
void print_trace()
|
||||||
{
|
{
|
||||||
bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU");
|
auto uid = geteuid();
|
||||||
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();
|
std::string temp_output_file = "/tmp/dump-output";
|
||||||
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
|
|
||||||
|
|
||||||
// check for passwordless sudo if not root
|
|
||||||
if (uid != 0) {
|
|
||||||
bool sudo_password_required = Strings::Contains(Process::execute("sudo -n true"), "a password is required");
|
|
||||||
if (sudo_password_required) {
|
|
||||||
LogCrash(
|
|
||||||
"[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root."
|
|
||||||
);
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char pid_buf[30];
|
char pid_buf[30];
|
||||||
sprintf(pid_buf, "%d", getpid());
|
sprintf(pid_buf, "%d", getpid());
|
||||||
@@ -264,6 +136,7 @@ void print_trace()
|
|||||||
int child_pid = fork();
|
int child_pid = fork();
|
||||||
if (!child_pid) {
|
if (!child_pid) {
|
||||||
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||||
|
|
||||||
dup2(fd, 1); // redirect output to stderr
|
dup2(fd, 1); // redirect output to stderr
|
||||||
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
|
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
|
||||||
if (uid == 0) {
|
if (uid == 0) {
|
||||||
@@ -278,22 +151,16 @@ void print_trace()
|
|||||||
abort(); /* If gdb failed to start */
|
abort(); /* If gdb failed to start */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
waitpid(child_pid, nullptr, 0);
|
waitpid(child_pid, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream input(temp_output_file);
|
std::ifstream input(temp_output_file);
|
||||||
std::string crash_report;
|
|
||||||
for (std::string line; getline(input, line);) {
|
for (std::string line; getline(input, line);) {
|
||||||
LogCrash("{}", line);
|
LogCrash("{}", line);
|
||||||
crash_report += fmt::format("{}\n", line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::remove(temp_output_file.c_str());
|
std::remove(temp_output_file.c_str());
|
||||||
|
|
||||||
if (RuleB(Analytics, CrashReporting)) {
|
|
||||||
SendCrashReport(crash_report);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
+381
-334
File diff suppressed because it is too large
Load Diff
+23
-15
@@ -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);
|
||||||
|
|
||||||
@@ -235,12 +241,14 @@ public:
|
|||||||
/* Database Variables */
|
/* Database Variables */
|
||||||
|
|
||||||
bool GetVariable(std::string varname, std::string &varvalue);
|
bool GetVariable(std::string varname, std::string &varvalue);
|
||||||
bool SetVariable(const std::string& varname, const std::string &varvalue);
|
bool SetVariable(const std::string varname, const std::string &varvalue);
|
||||||
bool LoadVariables();
|
bool LoadVariables();
|
||||||
|
|
||||||
/* General Queries */
|
/* General Queries */
|
||||||
|
|
||||||
|
bool GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, float* safe_heading = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr);
|
||||||
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0);
|
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0);
|
||||||
|
bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0);
|
||||||
bool LoadPTimers(uint32 charid, PTimerList &into);
|
bool LoadPTimers(uint32 charid, PTimerList &into);
|
||||||
|
|
||||||
uint8 GetPEQZone(uint32 zone_id, uint32 version);
|
uint8 GetPEQZone(uint32 zone_id, uint32 version);
|
||||||
@@ -263,7 +271,7 @@ public:
|
|||||||
void ClearInvSnapshots(bool from_now = false);
|
void ClearInvSnapshots(bool from_now = false);
|
||||||
|
|
||||||
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
|
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
|
||||||
void SourceSqlFromUrl(std::string url);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
@@ -23,12 +23,10 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include "database_dump_service.h"
|
#include "database_dump_service.h"
|
||||||
#include "../eqemu_logsys.h"
|
#include "../eqemu_logsys.h"
|
||||||
#include "../strings.h"
|
#include "../string_util.h"
|
||||||
#include "../eqemu_config.h"
|
#include "../eqemu_config.h"
|
||||||
#include "../database_schema.h"
|
#include "../database_schema.h"
|
||||||
#include "../file.h"
|
#include "../file_util.h"
|
||||||
#include "../process/process.h"
|
|
||||||
#include "../termcolor/rang.hpp"
|
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
@@ -37,12 +35,43 @@
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DATABASE_DUMP_PATH "backups/"
|
#define DATABASE_DUMP_PATH "backups/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cmd
|
||||||
|
* @param return_result
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true)
|
||||||
|
{
|
||||||
|
const char *file_name = "db-exec-result.txt";
|
||||||
|
|
||||||
|
if (return_result) {
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
std::system((cmd + " > " + file_name + " 2>&1").c_str());
|
||||||
|
#else
|
||||||
|
std::system((cmd + " > " + file_name).c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::system((cmd).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
if (return_result) {
|
||||||
|
std::ifstream file(file_name);
|
||||||
|
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
|
||||||
|
std::remove(file_name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -59,7 +88,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
|
|||||||
*/
|
*/
|
||||||
bool DatabaseDumpService::IsTarAvailable()
|
bool DatabaseDumpService::IsTarAvailable()
|
||||||
{
|
{
|
||||||
std::string version_output = Process::execute("tar --version");
|
std::string version_output = execute("tar --version");
|
||||||
|
|
||||||
return version_output.find("GNU tar") != std::string::npos;
|
return version_output.find("GNU tar") != std::string::npos;
|
||||||
}
|
}
|
||||||
@@ -70,7 +99,7 @@ bool DatabaseDumpService::IsTarAvailable()
|
|||||||
*/
|
*/
|
||||||
bool DatabaseDumpService::Is7ZipAvailable()
|
bool DatabaseDumpService::Is7ZipAvailable()
|
||||||
{
|
{
|
||||||
std::string version_output = Process::execute("7z --help");
|
std::string version_output = execute("7z --help");
|
||||||
|
|
||||||
return version_output.find("7-Zip") != std::string::npos;
|
return version_output.find("7-Zip") != std::string::npos;
|
||||||
}
|
}
|
||||||
@@ -88,13 +117,11 @@ bool DatabaseDumpService::HasCompressionBinary()
|
|||||||
*/
|
*/
|
||||||
std::string DatabaseDumpService::GetMySQLVersion()
|
std::string DatabaseDumpService::GetMySQLVersion()
|
||||||
{
|
{
|
||||||
std::string version_output = Process::execute("mysql --version");
|
std::string version_output = execute("mysql --version");
|
||||||
|
|
||||||
return Strings::Trim(version_output);
|
return trim(version_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string CREDENTIALS_FILE = "login.my.cnf";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -103,66 +130,128 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
|
|||||||
auto config = EQEmuConfig::get();
|
auto config = EQEmuConfig::get();
|
||||||
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
|
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
|
||||||
return fmt::format(
|
return fmt::format(
|
||||||
"mysqldump --defaults-extra-file={} {}",
|
"mysqldump -u {} -p{} -h {} --port={} {}",
|
||||||
CREDENTIALS_FILE,
|
config->ContentDbUsername,
|
||||||
|
config->ContentDbPassword,
|
||||||
|
config->ContentDbHost,
|
||||||
|
config->ContentDbPort,
|
||||||
config->ContentDbName
|
config->ContentDbName
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return fmt::format(
|
return fmt::format(
|
||||||
"mysqldump --defaults-extra-file={} {}",
|
"mysqldump -u {} -p{} -h {} --port={} {}",
|
||||||
CREDENTIALS_FILE,
|
config->DatabaseUsername,
|
||||||
|
config->DatabasePassword,
|
||||||
|
config->DatabaseHost,
|
||||||
|
config->DatabasePort,
|
||||||
config->DatabaseDB
|
config->DatabaseDB
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
std::string DatabaseDumpService::GetPlayerTablesList()
|
std::string DatabaseDumpService::GetPlayerTablesList()
|
||||||
{
|
{
|
||||||
return Strings::Join(DatabaseSchema::GetPlayerTables(), " ");
|
std::string tables_list;
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetPlayerTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
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) {
|
||||||
std::string DatabaseDumpService::GetMercTablesList()
|
tables_list += table + " ";
|
||||||
{
|
}
|
||||||
return Strings::Join(DatabaseSchema::GetMercTables(), " ");
|
|
||||||
|
return trim(tables_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
std::string DatabaseDumpService::GetLoginTableList()
|
std::string DatabaseDumpService::GetLoginTableList()
|
||||||
{
|
{
|
||||||
return Strings::Join(DatabaseSchema::GetLoginTables(), " ");
|
std::string tables_list;
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetLoginTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
std::string DatabaseDumpService::GetQueryServTables()
|
std::string DatabaseDumpService::GetQueryServTables()
|
||||||
{
|
{
|
||||||
return Strings::Join(DatabaseSchema::GetQueryServerTables(), " ");
|
std::string tables_list;
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetQueryServerTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
std::string DatabaseDumpService::GetSystemTablesList()
|
std::string DatabaseDumpService::GetSystemTablesList()
|
||||||
{
|
{
|
||||||
auto system_tables = DatabaseSchema::GetServerTables();
|
std::string tables_list;
|
||||||
auto version_tables = DatabaseSchema::GetVersionTables();
|
|
||||||
|
|
||||||
system_tables.insert(
|
std::vector<std::string> tables = DatabaseSchema::GetServerTables();
|
||||||
std::end(system_tables),
|
for (const auto &table : tables) {
|
||||||
std::begin(version_tables),
|
tables_list += table + " ";
|
||||||
std::end(version_tables)
|
}
|
||||||
);
|
|
||||||
|
|
||||||
return Strings::Join(system_tables, " ");
|
tables = DatabaseSchema::GetVersionTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
std::string DatabaseDumpService::GetStateTablesList()
|
std::string DatabaseDumpService::GetStateTablesList()
|
||||||
{
|
{
|
||||||
return Strings::Join(DatabaseSchema::GetStateTables(), " ");
|
std::string tables_list;
|
||||||
|
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetStateTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
std::string DatabaseDumpService::GetContentTablesList()
|
std::string DatabaseDumpService::GetContentTablesList()
|
||||||
{
|
{
|
||||||
return Strings::Join(DatabaseSchema::GetContentTables(), " ");
|
std::string tables_list;
|
||||||
|
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetContentTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,7 +286,7 @@ std::string DatabaseDumpService::GetDumpFileNameWithPath()
|
|||||||
return GetSetDumpPath() + GetDumpFileName();
|
return GetSetDumpPath() + GetDumpFileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseDumpService::DatabaseDump()
|
void DatabaseDumpService::Dump()
|
||||||
{
|
{
|
||||||
if (!IsMySQLInstalled()) {
|
if (!IsMySQLInstalled()) {
|
||||||
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
|
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
|
||||||
@@ -248,11 +337,6 @@ void DatabaseDumpService::DatabaseDump()
|
|||||||
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";
|
||||||
@@ -279,11 +363,6 @@ void DatabaseDumpService::DatabaseDump()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDumpStaticInstanceData()) {
|
|
||||||
tables_to_dump += "instance_list";
|
|
||||||
options += " --no-create-info --where=\"instance_list.is_global > 0 and instance_list.never_expires > 0\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dump_descriptor.empty()) {
|
if (!dump_descriptor.empty()) {
|
||||||
SetDumpFileName(GetDumpFileName() + dump_descriptor);
|
SetDumpFileName(GetDumpFileName() + dump_descriptor);
|
||||||
}
|
}
|
||||||
@@ -296,72 +375,48 @@ void DatabaseDumpService::DatabaseDump()
|
|||||||
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
|
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
|
std::string execute_command = fmt::format(
|
||||||
File::Makedir(GetSetDumpPath());
|
"{} {} {} {}",
|
||||||
|
GetBaseMySQLDumpCommand(),
|
||||||
|
options,
|
||||||
|
tables_to_dump,
|
||||||
|
pipe_file
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tables_to_dump.empty()) {
|
if (tables_to_dump.empty()) {
|
||||||
std::cerr << "No tables were specified" << std::endl;
|
std::cerr << "No tables were specified" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const auto execute_command = fmt::format(
|
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
|
||||||
"{} {} {} {}",
|
if (!execution_result.empty()) {
|
||||||
GetBaseMySQLDumpCommand(),
|
|
||||||
options,
|
|
||||||
tables_to_dump,
|
|
||||||
pipe_file
|
|
||||||
);
|
|
||||||
|
|
||||||
BuildCredentialsFile();
|
|
||||||
std::string execution_result = Process::execute(execute_command);
|
|
||||||
if (!execution_result.empty() && IsDumpOutputToConsole()) {
|
|
||||||
std::cout << execution_result;
|
std::cout << execution_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsDumpOutputToConsole()) {
|
|
||||||
LogSys.LoadLogSettingsDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pipe_file.empty()) {
|
|
||||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
|
||||||
auto r = File::GetContents(file);
|
|
||||||
if (!r.error.empty()) {
|
|
||||||
LogError("{}", r.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &line: Strings::Split(r.contents, "\n")) {
|
|
||||||
if (Strings::Contains(line, "mysqldump:")) {
|
|
||||||
LogError("{}", line);
|
|
||||||
LogError("Database dump failed. Correct the error before continuing or trying again");
|
|
||||||
LogError("This is to prevent data loss on behalf of the server operator");
|
|
||||||
RemoveSqlBackup();
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tables_to_dump.empty()) {
|
if (!tables_to_dump.empty()) {
|
||||||
LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump));
|
LogInfo("Dumping Tables [{}]", tables_to_dump);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
|
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
|
||||||
|
|
||||||
if (IsDumpWithCompression() && !IsDumpOutputToConsole()) {
|
if (IsDumpWithCompression() && !IsDumpOutputToConsole()) {
|
||||||
if (HasCompressionBinary()) {
|
if (HasCompressionBinary()) {
|
||||||
LogInfo("Compression requested. Compressing dump [{}.sql]", GetDumpFileNameWithPath());
|
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
|
||||||
|
|
||||||
if (IsTarAvailable()) {
|
if (IsTarAvailable()) {
|
||||||
Process::execute(
|
execute(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"tar -zcvf {}.tar.gz -C {} {}.sql",
|
"tar -zcvf {}.tar.gz -C {} {}.sql",
|
||||||
GetDumpFileNameWithPath(),
|
GetDumpFileNameWithPath(),
|
||||||
@@ -370,10 +425,9 @@ void DatabaseDumpService::DatabaseDump()
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
|
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
|
||||||
RemoveSqlBackup();
|
|
||||||
}
|
}
|
||||||
else if (Is7ZipAvailable()) {
|
else if (Is7ZipAvailable()) {
|
||||||
Process::execute(
|
execute(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"7z a -t7z {}.zip {}.sql",
|
"7z a -t7z {}.zip {}.sql",
|
||||||
GetDumpFileNameWithPath(),
|
GetDumpFileNameWithPath(),
|
||||||
@@ -381,7 +435,6 @@ void DatabaseDumpService::DatabaseDump()
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
|
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
|
||||||
RemoveSqlBackup();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogInfo("Compression requested, but no available compression binary was found");
|
LogInfo("Compression requested, but no available compression binary was found");
|
||||||
@@ -392,8 +445,6 @@ void DatabaseDumpService::DatabaseDump()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveCredentialsFile();
|
|
||||||
|
|
||||||
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
|
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
|
||||||
// LogDebug("[{}] dump-path", GetSetDumpPath());
|
// LogDebug("[{}] dump-path", GetSetDumpPath());
|
||||||
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
|
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
|
||||||
@@ -556,68 +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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseDumpService::RemoveSqlBackup()
|
|
||||||
{
|
|
||||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
|
||||||
if (File::Exists(file)) {
|
|
||||||
std::filesystem::remove(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveCredentialsFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseDumpService::BuildCredentialsFile()
|
|
||||||
{
|
|
||||||
auto config = EQEmuConfig::get();
|
|
||||||
std::ofstream out(CREDENTIALS_FILE);
|
|
||||||
if (out.is_open()) {
|
|
||||||
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
|
|
||||||
out << "[mysqldump]" << std::endl;
|
|
||||||
out << "user=" << config->ContentDbUsername << std::endl;
|
|
||||||
out << "password=" << config->ContentDbPassword << std::endl;
|
|
||||||
out << "host=" << config->ContentDbHost << std::endl;
|
|
||||||
out << "port=" << config->ContentDbPort << std::endl;
|
|
||||||
out << "default-character-set=utf8" << std::endl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out << "[mysqldump]" << std::endl;
|
|
||||||
out << "user=" << config->DatabaseUsername << std::endl;
|
|
||||||
out << "password=" << config->DatabasePassword << std::endl;
|
|
||||||
out << "host=" << config->DatabaseHost << std::endl;
|
|
||||||
out << "port=" << config->DatabasePort << std::endl;
|
|
||||||
out << "default-character-set=utf8" << std::endl;
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogError("Failed to open credentials file for writing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseDumpService::RemoveCredentialsFile()
|
|
||||||
{
|
|
||||||
if (File::Exists(CREDENTIALS_FILE)) {
|
|
||||||
std::filesystem::remove(CREDENTIALS_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DatabaseDumpService::IsDumpStaticInstanceData()
|
|
||||||
{
|
|
||||||
return dump_static_instance_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseDumpService::SetDumpStaticInstanceData(bool b)
|
|
||||||
{
|
|
||||||
dump_static_instance_data = b;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
class DatabaseDumpService {
|
class DatabaseDumpService {
|
||||||
public:
|
public:
|
||||||
void DatabaseDump();
|
void Dump();
|
||||||
bool IsDumpAllTables() const;
|
bool IsDumpAllTables() const;
|
||||||
void SetDumpAllTables(bool dump_all_tables);
|
void SetDumpAllTables(bool dump_all_tables);
|
||||||
bool IsDumpWithNoData() const;
|
bool IsDumpWithNoData() const;
|
||||||
@@ -55,11 +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);
|
|
||||||
|
|
||||||
void SetDumpStaticInstanceData(bool b);
|
|
||||||
bool IsDumpStaticInstanceData();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool dump_all_tables = false;
|
bool dump_all_tables = false;
|
||||||
@@ -75,18 +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;
|
|
||||||
bool dump_static_instance_data = false;
|
|
||||||
|
|
||||||
std::string dump_path;
|
std::string dump_path;
|
||||||
std::string dump_file_name;
|
std::string dump_file_name;
|
||||||
|
|
||||||
|
std::string execute(const std::string &cmd, bool return_result);
|
||||||
bool IsMySQLInstalled();
|
bool IsMySQLInstalled();
|
||||||
std::string GetMySQLVersion();
|
std::string GetMySQLVersion();
|
||||||
std::string GetBaseMySQLDumpCommand();
|
std::string GetBaseMySQLDumpCommand();
|
||||||
std::string GetPlayerTablesList();
|
std::string GetPlayerTablesList();
|
||||||
std::string GetBotTablesList();
|
std::string GetBotTablesList();
|
||||||
std::string GetMercTablesList();
|
|
||||||
std::string GetSystemTablesList();
|
std::string GetSystemTablesList();
|
||||||
std::string GetStateTablesList();
|
std::string GetStateTablesList();
|
||||||
std::string GetContentTablesList();
|
std::string GetContentTablesList();
|
||||||
@@ -97,9 +89,6 @@ private:
|
|||||||
std::string GetDumpFileNameWithPath();
|
std::string GetDumpFileNameWithPath();
|
||||||
std::string GetSetDumpPath();
|
std::string GetSetDumpPath();
|
||||||
std::string GetQueryServTables();
|
std::string GetQueryServTables();
|
||||||
void RemoveSqlBackup();
|
|
||||||
void BuildCredentialsFile();
|
|
||||||
void RemoveCredentialsFile();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,300 +0,0 @@
|
|||||||
#include <filesystem>
|
|
||||||
#include "database_update.h"
|
|
||||||
#include "../eqemu_logsys.h"
|
|
||||||
#include "../database.h"
|
|
||||||
#include "../strings.h"
|
|
||||||
#include "../rulesys.h"
|
|
||||||
#include "../http/httplib.h"
|
|
||||||
|
|
||||||
#include "database_update_manifest.cpp"
|
|
||||||
#include "database_update_manifest_bots.cpp"
|
|
||||||
#include "database_dump_service.h"
|
|
||||||
|
|
||||||
constexpr int BREAK_LENGTH = 70;
|
|
||||||
|
|
||||||
DatabaseVersion DatabaseUpdate::GetDatabaseVersions()
|
|
||||||
{
|
|
||||||
auto results = m_database->QueryDatabase("SELECT `version`, `bots_version` FROM `db_version` LIMIT 1");
|
|
||||||
if (!results.Success() || !results.RowCount()) {
|
|
||||||
LogError("Failed to read from [db_version] table!");
|
|
||||||
return DatabaseVersion{};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto r = results.begin();
|
|
||||||
|
|
||||||
return DatabaseVersion{
|
|
||||||
.server_database_version = Strings::ToInt(r[0]),
|
|
||||||
.bots_database_version = Strings::ToInt(r[1]),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
DatabaseVersion DatabaseUpdate::GetBinaryDatabaseVersions()
|
|
||||||
{
|
|
||||||
return DatabaseVersion{
|
|
||||||
.server_database_version = CURRENT_BINARY_DATABASE_VERSION,
|
|
||||||
.bots_database_version = (RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// the amount of versions we look-back to ensure we have all migrations
|
|
||||||
// we may not want to force these, but just warn about the look-backs
|
|
||||||
constexpr int LOOK_BACK_AMOUNT = 10;
|
|
||||||
|
|
||||||
// this check will take action
|
|
||||||
void DatabaseUpdate::CheckDbUpdates()
|
|
||||||
{
|
|
||||||
InjectBotsVersionColumn();
|
|
||||||
auto v = GetDatabaseVersions();
|
|
||||||
auto b = GetBinaryDatabaseVersions();
|
|
||||||
if (CheckVersionsUpToDate(v, b)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UpdateManifest(manifest_entries, v.server_database_version, b.server_database_version)) {
|
|
||||||
LogInfo(
|
|
||||||
"Updates ran successfully, setting database version to [{}] from [{}]",
|
|
||||||
b.server_database_version,
|
|
||||||
v.server_database_version
|
|
||||||
);
|
|
||||||
m_database->QueryDatabase(fmt::format("UPDATE `db_version` SET `version` = {}", b.server_database_version));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b.bots_database_version > 0) {
|
|
||||||
if (UpdateManifest(bot_manifest_entries, v.bots_database_version, b.bots_database_version)) {
|
|
||||||
LogInfo(
|
|
||||||
"Updates ran successfully, setting database version to [{}] from [{}]",
|
|
||||||
b.bots_database_version,
|
|
||||||
v.bots_database_version
|
|
||||||
);
|
|
||||||
m_database->QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"UPDATE `db_version` SET `bots_version` = {}",
|
|
||||||
b.bots_database_version
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string DatabaseUpdate::GetQueryResult(std::string query)
|
|
||||||
{
|
|
||||||
auto results = m_database->QueryDatabase(query);
|
|
||||||
|
|
||||||
std::vector<std::string> result_lines = {};
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
std::vector<std::string> cols;
|
|
||||||
|
|
||||||
int field_count = results.ColumnCount();
|
|
||||||
cols.reserve(field_count);
|
|
||||||
for (int i = 0; i < field_count; ++i) {
|
|
||||||
if (row[i] != nullptr) {
|
|
||||||
cols.emplace_back(row[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result_lines.emplace_back(Strings::Join(cols, " "));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Strings::Join(result_lines, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DatabaseUpdate::ShouldRunMigration(ManifestEntry &e, std::string query_result)
|
|
||||||
{
|
|
||||||
std::string r = Strings::Trim(query_result);
|
|
||||||
if (e.condition == "contains") {
|
|
||||||
return Strings::Contains(r, e.match);
|
|
||||||
}
|
|
||||||
else if (e.condition == "match") {
|
|
||||||
return r == e.match;
|
|
||||||
}
|
|
||||||
else if (e.condition == "missing") {
|
|
||||||
return !Strings::Contains(r, e.match);
|
|
||||||
}
|
|
||||||
else if (e.condition == "empty") {
|
|
||||||
return r.empty();
|
|
||||||
}
|
|
||||||
else if (e.condition == "not_empty") {
|
|
||||||
return !r.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return true if we ran updates
|
|
||||||
bool DatabaseUpdate::UpdateManifest(
|
|
||||||
std::vector<ManifestEntry> entries,
|
|
||||||
int version_low,
|
|
||||||
int version_high
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::vector<int> missing_migrations = {};
|
|
||||||
if (version_low != version_high) {
|
|
||||||
|
|
||||||
LogSys.DisableMySQLErrorLogs();
|
|
||||||
for (int version = version_low + 1; version <= version_high; ++version) {
|
|
||||||
for (auto &e: entries) {
|
|
||||||
if (e.version == version) {
|
|
||||||
bool has_migration = true;
|
|
||||||
std::string r = GetQueryResult(e.check);
|
|
||||||
if (ShouldRunMigration(e, r)) {
|
|
||||||
has_migration = false;
|
|
||||||
missing_migrations.emplace_back(e.version);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string prefix = fmt::format(
|
|
||||||
"[{}]",
|
|
||||||
has_migration ? "ok" : "missing"
|
|
||||||
);
|
|
||||||
|
|
||||||
LogInfo(
|
|
||||||
"[{}] {:>10} | [{}]",
|
|
||||||
e.version,
|
|
||||||
prefix,
|
|
||||||
e.description
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogSys.EnableMySQLErrorLogs();
|
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
|
||||||
|
|
||||||
if (!missing_migrations.empty()) {
|
|
||||||
LogInfo("Automatically backing up database before applying updates");
|
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
|
||||||
auto s = DatabaseDumpService();
|
|
||||||
s.SetDumpAllTables(true);
|
|
||||||
s.SetDumpWithCompression(true);
|
|
||||||
s.DatabaseDump();
|
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!missing_migrations.empty()) {
|
|
||||||
LogInfo("Running database migrations. Please wait...");
|
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &m: missing_migrations) {
|
|
||||||
for (auto &e: entries) {
|
|
||||||
if (e.version == m) {
|
|
||||||
bool errored_migration = false;
|
|
||||||
|
|
||||||
auto r = m_database->QueryDatabaseMulti(e.sql);
|
|
||||||
|
|
||||||
// ignore empty query result "errors"
|
|
||||||
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
|
|
||||||
LogError("(#{}) [{}]", r.ErrorNumber(), r.ErrorMessage());
|
|
||||||
errored_migration = true;
|
|
||||||
|
|
||||||
LogInfo("Required database update failed. This could be a problem");
|
|
||||||
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
|
|
||||||
|
|
||||||
// user input
|
|
||||||
std::string input;
|
|
||||||
bool gave_input = false;
|
|
||||||
time_t start_time = time(nullptr);
|
|
||||||
time_t wait_time_seconds = 60;
|
|
||||||
|
|
||||||
// spawn a concurrent thread that waits for input from std::cin
|
|
||||||
std::thread t1(
|
|
||||||
[&]() {
|
|
||||||
std::cin >> input;
|
|
||||||
gave_input = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
t1.detach();
|
|
||||||
|
|
||||||
// check the inputReceived flag once every 50ms for 10 seconds
|
|
||||||
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
||||||
}
|
|
||||||
|
|
||||||
// prompt for user skip
|
|
||||||
if (Strings::Trim(input) == "y") {
|
|
||||||
errored_migration = false;
|
|
||||||
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo(
|
|
||||||
"[{}] [{}] [{}]",
|
|
||||||
e.version,
|
|
||||||
e.description,
|
|
||||||
(errored_migration ? "error" : "ok")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (errored_migration) {
|
|
||||||
LogError("Fatal | Database migration [{}] failed to run", e.description);
|
|
||||||
LogError("Fatal | Shutting down");
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DatabaseUpdate *DatabaseUpdate::SetDatabase(Database *db)
|
|
||||||
{
|
|
||||||
m_database = db;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
|
||||||
{
|
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
|
||||||
|
|
||||||
LogInfo(
|
|
||||||
"{:>8} | database [{}] binary [{}] {}",
|
|
||||||
"Server",
|
|
||||||
v.server_database_version,
|
|
||||||
b.server_database_version,
|
|
||||||
(v.server_database_version == b.server_database_version) ? "up to date" : "checking updates"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (RuleB(Bots, Enabled) && b.bots_database_version > 0) {
|
|
||||||
LogInfo(
|
|
||||||
"{:>8} | database [{}] binary [{}] {}",
|
|
||||||
"Bots",
|
|
||||||
v.bots_database_version,
|
|
||||||
b.bots_database_version,
|
|
||||||
(v.bots_database_version == b.bots_database_version) ? "up to date" : "checking updates"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("{:>8} | [server.auto_database_updates] [<green>true]", "Config");
|
|
||||||
|
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
|
||||||
|
|
||||||
// server database version is required
|
|
||||||
bool server_up_to_date = v.server_database_version == b.server_database_version;
|
|
||||||
// bots database version is optional, if not enabled then it is always up-to-date
|
|
||||||
bool bots_up_to_date = RuleB(Bots, Enabled) ? v.bots_database_version == b.bots_database_version : true;
|
|
||||||
|
|
||||||
return server_up_to_date && bots_up_to_date;
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks to see if there are pending updates
|
|
||||||
// used by zone to prevent launch or boot loop until updates are applied
|
|
||||||
bool DatabaseUpdate::HasPendingUpdates()
|
|
||||||
{
|
|
||||||
auto v = GetDatabaseVersions();
|
|
||||||
auto b = GetBinaryDatabaseVersions();
|
|
||||||
|
|
||||||
return !CheckVersionsUpToDate(v, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseUpdate::InjectBotsVersionColumn()
|
|
||||||
{
|
|
||||||
auto r = m_database->QueryDatabase("show columns from db_version where Field like '%bots_version%'");
|
|
||||||
if (r.RowCount() == 0) {
|
|
||||||
m_database->QueryDatabase("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#ifndef EQEMU_DATABASE_UPDATE_H
|
|
||||||
#define EQEMU_DATABASE_UPDATE_H
|
|
||||||
|
|
||||||
#include "../database.h"
|
|
||||||
|
|
||||||
struct ManifestEntry {
|
|
||||||
int version{}; // database version of the migration
|
|
||||||
std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
|
|
||||||
std::string check{}; // query that checks against the condition
|
|
||||||
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
|
||||||
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
|
||||||
std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DatabaseVersion {
|
|
||||||
int server_database_version;
|
|
||||||
int bots_database_version;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DatabaseUpdate {
|
|
||||||
public:
|
|
||||||
DatabaseVersion GetDatabaseVersions();
|
|
||||||
DatabaseVersion GetBinaryDatabaseVersions();
|
|
||||||
void CheckDbUpdates();
|
|
||||||
std::string GetQueryResult(std::string query);
|
|
||||||
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
|
|
||||||
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
|
|
||||||
|
|
||||||
DatabaseUpdate *SetDatabase(Database *db);
|
|
||||||
bool HasPendingUpdates();
|
|
||||||
private:
|
|
||||||
Database *m_database;
|
|
||||||
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
|
||||||
void InjectBotsVersionColumn();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //EQEMU_DATABASE_UPDATE_H
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,107 +0,0 @@
|
|||||||
#include "database_update.h"
|
|
||||||
|
|
||||||
std::vector<ManifestEntry> bot_manifest_entries = {
|
|
||||||
ManifestEntry{
|
|
||||||
.version = 9035,
|
|
||||||
.description = "2022_12_04_bot_archery.sql",
|
|
||||||
.check = "SHOW COLUMNS FROM `bot_data` LIKE 'archery_setting'",
|
|
||||||
.condition = "empty",
|
|
||||||
.match = "",
|
|
||||||
.sql = R"(
|
|
||||||
ALTER TABLE `bot_data`
|
|
||||||
ADD COLUMN `archery_setting` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `enforce_spell_settings`;
|
|
||||||
)",
|
|
||||||
},
|
|
||||||
ManifestEntry{
|
|
||||||
.version = 9036,
|
|
||||||
.description = "2023_01_19_drop_bot_views.sql",
|
|
||||||
.check = "SHOW TABLES LIKE 'vw_groups'",
|
|
||||||
.condition = "not_empty",
|
|
||||||
.match = "",
|
|
||||||
.sql = R"(
|
|
||||||
DROP VIEW vw_bot_groups;
|
|
||||||
DROP VIEW vw_bot_character_mobs;
|
|
||||||
DROP VIEW vw_groups;
|
|
||||||
DROP VIEW vw_guild_members;
|
|
||||||
DROP TABLE bot_guild_members;
|
|
||||||
|
|
||||||
)",
|
|
||||||
},
|
|
||||||
ManifestEntry{
|
|
||||||
.version = 9037,
|
|
||||||
.description = "2023_01_22_add_name_index.sql",
|
|
||||||
.check = "show index from bot_data WHERE key_name = 'name`",
|
|
||||||
.condition = "",
|
|
||||||
.match = "empty",
|
|
||||||
.sql = R"(
|
|
||||||
create index `name` on bot_data(`name`);
|
|
||||||
)",
|
|
||||||
},
|
|
||||||
ManifestEntry{
|
|
||||||
.version = 9038,
|
|
||||||
.description = "2023_02_16_add_caster_range.sql",
|
|
||||||
.check = "SHOW COLUMNS FROM `bot_data` LIKE 'caster_range'",
|
|
||||||
.condition = "",
|
|
||||||
.match = "empty",
|
|
||||||
.sql = R"(
|
|
||||||
ALTER TABLE `bot_data`
|
|
||||||
ADD COLUMN `caster_range` INT(11) UNSIGNED NOT NULL DEFAULT '300' AFTER `archery_setting`;
|
|
||||||
)",
|
|
||||||
},
|
|
||||||
ManifestEntry{
|
|
||||||
.version = 9039,
|
|
||||||
.description = "2023_03_31_remove_bot_groups.sql",
|
|
||||||
.check = "SHOW TABLES LIKE 'bot_groups'",
|
|
||||||
.condition = "",
|
|
||||||
.match = "not_empty",
|
|
||||||
.sql = R"(
|
|
||||||
SET FOREIGN_KEY_CHECKS = 0;
|
|
||||||
DROP TABLE IF EXISTS `bot_groups`;
|
|
||||||
DROP TABLE IF EXISTS `bot_group_members`;
|
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
|
||||||
)",
|
|
||||||
},
|
|
||||||
ManifestEntry{
|
|
||||||
.version = 9040,
|
|
||||||
.description = "2023_11_16_bot_starting_items.sql",
|
|
||||||
.check = "SHOW TABLES LIKE 'bot_starting_items'",
|
|
||||||
.condition = "empty",
|
|
||||||
.match = "",
|
|
||||||
.sql = R"(
|
|
||||||
CREATE TABLE `bot_starting_items` (
|
|
||||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`races` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
`classes` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
|
|
||||||
`min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
`slot_id` mediumint(9) NOT NULL DEFAULT -1,
|
|
||||||
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
|
||||||
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
|
||||||
`content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
|
||||||
`content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci;
|
|
||||||
)"
|
|
||||||
}
|
|
||||||
// -- template; copy/paste this when you need to create a new entry
|
|
||||||
// ManifestEntry{
|
|
||||||
// .version = 9228,
|
|
||||||
// .description = "some_new_migration.sql",
|
|
||||||
// .check = "SHOW COLUMNS FROM `table_name` LIKE 'column_name'",
|
|
||||||
// .condition = "empty",
|
|
||||||
// .match = "",
|
|
||||||
// .sql = R"(
|
|
||||||
//
|
|
||||||
//)"
|
|
||||||
};
|
|
||||||
|
|
||||||
// see struct definitions for what each field does
|
|
||||||
// struct ManifestEntry {
|
|
||||||
// int version{}; // database version of the migration
|
|
||||||
// std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
|
|
||||||
// std::string check{}; // query that checks against the condition
|
|
||||||
// std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
|
||||||
// std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
|
||||||
// std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
|
||||||
// };
|
|
||||||
+1795
-13
File diff suppressed because it is too large
Load Diff
+366
-336
@@ -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,241 +41,251 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id)
|
/**
|
||||||
|
* @param instance_id
|
||||||
|
* @param char_id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
|
||||||
{
|
{
|
||||||
auto e = InstanceListPlayerRepository::NewEntity();
|
std::string query = StringFormat(
|
||||||
|
"REPLACE INTO `instance_list_player` (id, charid) "
|
||||||
|
"VALUES "
|
||||||
|
"(%lu, %lu)",
|
||||||
|
(unsigned long) instance_id,
|
||||||
|
(unsigned long) char_id
|
||||||
|
);
|
||||||
|
|
||||||
e.id = instance_id;
|
auto results = QueryDatabase(query);
|
||||||
e.charid = character_id;
|
|
||||||
|
|
||||||
return InstanceListPlayerRepository::ReplaceOne(*this, e);
|
return results.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id)
|
bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id)
|
||||||
{
|
{
|
||||||
if (!instance_id) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto l = InstanceListPlayerRepository::GetWhere(
|
std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id);
|
||||||
*this,
|
auto results = QueryDatabase(query);
|
||||||
fmt::format(
|
|
||||||
"id = {} AND charid = {}",
|
if (!results.Success())
|
||||||
instance_id,
|
return false;
|
||||||
character_id
|
|
||||||
)
|
if (results.RowCount() != 1)
|
||||||
);
|
|
||||||
if (l.empty()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::CheckInstanceExists(uint16 instance_id)
|
bool Database::CheckInstanceExists(uint16 instance_id) {
|
||||||
{
|
std::string query = StringFormat(
|
||||||
if (!instance_id) {
|
"SELECT "
|
||||||
return false;
|
"`id` "
|
||||||
}
|
"FROM "
|
||||||
|
"`instance_list` "
|
||||||
|
"WHERE "
|
||||||
|
"`id` = %u",
|
||||||
|
instance_id
|
||||||
|
);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
if (!results.Success())
|
||||||
if (!i.id) {
|
return false;
|
||||||
|
|
||||||
|
if (results.RowCount() == 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::CheckInstanceExpired(uint16 instance_id)
|
bool Database::CheckInstanceExpired(uint16 instance_id)
|
||||||
{
|
{
|
||||||
if (!instance_id) {
|
|
||||||
|
int32 start_time = 0;
|
||||||
|
int32 duration = 0;
|
||||||
|
uint32 never_expires = 0;
|
||||||
|
|
||||||
|
std::string query = StringFormat(
|
||||||
|
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
|
||||||
|
instance_id
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
if (results.RowCount() == 0) {
|
||||||
if (!i.id) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.never_expires) {
|
auto row = results.begin();
|
||||||
|
|
||||||
|
start_time = atoi(row[0]);
|
||||||
|
duration = atoi(row[1]);
|
||||||
|
never_expires = atoi(row[2]);
|
||||||
|
|
||||||
|
if (never_expires == 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeval tv{};
|
timeval tv{};
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
|
|
||||||
return (i.start_time + i.duration) <= tv.tv_sec;
|
return (start_time + duration) <= tv.tv_sec;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
|
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
|
||||||
{
|
{
|
||||||
auto e = InstanceListRepository::NewEntity();
|
std::string query = StringFormat(
|
||||||
|
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
|
||||||
|
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
|
||||||
|
instance_id,
|
||||||
|
zone_id,
|
||||||
|
version,
|
||||||
|
duration
|
||||||
|
);
|
||||||
|
|
||||||
e.id = instance_id;
|
auto results = QueryDatabase(query);
|
||||||
e.zone = zone_id;
|
|
||||||
e.version = version;
|
|
||||||
e.start_time = std::time(nullptr);
|
|
||||||
e.duration = duration;
|
|
||||||
|
|
||||||
return InstanceListRepository::InsertOne(*this, e).id;
|
return results.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
||||||
{
|
{
|
||||||
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
|
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
|
||||||
uint32 max_instance_id = 32000;
|
uint32 max = 32000;
|
||||||
|
|
||||||
// sanity check reserved
|
std::string query = StringFormat(
|
||||||
if (max_reserved_instance_id >= max_instance_id) {
|
"SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
|
||||||
instance_id = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// recycle instances
|
|
||||||
if (RuleB(Instances, RecycleInstanceIds)) {
|
|
||||||
|
|
||||||
//query to get first unused id above reserved
|
|
||||||
auto query = fmt::format(
|
|
||||||
SQL(
|
|
||||||
SELECT id
|
|
||||||
FROM instance_list
|
|
||||||
WHERE id = {};
|
|
||||||
),
|
|
||||||
max_reserved_instance_id + 1
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
// could not successfully query - bail out
|
|
||||||
if (!results.Success()) {
|
|
||||||
instance_id = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first id is available
|
|
||||||
if (results.RowCount() == 0) {
|
|
||||||
instance_id = max_reserved_instance_id + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now look for next available above reserved
|
|
||||||
query = fmt::format(
|
|
||||||
SQL(
|
|
||||||
SELECT MIN(i.id + 1) AS next_available
|
|
||||||
FROM instance_list i
|
|
||||||
LEFT JOIN instance_list i2 ON i.id + 1 = i2.id
|
|
||||||
WHERE i.id >= {}
|
|
||||||
AND i2.id IS NULL;
|
|
||||||
),
|
|
||||||
max_reserved_instance_id
|
|
||||||
);
|
|
||||||
|
|
||||||
results = QueryDatabase(query);
|
|
||||||
|
|
||||||
// could not successfully query - bail out
|
|
||||||
if (!results.Success()) {
|
|
||||||
instance_id = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// did not retrieve any rows - bail out
|
|
||||||
if (results.RowCount() == 0) {
|
|
||||||
instance_id = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
|
|
||||||
// check that id is within limits
|
|
||||||
if (row[0] && Strings::ToInt(row[0]) <= max_instance_id) {
|
|
||||||
instance_id = Strings::ToInt(row[0]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no available instance ids
|
|
||||||
instance_id = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get max unused id above reserved
|
|
||||||
auto query = fmt::format(
|
|
||||||
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}",
|
|
||||||
max_reserved_instance_id,
|
max_reserved_instance_id,
|
||||||
max_reserved_instance_id
|
max_reserved_instance_id
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (RuleB(Instances, RecycleInstanceIds)) {
|
||||||
|
query = (
|
||||||
|
SQL(
|
||||||
|
SELECT i.id + 1 AS next_available
|
||||||
|
FROM instance_list i
|
||||||
|
LEFT JOIN instance_list i2 ON i2.id = i.id + 1
|
||||||
|
WHERE i2.id IS NULL
|
||||||
|
ORDER BY i.id
|
||||||
|
LIMIT 0, 1;
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
// could not successfully query - bail out
|
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
instance_id = 0;
|
instance_id = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// did not retrieve any rows - bail out
|
if (results.RowCount() == 0) {
|
||||||
|
instance_id = max_reserved_instance_id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
if (atoi(row[0]) <= max) {
|
||||||
|
instance_id = atoi(row[0]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance_id < max_reserved_instance_id) {
|
||||||
|
instance_id = max_reserved_instance_id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id);
|
||||||
|
results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success()) {
|
||||||
|
instance_id = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0) {
|
if (results.RowCount() == 0) {
|
||||||
instance_id = 0;
|
instance_id = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto row = results.begin();
|
max_reserved_instance_id++;
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
if (max_reserved_instance_id < atoi(row[0])) {
|
||||||
|
instance_id = max_reserved_instance_id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// no instances currently used
|
if (max_reserved_instance_id > max) {
|
||||||
if (!row[0]) {
|
instance_id = 0;
|
||||||
instance_id = max_reserved_instance_id + 1;
|
return false;
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
max_reserved_instance_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that id is within limits
|
instance_id = max_reserved_instance_id;
|
||||||
if (Strings::ToInt(row[0]) <= max_instance_id) {
|
|
||||||
instance_id = Strings::ToInt(row[0]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no available instance ids
|
return true;
|
||||||
instance_id = 0;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -293,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;
|
||||||
|
|
||||||
|
std::string query = StringFormat(
|
||||||
|
"SELECT "
|
||||||
|
"instance_list.id "
|
||||||
|
"FROM "
|
||||||
|
"instance_list, "
|
||||||
|
"instance_list_player "
|
||||||
|
"WHERE "
|
||||||
|
"instance_list.zone = %u "
|
||||||
|
"AND instance_list.version = %u "
|
||||||
|
"AND instance_list.id = instance_list_player.id "
|
||||||
|
"AND instance_list_player.charid = %u "
|
||||||
|
"LIMIT 1; ",
|
||||||
|
zone,
|
||||||
|
version,
|
||||||
|
character_id
|
||||||
|
);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (results.RowCount() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
return atoi(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 Database::GetInstanceVersion(uint16 instance_id) {
|
||||||
|
if (instance_id == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (results.RowCount() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
return atoi(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
|
||||||
|
{
|
||||||
|
uint32 start_time = 0;
|
||||||
|
uint32 duration = 0;
|
||||||
|
uint32 never_expires = 0;
|
||||||
|
|
||||||
|
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success())
|
||||||
|
{
|
||||||
|
is_perma = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto query = fmt::format(
|
if (results.RowCount() == 0)
|
||||||
"SELECT instance_list.id FROM "
|
{
|
||||||
"instance_list, instance_list_player WHERE "
|
is_perma = false;
|
||||||
"instance_list.zone = {} AND "
|
|
||||||
"instance_list.version = {} AND "
|
|
||||||
"instance_list.id = instance_list_player.id AND "
|
|
||||||
"instance_list_player.charid = {} "
|
|
||||||
"LIMIT 1;",
|
|
||||||
zone_id,
|
|
||||||
version,
|
|
||||||
character_id
|
|
||||||
);
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
if (!results.Success() || !results.RowCount()) {
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -397,173 +396,204 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
|
|||||||
|
|
||||||
timeval tv;
|
timeval tv;
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
return ((i.start_time + i.duration) - tv.tv_sec);
|
return ((start_time + duration) - tv.tv_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Database::GetInstanceZoneID(uint16 instance_id)
|
uint32 Database::VersionFromInstanceID(uint16 instance_id)
|
||||||
{
|
{
|
||||||
if (!instance_id) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
|
||||||
if (!i.id) {
|
auto results = QueryDatabase(query);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i.zone;
|
if (!results.Success())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (results.RowCount() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
return atoi(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Database::ZoneIDFromInstanceID(uint16 instance_id)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (results.RowCount() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
return atoi(row[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
|
void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
|
||||||
{
|
{
|
||||||
auto zone_id = GetInstanceZoneID(instance_id);
|
|
||||||
auto version = GetInstanceVersion(instance_id);
|
|
||||||
|
|
||||||
auto l = GroupIdRepository::GetWhere(
|
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
|
||||||
*this,
|
uint16 version = VersionFromInstanceID(instance_id);
|
||||||
fmt::format(
|
|
||||||
"groupid = {}",
|
std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id);
|
||||||
group_id
|
auto results = QueryDatabase(query);
|
||||||
)
|
|
||||||
);
|
if (!results.Success())
|
||||||
if (l.empty()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& e : l) {
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
if (!GetInstanceID(zone_id, e.charid, version)) {
|
{
|
||||||
AddClientToInstance(instance_id, e.charid);
|
uint32 charid = atoi(row[0]);
|
||||||
}
|
if (GetInstanceID(zone_id, charid, version) == 0)
|
||||||
|
AddClientToInstance(instance_id, charid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
|
void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
|
||||||
{
|
{
|
||||||
auto zone_id = GetInstanceZoneID(instance_id);
|
|
||||||
auto version = GetInstanceVersion(instance_id);
|
|
||||||
|
|
||||||
auto l = RaidMembersRepository::GetWhere(
|
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
|
||||||
*this,
|
uint16 version = VersionFromInstanceID(instance_id);
|
||||||
|
|
||||||
|
std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
uint32 charid = atoi(row[0]);
|
||||||
|
if (GetInstanceID(zone_id, charid, version) == 0)
|
||||||
|
AddClientToInstance(instance_id, charid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::BuryCorpsesInInstance(uint16 instance_id) {
|
||||||
|
QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"raidid = {}",
|
"UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id = {}",
|
||||||
raid_id
|
instance_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (l.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& e : l) {
|
|
||||||
if (!GetInstanceID(zone_id, e.charid, version)) {
|
|
||||||
AddClientToInstance(instance_id, e.charid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::DeleteInstance(uint16 instance_id)
|
void Database::DeleteInstance(uint16 instance_id)
|
||||||
{
|
{
|
||||||
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id));
|
std::string query;
|
||||||
|
|
||||||
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id);
|
||||||
|
QueryDatabase(query);
|
||||||
|
|
||||||
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id);
|
||||||
|
QueryDatabase(query);
|
||||||
|
|
||||||
|
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
|
||||||
|
QueryDatabase(query);
|
||||||
|
|
||||||
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
|
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
|
||||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||||
|
|
||||||
CharacterCorpsesRepository::BuryInstance(*this, instance_id);
|
BuryCorpsesInInstance(instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id)
|
void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid)
|
||||||
{
|
{
|
||||||
auto instance_id = GetInstanceID(zone_id, character_id, version);
|
uint16 id = GetInstanceID(zone, charid, version);
|
||||||
if (instance_id) {
|
if (id != 0)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
char ln[128];
|
char ln[128];
|
||||||
memset(ln, 0, 128);
|
memset(ln, 0, 128);
|
||||||
GetGroupLeadershipInfo(group_id, ln);
|
GetGroupLeadershipInfo(gid, ln);
|
||||||
|
uint32 l_charid = GetCharacterID((const char*)ln);
|
||||||
|
uint16 l_id = GetInstanceID(zone, l_charid, version);
|
||||||
|
|
||||||
auto group_leader_id = GetCharacterID((const char*)ln);
|
if (l_id == 0)
|
||||||
auto group_leader_instance_id = GetInstanceID(zone_id, group_leader_id, version);
|
|
||||||
|
|
||||||
if (!group_leader_instance_id) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
AddClientToInstance(group_leader_instance_id, character_id);
|
AddClientToInstance(l_id, charid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id)
|
void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid)
|
||||||
{
|
{
|
||||||
uint16 instance_id = GetInstanceID(zone_id, character_id, version);
|
uint16 id = GetInstanceID(zone, charid, version);
|
||||||
if (instance_id) {
|
if (id != 0)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id));
|
uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid));
|
||||||
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
|
uint16 l_id = GetInstanceID(zone, l_charid, version);
|
||||||
|
|
||||||
if (!raid_leader_instance_id) {
|
if (l_id == 0)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
AddClientToInstance(raid_leader_instance_id, character_id);
|
AddClientToInstance(l_id, charid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids)
|
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list) {
|
||||||
{
|
|
||||||
auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id));
|
|
||||||
if (l.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& e : l) {
|
std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id);
|
||||||
character_ids.push_back(e.charid);
|
auto results = QueryDatabase(query);
|
||||||
}
|
|
||||||
|
if (!results.Success())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
charid_list.push_back(atoi(row[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::PurgeExpiredInstances()
|
void Database::PurgeExpiredInstances()
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delay purging by a day so that we can continue using adjacent free instance id's
|
* Delay purging by a day so that we can continue using adjacent free instance id's
|
||||||
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but
|
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but
|
||||||
* has not been fully de-allocated
|
* has not been fully de-allocated
|
||||||
*/
|
*/
|
||||||
auto l = InstanceListRepository::GetWhere(
|
std::string query =
|
||||||
*this,
|
SQL(
|
||||||
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0"
|
SELECT
|
||||||
);
|
id
|
||||||
if (l.empty()) {
|
FROM
|
||||||
|
instance_list
|
||||||
|
where
|
||||||
|
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
|
||||||
|
and never_expires = 0
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.RowCount() == 0) {
|
||||||
return;
|
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-35
@@ -66,10 +66,9 @@ namespace DatabaseSchema {
|
|||||||
{"character_potionbelt", "id"},
|
{"character_potionbelt", "id"},
|
||||||
{"character_skills", "id"},
|
{"character_skills", "id"},
|
||||||
{"character_spells", "id"},
|
{"character_spells", "id"},
|
||||||
{"character_stats_record", "character_id"},
|
|
||||||
{"character_task_timers", "character_id"},
|
{"character_task_timers", "character_id"},
|
||||||
{"character_tasks", "charid"},
|
{"character_tasks", "charid"},
|
||||||
{"character_tribute", "character_id"},
|
{"character_tribute", "id"},
|
||||||
{"completed_tasks", "charid"},
|
{"completed_tasks", "charid"},
|
||||||
{"data_buckets", "id"},
|
{"data_buckets", "id"},
|
||||||
{"faction_values", "char_id"},
|
{"faction_values", "char_id"},
|
||||||
@@ -135,7 +134,6 @@ namespace DatabaseSchema {
|
|||||||
"character_potionbelt",
|
"character_potionbelt",
|
||||||
"character_skills",
|
"character_skills",
|
||||||
"character_spells",
|
"character_spells",
|
||||||
"character_stats_record",
|
|
||||||
"character_task_timers",
|
"character_task_timers",
|
||||||
"character_tasks",
|
"character_tasks",
|
||||||
"character_tribute",
|
"character_tribute",
|
||||||
@@ -191,14 +189,13 @@ namespace DatabaseSchema {
|
|||||||
"char_create_point_allocations",
|
"char_create_point_allocations",
|
||||||
"damageshieldtypes",
|
"damageshieldtypes",
|
||||||
"doors",
|
"doors",
|
||||||
"dynamic_zone_templates",
|
|
||||||
"faction_association",
|
|
||||||
"faction_base_data",
|
"faction_base_data",
|
||||||
"faction_list",
|
"faction_list",
|
||||||
"faction_list_mod",
|
"faction_list_mod",
|
||||||
"fishing",
|
"fishing",
|
||||||
"forage",
|
"forage",
|
||||||
"global_loot",
|
"global_loot",
|
||||||
|
"goallists",
|
||||||
"graveyard",
|
"graveyard",
|
||||||
"grid",
|
"grid",
|
||||||
"grid_entries",
|
"grid_entries",
|
||||||
@@ -227,6 +224,7 @@ namespace DatabaseSchema {
|
|||||||
"pets_beastlord_data",
|
"pets_beastlord_data",
|
||||||
"pets_equipmentset",
|
"pets_equipmentset",
|
||||||
"pets_equipmentset_entries",
|
"pets_equipmentset_entries",
|
||||||
|
"proximities",
|
||||||
"skill_caps",
|
"skill_caps",
|
||||||
"spawn2",
|
"spawn2",
|
||||||
"spawn_conditions",
|
"spawn_conditions",
|
||||||
@@ -258,9 +256,7 @@ namespace DatabaseSchema {
|
|||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"chatchannels",
|
"chatchannels",
|
||||||
"chatchannel_reserved_names",
|
|
||||||
"command_settings",
|
"command_settings",
|
||||||
"command_subsettings",
|
|
||||||
"content_flags",
|
"content_flags",
|
||||||
"db_str",
|
"db_str",
|
||||||
"eqtime",
|
"eqtime",
|
||||||
@@ -322,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",
|
||||||
@@ -345,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",
|
||||||
@@ -396,6 +389,9 @@ namespace DatabaseSchema {
|
|||||||
"bot_command_settings",
|
"bot_command_settings",
|
||||||
"bot_create_combinations",
|
"bot_create_combinations",
|
||||||
"bot_data",
|
"bot_data",
|
||||||
|
"bot_group_members",
|
||||||
|
"bot_groups",
|
||||||
|
"bot_guild_members",
|
||||||
"bot_heal_rotation_members",
|
"bot_heal_rotation_members",
|
||||||
"bot_heal_rotation_targets",
|
"bot_heal_rotation_targets",
|
||||||
"bot_heal_rotations",
|
"bot_heal_rotations",
|
||||||
@@ -406,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"
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+52
-190
@@ -13,7 +13,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mysqld_error.h>
|
#include <mysqld_error.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "strings.h"
|
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@@ -35,16 +34,14 @@
|
|||||||
|
|
||||||
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;
|
pDatabase = nullptr;
|
||||||
pDatabase = nullptr;
|
pCompress = false;
|
||||||
pCompress = false;
|
pSSL = false;
|
||||||
pSSL = false;
|
pStatus = Closed;
|
||||||
pStatus = Closed;
|
|
||||||
m_mutex = new Mutex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBcore::~DBcore()
|
DBcore::~DBcore()
|
||||||
@@ -54,10 +51,16 @@ DBcore::~DBcore()
|
|||||||
* are re-using the default database connection pointer when we dont have an
|
* are re-using the default database connection pointer when we dont have an
|
||||||
* external configuration setup ex: (content_database)
|
* external configuration setup ex: (content_database)
|
||||||
*/
|
*/
|
||||||
if (mysqlOwner) {
|
std::string mysql_connection_host;
|
||||||
mysql_close(mysql);
|
if (mysql.host) {
|
||||||
|
mysql_connection_host = mysql.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GetOriginHost() != mysql_connection_host) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_close(&mysql);
|
||||||
safe_delete_array(pHost);
|
safe_delete_array(pHost);
|
||||||
safe_delete_array(pUser);
|
safe_delete_array(pUser);
|
||||||
safe_delete_array(pPassword);
|
safe_delete_array(pPassword);
|
||||||
@@ -67,21 +70,20 @@ DBcore::~DBcore()
|
|||||||
// Sends the MySQL server a keepalive
|
// Sends the MySQL server a keepalive
|
||||||
void DBcore::ping()
|
void DBcore::ping()
|
||||||
{
|
{
|
||||||
if (!m_mutex->trylock()) {
|
if (!MDatabase.trylock()) {
|
||||||
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
|
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mysql_ping(mysql);
|
mysql_ping(&mysql);
|
||||||
m_mutex->unlock();
|
MDatabase.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
MySQLRequestResult DBcore::QueryDatabase(const std::string& query, bool retryOnFailureOnce)
|
MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce)
|
||||||
{
|
{
|
||||||
auto r = QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DBcore::DoesTableExist(const std::string& table_name)
|
bool DBcore::DoesTableExist(std::string table_name)
|
||||||
{
|
{
|
||||||
auto results = QueryDatabase(fmt::format("SHOW TABLES LIKE '{}'", table_name));
|
auto results = QueryDatabase(fmt::format("SHOW TABLES LIKE '{}'", table_name));
|
||||||
|
|
||||||
@@ -93,16 +95,18 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
BenchTimer timer;
|
BenchTimer timer;
|
||||||
timer.reset();
|
timer.reset();
|
||||||
|
|
||||||
LockMutex lock(m_mutex);
|
LockMutex lock(&MDatabase);
|
||||||
|
|
||||||
// Reconnect if we are not connected before hand.
|
// Reconnect if we are not connected before hand.
|
||||||
if (pStatus != Connected) {
|
if (pStatus != Connected) {
|
||||||
Open();
|
Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// request query. != 0 indicates some kind of error.
|
// request query. != 0 indicates some kind of error.
|
||||||
if (mysql_real_query(mysql, query, querylen) != 0) {
|
if (mysql_real_query(&mysql, query, querylen) != 0) {
|
||||||
unsigned int errorNumber = mysql_errno(mysql);
|
unsigned int errorNumber = mysql_errno(&mysql);
|
||||||
|
|
||||||
if (errorNumber == CR_SERVER_GONE_ERROR) {
|
if (errorNumber == CR_SERVER_GONE_ERROR) {
|
||||||
pStatus = Error;
|
pStatus = Error;
|
||||||
@@ -126,26 +130,26 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
|
|
||||||
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
||||||
|
|
||||||
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql));
|
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
|
||||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(mysql), errorBuffer);
|
return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(&mysql), errorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
||||||
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql));
|
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error logging
|
* Error logging
|
||||||
*/
|
*/
|
||||||
if (mysql_errno(mysql) > 0 && query[0] != '\0') {
|
if (mysql_errno(&mysql) > 0 && strlen(query) > 0) {
|
||||||
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(mysql), mysql_error(mysql), query);
|
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(mysql), errorBuffer);
|
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// successful query. get results.
|
// successful query. get results.
|
||||||
MYSQL_RES *res = mysql_store_result(mysql);
|
MYSQL_RES *res = mysql_store_result(&mysql);
|
||||||
uint32 rowCount = 0;
|
uint32 rowCount = 0;
|
||||||
|
|
||||||
if (res != nullptr) {
|
if (res != nullptr) {
|
||||||
@@ -154,16 +158,16 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
|
|
||||||
MySQLRequestResult requestResult(
|
MySQLRequestResult requestResult(
|
||||||
res,
|
res,
|
||||||
(uint32) mysql_affected_rows(mysql),
|
(uint32) mysql_affected_rows(&mysql),
|
||||||
rowCount,
|
rowCount,
|
||||||
(uint32) mysql_field_count(mysql),
|
(uint32) mysql_field_count(&mysql),
|
||||||
(uint32) mysql_insert_id(mysql)
|
(uint32) mysql_insert_id(&mysql)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
||||||
if ((strncasecmp(query, "select", 6) == 0)) {
|
if ((strncasecmp(query, "select", 6) == 0)) {
|
||||||
LogMySQLQuery(
|
LogMySQLQuery(
|
||||||
"{0} -- ({1} row{2} returned) ({3}s)",
|
"{0}; -- ({1} row{2} returned) ({3}s)",
|
||||||
query,
|
query,
|
||||||
requestResult.RowCount(),
|
requestResult.RowCount(),
|
||||||
requestResult.RowCount() == 1 ? "" : "s",
|
requestResult.RowCount() == 1 ? "" : "s",
|
||||||
@@ -172,7 +176,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogMySQLQuery(
|
LogMySQLQuery(
|
||||||
"{0} -- ({1} row{2} affected) ({3}s)",
|
"{0}; -- ({1} row{2} affected) ({3}s)",
|
||||||
query,
|
query,
|
||||||
requestResult.RowsAffected(),
|
requestResult.RowsAffected(),
|
||||||
requestResult.RowsAffected() == 1 ? "" : "s",
|
requestResult.RowsAffected() == 1 ? "" : "s",
|
||||||
@@ -203,7 +207,7 @@ uint32 DBcore::DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen)
|
|||||||
{
|
{
|
||||||
// No good reason to lock the DB, we only need it in the first place to check char encoding.
|
// No good reason to lock the DB, we only need it in the first place to check char encoding.
|
||||||
// LockMutex lock(&MDatabase);
|
// LockMutex lock(&MDatabase);
|
||||||
return mysql_real_escape_string(mysql, tobuf, frombuf, fromlen);
|
return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DBcore::Open(
|
bool DBcore::Open(
|
||||||
@@ -218,7 +222,7 @@ bool DBcore::Open(
|
|||||||
bool iSSL
|
bool iSSL
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LockMutex lock(m_mutex);
|
LockMutex lock(&MDatabase);
|
||||||
safe_delete_array(pHost);
|
safe_delete_array(pHost);
|
||||||
safe_delete_array(pUser);
|
safe_delete_array(pUser);
|
||||||
safe_delete_array(pPassword);
|
safe_delete_array(pPassword);
|
||||||
@@ -238,13 +242,13 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
|
|||||||
if (errbuf) {
|
if (errbuf) {
|
||||||
errbuf[0] = 0;
|
errbuf[0] = 0;
|
||||||
}
|
}
|
||||||
LockMutex lock(m_mutex);
|
LockMutex lock(&MDatabase);
|
||||||
if (GetStatus() == Connected) {
|
if (GetStatus() == Connected) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (GetStatus() == Error) {
|
if (GetStatus() == Error) {
|
||||||
mysql_close(mysql);
|
mysql_close(&mysql);
|
||||||
mysql_init(mysql); // Initialize structure again
|
mysql_init(&mysql); // Initialize structure again
|
||||||
}
|
}
|
||||||
if (!pHost) {
|
if (!pHost) {
|
||||||
return false;
|
return false;
|
||||||
@@ -261,7 +265,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
|
|||||||
if (pSSL) {
|
if (pSSL) {
|
||||||
flags |= CLIENT_SSL;
|
flags |= CLIENT_SSL;
|
||||||
}
|
}
|
||||||
if (mysql_real_connect(mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
|
if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
|
||||||
pStatus = Connected;
|
pStatus = Connected;
|
||||||
|
|
||||||
std::string connected_origin_host = pHost;
|
std::string connected_origin_host = pHost;
|
||||||
@@ -271,16 +275,21 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (errnum) {
|
if (errnum) {
|
||||||
*errnum = mysql_errno(mysql);
|
*errnum = mysql_errno(&mysql);
|
||||||
}
|
}
|
||||||
if (errbuf) {
|
if (errbuf) {
|
||||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql));
|
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
}
|
}
|
||||||
pStatus = Error;
|
pStatus = Error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DBcore::SetMysql(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
DBcore::mysql = *mysql;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string &DBcore::GetOriginHost() const
|
const std::string &DBcore::GetOriginHost() const
|
||||||
{
|
{
|
||||||
return origin_host;
|
return origin_host;
|
||||||
@@ -290,150 +299,3 @@ void DBcore::SetOriginHost(const std::string &origin_host)
|
|||||||
{
|
{
|
||||||
DBcore::origin_host = origin_host;
|
DBcore::origin_host = origin_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DBcore::Escape(const std::string& s)
|
|
||||||
{
|
|
||||||
const std::size_t s_len = s.length();
|
|
||||||
std::vector<char> temp((s_len * 2) + 1, '\0');
|
|
||||||
mysql_real_escape_string(mysql, temp.data(), s.c_str(), s_len);
|
|
||||||
|
|
||||||
return temp.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBcore::SetMutex(Mutex *mutex)
|
|
||||||
{
|
|
||||||
safe_delete(m_mutex);
|
|
||||||
|
|
||||||
DBcore::m_mutex = mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// executes multiple statements in one query
|
|
||||||
// do not use this in application logic
|
|
||||||
// this was built and maintained for database migrations only
|
|
||||||
MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
|
|
||||||
{
|
|
||||||
SetMultiStatementsOn();
|
|
||||||
|
|
||||||
BenchTimer timer;
|
|
||||||
timer.reset();
|
|
||||||
|
|
||||||
LockMutex lock(m_mutex);
|
|
||||||
|
|
||||||
// Reconnect if we are not connected before hand.
|
|
||||||
if (pStatus != Connected) {
|
|
||||||
Open();
|
|
||||||
}
|
|
||||||
auto r = MySQLRequestResult{};
|
|
||||||
|
|
||||||
int status = mysql_real_query(mysql, query.c_str(), query.length());
|
|
||||||
|
|
||||||
// process single result
|
|
||||||
if (status != 0) {
|
|
||||||
unsigned int error_number = mysql_errno(mysql);
|
|
||||||
|
|
||||||
if (error_number == CR_SERVER_GONE_ERROR) {
|
|
||||||
pStatus = Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// error logging
|
|
||||||
if (mysql_errno(mysql) > 0 && query.length() > 0 && mysql_errno(mysql) != 1065) {
|
|
||||||
std::string error_raw = fmt::format("{}", mysql_error(mysql));
|
|
||||||
std::string mysql_err = Strings::Trim(error_raw);
|
|
||||||
std::string clean_query = Strings::Replace(query, "\n", "");
|
|
||||||
LogMySQLError("[{}] ({}) query [{}]", mysql_err, mysql_errno(mysql), clean_query);
|
|
||||||
|
|
||||||
MYSQL_RES *res = mysql_store_result(mysql);
|
|
||||||
|
|
||||||
uint32 row_count = 0;
|
|
||||||
if (res) {
|
|
||||||
row_count = (uint32) mysql_num_rows(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = MySQLRequestResult(
|
|
||||||
res,
|
|
||||||
(uint32) mysql_affected_rows(mysql),
|
|
||||||
row_count,
|
|
||||||
(uint32) mysql_field_count(mysql),
|
|
||||||
(uint32) mysql_insert_id(mysql)
|
|
||||||
);
|
|
||||||
|
|
||||||
std::string error_message = mysql_error(mysql);
|
|
||||||
r.SetErrorMessage(error_message);
|
|
||||||
r.SetErrorNumber(mysql_errno(mysql));
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
mysql_free_result(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetMultiStatementsOff();
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
// there could be a query with a semicolon in the actual data, this is best effort for
|
|
||||||
// logging / display purposes
|
|
||||||
// rare that we see this when this is only used in DDL statements
|
|
||||||
auto pieces = Strings::Split(query, ";");
|
|
||||||
|
|
||||||
// process each statement result
|
|
||||||
do {
|
|
||||||
uint32 row_count = 0;
|
|
||||||
MYSQL_RES *res = mysql_store_result(mysql);
|
|
||||||
|
|
||||||
r = MySQLRequestResult(
|
|
||||||
res,
|
|
||||||
(uint32) mysql_affected_rows(mysql),
|
|
||||||
row_count,
|
|
||||||
(uint32) mysql_field_count(mysql),
|
|
||||||
(uint32) mysql_insert_id(mysql)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pieces.size() >= index) {
|
|
||||||
auto piece = pieces[index];
|
|
||||||
LogMySQLQuery(
|
|
||||||
"{} -- ({} row{} affected) ({}s)",
|
|
||||||
piece,
|
|
||||||
r.RowsAffected(),
|
|
||||||
r.RowsAffected() == 1 ? "" : "s",
|
|
||||||
std::to_string(timer.elapsed())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
row_count = (uint32) mysql_num_rows(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// more results? -1 = no, >0 = error, 0 = yes (keep looping)
|
|
||||||
if ((status = mysql_next_result(mysql)) > 0) {
|
|
||||||
if (mysql_errno(mysql) > 0) {
|
|
||||||
LogMySQLError("[{}] [{}]", mysql_errno(mysql), mysql_error(mysql));
|
|
||||||
}
|
|
||||||
|
|
||||||
mysql_free_result(res);
|
|
||||||
|
|
||||||
// error logging
|
|
||||||
std::string error_message = mysql_error(mysql);
|
|
||||||
r.SetErrorMessage(error_message);
|
|
||||||
r.SetErrorNumber(mysql_errno(mysql));
|
|
||||||
|
|
||||||
SetMultiStatementsOff();
|
|
||||||
|
|
||||||
// we handle errors elsewhere
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
mysql_free_result(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
} while (status == 0);
|
|
||||||
|
|
||||||
SetMultiStatementsOff();
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|||||||
+7
-30
@@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
class DBcore {
|
class DBcore {
|
||||||
public:
|
public:
|
||||||
@@ -24,26 +23,19 @@ public:
|
|||||||
~DBcore();
|
~DBcore();
|
||||||
eStatus GetStatus() { return pStatus; }
|
eStatus GetStatus() { return pStatus; }
|
||||||
MySQLRequestResult QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce = true);
|
MySQLRequestResult QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce = true);
|
||||||
MySQLRequestResult QueryDatabase(const std::string& query, bool retryOnFailureOnce = true);
|
MySQLRequestResult QueryDatabase(std::string query, bool retryOnFailureOnce = true);
|
||||||
MySQLRequestResult QueryDatabaseMulti(const std::string &query);
|
|
||||||
void TransactionBegin();
|
void TransactionBegin();
|
||||||
void TransactionCommit();
|
void TransactionCommit();
|
||||||
void TransactionRollback();
|
void TransactionRollback();
|
||||||
std::string Escape(const std::string& s);
|
|
||||||
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
|
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
|
||||||
void ping();
|
void ping();
|
||||||
|
MYSQL *getMySQL() { return &mysql; }
|
||||||
|
void SetMysql(MYSQL *mysql);
|
||||||
|
|
||||||
const std::string &GetOriginHost() const;
|
const std::string &GetOriginHost() const;
|
||||||
void SetOriginHost(const std::string &origin_host);
|
void SetOriginHost(const std::string &origin_host);
|
||||||
|
|
||||||
bool DoesTableExist(const std::string& table_name);
|
bool DoesTableExist(std::string table_name);
|
||||||
|
|
||||||
void SetMySQL(const DBcore &o)
|
|
||||||
{
|
|
||||||
mysql = o.mysql;
|
|
||||||
mysqlOwner = false;
|
|
||||||
}
|
|
||||||
void SetMutex(Mutex *mutex);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Open(
|
bool Open(
|
||||||
@@ -61,13 +53,10 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr);
|
bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr);
|
||||||
|
|
||||||
MYSQL* mysql;
|
MYSQL mysql;
|
||||||
bool mysqlOwner;
|
Mutex MDatabase;
|
||||||
Mutex *m_mutex;
|
|
||||||
eStatus pStatus;
|
eStatus pStatus;
|
||||||
|
|
||||||
std::mutex m_query_lock{};
|
|
||||||
|
|
||||||
std::string origin_host;
|
std::string origin_host;
|
||||||
|
|
||||||
char *pHost;
|
char *pHost;
|
||||||
@@ -78,20 +67,8 @@ private:
|
|||||||
uint32 pPort;
|
uint32 pPort;
|
||||||
bool pSSL;
|
bool pSSL;
|
||||||
|
|
||||||
// allows multiple queries to be executed within the same query
|
|
||||||
// do not use this under normal operation
|
|
||||||
// we use this during database migrations only currently
|
|
||||||
void SetMultiStatementsOn()
|
|
||||||
{
|
|
||||||
mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
// disables multiple statements to be executed in one query
|
|
||||||
void SetMultiStatementsOff()
|
|
||||||
{
|
|
||||||
mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+121
-71
@@ -19,81 +19,131 @@
|
|||||||
|
|
||||||
#include "deity.h"
|
#include "deity.h"
|
||||||
|
|
||||||
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
|
|
||||||
|
EQ::deity::DeityTypeBit EQ::deity::ConvertDeityTypeToDeityTypeBit(DeityType deity_type)
|
||||||
{
|
{
|
||||||
switch (deity_type) {
|
switch (deity_type) {
|
||||||
case DeityBertoxxulous:
|
case DeityBertoxxulous:
|
||||||
return bit_DeityBertoxxulous;
|
return bit_DeityBertoxxulous;
|
||||||
case DeityBrellSirilis:
|
case DeityBrellSirilis:
|
||||||
return bit_DeityBrellSirilis;
|
return bit_DeityBrellSirilis;
|
||||||
case DeityCazicThule:
|
case DeityCazicThule:
|
||||||
return bit_DeityCazicThule;
|
return bit_DeityCazicThule;
|
||||||
case DeityErollisiMarr:
|
case DeityErollisiMarr:
|
||||||
return bit_DeityErollisiMarr;
|
return bit_DeityErollisiMarr;
|
||||||
case DeityBristlebane:
|
case DeityBristlebane:
|
||||||
return bit_DeityBristlebane;
|
return bit_DeityBristlebane;
|
||||||
case DeityInnoruuk:
|
case DeityInnoruuk:
|
||||||
return bit_DeityInnoruuk;
|
return bit_DeityInnoruuk;
|
||||||
case DeityKarana:
|
case DeityKarana:
|
||||||
return bit_DeityKarana;
|
return bit_DeityKarana;
|
||||||
case DeityMithanielMarr:
|
case DeityMithanielMarr:
|
||||||
return bit_DeityMithanielMarr;
|
return bit_DeityMithanielMarr;
|
||||||
case DeityPrexus:
|
case DeityPrexus:
|
||||||
return bit_DeityPrexus;
|
return bit_DeityPrexus;
|
||||||
case DeityQuellious:
|
case DeityQuellious:
|
||||||
return bit_DeityQuellious;
|
return bit_DeityQuellious;
|
||||||
case DeityRallosZek:
|
case DeityRallosZek:
|
||||||
return bit_DeityRallosZek;
|
return bit_DeityRallosZek;
|
||||||
case DeityRodcetNife:
|
case DeityRodcetNife:
|
||||||
return bit_DeityRodcetNife;
|
return bit_DeityRodcetNife;
|
||||||
case DeitySolusekRo:
|
case DeitySolusekRo:
|
||||||
return bit_DeitySolusekRo;
|
return bit_DeitySolusekRo;
|
||||||
case DeityTheTribunal:
|
case DeityTheTribunal:
|
||||||
return bit_DeityTheTribunal;
|
return bit_DeityTheTribunal;
|
||||||
case DeityTunare:
|
case DeityTunare:
|
||||||
return bit_DeityTunare;
|
return bit_DeityTunare;
|
||||||
case DeityVeeshan:
|
case DeityVeeshan:
|
||||||
return bit_DeityVeeshan;
|
return bit_DeityVeeshan;
|
||||||
case DeityAgnostic_LB:
|
case DeityAgnostic_LB:
|
||||||
case DeityAgnostic:
|
case DeityAgnostic:
|
||||||
return bit_DeityAgnostic;
|
return bit_DeityAgnostic;
|
||||||
default:
|
default:
|
||||||
return bit_DeityAll;
|
return bit_DeityAll;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<EQ::deity::DeityType, std::string>& EQ::deity::GetDeityMap()
|
|
||||||
{
|
|
||||||
static const std::map<EQ::deity::DeityType, std::string> deity_map = {
|
|
||||||
{ DeityAgnostic, "Agnostic" },
|
|
||||||
{ DeityAgnostic_LB, "Agnostic" },
|
|
||||||
{ DeityBertoxxulous, "Bertoxxulous" },
|
|
||||||
{ DeityBrellSirilis, "Brell Serilis" },
|
|
||||||
{ DeityBristlebane, "Bristlebane" },
|
|
||||||
{ DeityCazicThule, "Cazic-Thule" },
|
|
||||||
{ DeityErollisiMarr, "Erollisi Marr" },
|
|
||||||
{ DeityInnoruuk, "Innoruuk" },
|
|
||||||
{ DeityKarana, "Karana" },
|
|
||||||
{ DeityMithanielMarr, "Mithaniel Marr" },
|
|
||||||
{ DeityPrexus, "Prexus" },
|
|
||||||
{ DeityQuellious, "Quellious" },
|
|
||||||
{ DeityRallosZek, "Rallos Zek" },
|
|
||||||
{ DeityRodcetNife, "Rodcet Nife" },
|
|
||||||
{ DeitySolusekRo, "Solusek Ro" },
|
|
||||||
{ DeityTheTribunal, "The Tribunal" },
|
|
||||||
{ DeityTunare, "Tunare" },
|
|
||||||
{ DeityVeeshan, "Veeshan" }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return deity_map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EQ::deity::GetDeityName(DeityType deity_type)
|
EQ::deity::DeityType EQ::deity::ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit)
|
||||||
{
|
{
|
||||||
|
switch (deity_type_bit) {
|
||||||
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) {
|
case bit_DeityAgnostic:
|
||||||
return EQ::deity::GetDeityMap().find(deity_type)->second;
|
return DeityAgnostic;
|
||||||
}
|
case bit_DeityBertoxxulous:
|
||||||
|
return DeityBertoxxulous;
|
||||||
return std::string();
|
case bit_DeityBrellSirilis:
|
||||||
|
return DeityBrellSirilis;
|
||||||
|
case bit_DeityCazicThule:
|
||||||
|
return DeityCazicThule;
|
||||||
|
case bit_DeityErollisiMarr:
|
||||||
|
return DeityErollisiMarr;
|
||||||
|
case bit_DeityBristlebane:
|
||||||
|
return DeityBristlebane;
|
||||||
|
case bit_DeityInnoruuk:
|
||||||
|
return DeityInnoruuk;
|
||||||
|
case bit_DeityKarana:
|
||||||
|
return DeityKarana;
|
||||||
|
case bit_DeityMithanielMarr:
|
||||||
|
return DeityMithanielMarr;
|
||||||
|
case bit_DeityPrexus:
|
||||||
|
return DeityPrexus;
|
||||||
|
case bit_DeityQuellious:
|
||||||
|
return DeityQuellious;
|
||||||
|
case bit_DeityRallosZek:
|
||||||
|
return DeityRallosZek;
|
||||||
|
case bit_DeityRodcetNife:
|
||||||
|
return DeityRodcetNife;
|
||||||
|
case bit_DeitySolusekRo:
|
||||||
|
return DeitySolusekRo;
|
||||||
|
case bit_DeityTheTribunal:
|
||||||
|
return DeityTheTribunal;
|
||||||
|
case bit_DeityTunare:
|
||||||
|
return DeityTunare;
|
||||||
|
case bit_DeityVeeshan:
|
||||||
|
return DeityVeeshan;
|
||||||
|
default:
|
||||||
|
return DeityUnknown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* EQ::deity::DeityName(DeityType deity_type)
|
||||||
|
{
|
||||||
|
switch (deity_type) {
|
||||||
|
case DeityBertoxxulous:
|
||||||
|
return "Bertoxxulous";
|
||||||
|
case DeityBrellSirilis:
|
||||||
|
return "Brell Serilis";
|
||||||
|
case DeityCazicThule:
|
||||||
|
return "Cazic-Thule";
|
||||||
|
case DeityErollisiMarr:
|
||||||
|
return "Erollisi Marr";
|
||||||
|
case DeityBristlebane:
|
||||||
|
return "Bristlebane";
|
||||||
|
case DeityInnoruuk:
|
||||||
|
return "Innoruuk";
|
||||||
|
case DeityKarana:
|
||||||
|
return "Karana";
|
||||||
|
case DeityMithanielMarr:
|
||||||
|
return "Mithaniel Marr";
|
||||||
|
case DeityPrexus:
|
||||||
|
return "Prexus";
|
||||||
|
case DeityQuellious:
|
||||||
|
return "Quellious";
|
||||||
|
case DeityRallosZek:
|
||||||
|
return "Rallos Zek";
|
||||||
|
case DeityRodcetNife:
|
||||||
|
return "Rodcet Nife";
|
||||||
|
case DeitySolusekRo:
|
||||||
|
return "Solusek Ro";
|
||||||
|
case DeityTheTribunal:
|
||||||
|
return "The Tribunal";
|
||||||
|
case DeityTunare:
|
||||||
|
return "Tunare";
|
||||||
|
case DeityVeeshan:
|
||||||
|
return "Veeshan";
|
||||||
|
case DeityAgnostic_LB:
|
||||||
|
case DeityAgnostic:
|
||||||
|
return "Agnostic";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-22
@@ -21,8 +21,6 @@
|
|||||||
#define COMMON_DEITY_H
|
#define COMMON_DEITY_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ
|
||||||
@@ -51,29 +49,30 @@ namespace EQ
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum DeityTypeBit : uint32 {
|
enum DeityTypeBit : uint32 {
|
||||||
bit_DeityAgnostic = 0x00000001,
|
bit_DeityNone = 0x00000000,
|
||||||
bit_DeityBertoxxulous = 0x00000002,
|
bit_DeityAgnostic = 0x00000001,
|
||||||
bit_DeityBrellSirilis = 0x00000004,
|
bit_DeityBertoxxulous = 0x00000002,
|
||||||
bit_DeityCazicThule = 0x00000008,
|
bit_DeityBrellSirilis = 0x00000004,
|
||||||
bit_DeityErollisiMarr = 0x00000010,
|
bit_DeityCazicThule = 0x00000008,
|
||||||
bit_DeityBristlebane = 0x00000020,
|
bit_DeityErollisiMarr = 0x00000010,
|
||||||
bit_DeityInnoruuk = 0x00000040,
|
bit_DeityBristlebane = 0x00000020,
|
||||||
bit_DeityKarana = 0x00000080,
|
bit_DeityInnoruuk = 0x00000040,
|
||||||
|
bit_DeityKarana = 0x00000080,
|
||||||
bit_DeityMithanielMarr = 0x00000100,
|
bit_DeityMithanielMarr = 0x00000100,
|
||||||
bit_DeityPrexus = 0x00000200,
|
bit_DeityPrexus = 0x00000200,
|
||||||
bit_DeityQuellious = 0x00000400,
|
bit_DeityQuellious = 0x00000400,
|
||||||
bit_DeityRallosZek = 0x00000800,
|
bit_DeityRallosZek = 0x00000800,
|
||||||
bit_DeityRodcetNife = 0x00001000,
|
bit_DeityRodcetNife = 0x00001000,
|
||||||
bit_DeitySolusekRo = 0x00002000,
|
bit_DeitySolusekRo = 0x00002000,
|
||||||
bit_DeityTheTribunal = 0x00004000,
|
bit_DeityTheTribunal = 0x00004000,
|
||||||
bit_DeityTunare = 0x00008000,
|
bit_DeityTunare = 0x00008000,
|
||||||
bit_DeityVeeshan = 0x00010000,
|
bit_DeityVeeshan = 0x00010000,
|
||||||
bit_DeityAll = UINT32_MAX
|
bit_DeityAll = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
|
|
||||||
extern DeityTypeBit GetDeityBitmask(DeityType deity_type);
|
extern DeityTypeBit ConvertDeityTypeToDeityTypeBit(DeityType deity_type);
|
||||||
extern std::string GetDeityName(DeityType deity_type);
|
extern DeityType ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit);
|
||||||
extern const std::map<DeityType, std::string>& GetDeityMap();
|
extern const char* DeityName(DeityType deity_type);
|
||||||
|
|
||||||
} /*deity*/
|
} /*deity*/
|
||||||
|
|
||||||
|
|||||||
+18
-92
@@ -1,32 +1,40 @@
|
|||||||
#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
|
||||||
|
httplib::Headers headers = {
|
||||||
|
{"Content-Type", "application/json"}
|
||||||
|
};
|
||||||
|
|
||||||
// payload
|
// payload
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
@@ -38,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);
|
||||||
}
|
}
|
||||||
@@ -54,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);
|
||||||
@@ -73,71 +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
|
|
||||||
|
|
||||||
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) {
|
||||||
@@ -146,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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
@@ -37,7 +33,7 @@ void DiscordManager::ProcessMessageQueue()
|
|||||||
message,
|
message,
|
||||||
webhook.webhook_url
|
webhook.webhook_url
|
||||||
);
|
);
|
||||||
message.clear();
|
message = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
message += m;
|
message += m;
|
||||||
@@ -51,9 +47,10 @@ void DiscordManager::ProcessMessageQueue()
|
|||||||
webhook.webhook_url
|
webhook.webhook_url
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
message.clear();
|
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{};
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
+23
-171
@@ -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[] = {
|
||||||
@@ -197,11 +194,11 @@ const std::map<int, std::string>& EQ::constants::GetLanguageMap()
|
|||||||
|
|
||||||
std::string EQ::constants::GetLanguageName(int language_id)
|
std::string EQ::constants::GetLanguageName(int language_id)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
||||||
return std::string();
|
return EQ::constants::GetLanguageMap().find(language_id)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetLanguageMap().find(language_id)->second;
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
||||||
@@ -220,11 +217,11 @@ const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
|||||||
|
|
||||||
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
|
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
||||||
return std::string();
|
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
|
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
|
||||||
@@ -243,11 +240,11 @@ const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
|
|||||||
|
|
||||||
std::string EQ::constants::GetFlyModeName(int8 flymode_id)
|
std::string EQ::constants::GetFlyModeName(int8 flymode_id)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
||||||
return std::string();
|
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
|
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
|
||||||
@@ -365,11 +362,11 @@ const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
|
|||||||
|
|
||||||
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
|
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(faction_consider_level, ConsiderLevel::Ally, ConsiderLevel::Scowls)) {
|
if (EQ::constants::GetConsiderLevelMap().find(faction_consider_level) != EQ::constants::GetConsiderLevelMap().end()) {
|
||||||
return std::string();;
|
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
|
const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
|
||||||
@@ -386,11 +383,11 @@ const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
|
|||||||
|
|
||||||
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
|
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
|
if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
|
||||||
return std::string();
|
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
|
const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
|
||||||
@@ -407,11 +404,11 @@ const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
|
|||||||
|
|
||||||
std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id)
|
std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
|
if (EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
|
||||||
return std::string();
|
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
|
const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
|
||||||
@@ -429,154 +426,9 @@ const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
|
|||||||
|
|
||||||
std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
|
std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
|
if (EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
|
||||||
return std::string();
|
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
|
return std::string();
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
|
|
||||||
{
|
|
||||||
static const std::map<int, std::string> object_type_map = {
|
|
||||||
{ ObjectTypes::SmallBag, "Small Bag" },
|
|
||||||
{ ObjectTypes::LargeBag, "Large Bag" },
|
|
||||||
{ ObjectTypes::Quiver, "Quiver" },
|
|
||||||
{ ObjectTypes::BeltPouch, "Belt Pouch" },
|
|
||||||
{ ObjectTypes::WristPouch, "Wrist Pouch" },
|
|
||||||
{ ObjectTypes::Backpack, "Backpack" },
|
|
||||||
{ ObjectTypes::SmallChest, "Small Chest" },
|
|
||||||
{ ObjectTypes::LargeChest, "Large Chest" },
|
|
||||||
{ ObjectTypes::Bandolier, "Bandolier" },
|
|
||||||
{ ObjectTypes::Medicine, "Medicine" },
|
|
||||||
{ ObjectTypes::Tinkering, "Tinkering" },
|
|
||||||
{ ObjectTypes::Lexicon, "Lexicon" },
|
|
||||||
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
|
|
||||||
{ ObjectTypes::Quest, "Quest" },
|
|
||||||
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
|
|
||||||
{ ObjectTypes::Baking, "Baking" },
|
|
||||||
{ ObjectTypes::Tailoring, "Tailoring" },
|
|
||||||
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
|
|
||||||
{ ObjectTypes::Fletching, "Fletching" },
|
|
||||||
{ ObjectTypes::Brewing, "Brewing" },
|
|
||||||
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
|
|
||||||
{ ObjectTypes::Pottery, "Pottery" },
|
|
||||||
{ ObjectTypes::Kiln, "Kiln" },
|
|
||||||
{ ObjectTypes::KeyMaker, "Key Maker" },
|
|
||||||
{ ObjectTypes::ResearchWIZ, "Lexicon" },
|
|
||||||
{ ObjectTypes::ResearchMAG, "Lexicon" },
|
|
||||||
{ ObjectTypes::ResearchNEC, "Lexicon" },
|
|
||||||
{ ObjectTypes::ResearchENC, "Lexicon" },
|
|
||||||
{ ObjectTypes::Unknown, "Unknown" },
|
|
||||||
{ ObjectTypes::ResearchPractice, "Lexicon" },
|
|
||||||
{ ObjectTypes::Alchemy, "Alchemy" },
|
|
||||||
{ ObjectTypes::HighElfForge, "High Elf Forge" },
|
|
||||||
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
|
|
||||||
{ ObjectTypes::OgreForge, "Ogre Forge" },
|
|
||||||
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
|
|
||||||
{ ObjectTypes::GnomeForge, "Gnome Forge" },
|
|
||||||
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
|
|
||||||
{ ObjectTypes::IksarForge, "Iksar Forge" },
|
|
||||||
{ ObjectTypes::HumanForgeOne, "Human Forge" },
|
|
||||||
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
|
|
||||||
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
|
|
||||||
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
|
|
||||||
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
|
|
||||||
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
|
|
||||||
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
|
|
||||||
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
|
|
||||||
{ ObjectTypes::Fishing, "Fishing" },
|
|
||||||
{ ObjectTypes::TrollForge, "Troll Forge" },
|
|
||||||
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
|
|
||||||
{ ObjectTypes::HalflingForge, "Halfling Forge" },
|
|
||||||
{ ObjectTypes::EruditeForge, "Erudite Forge" },
|
|
||||||
{ ObjectTypes::Merchant, "Merchant" },
|
|
||||||
{ ObjectTypes::FroglokForge, "Froglok Forge" },
|
|
||||||
{ ObjectTypes::Augmenter, "Augmenter" },
|
|
||||||
{ ObjectTypes::Churn, "Churn" },
|
|
||||||
{ ObjectTypes::TransformationMold, "Transformation Mold" },
|
|
||||||
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
|
|
||||||
{ ObjectTypes::Unattuner, "Unattuner" },
|
|
||||||
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
|
|
||||||
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
|
|
||||||
{ ObjectTypes::NoDeposit, "No Deposit" }
|
|
||||||
};
|
|
||||||
|
|
||||||
return object_type_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::constants::GetObjectTypeName(int object_type)
|
|
||||||
{
|
|
||||||
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
|
||||||
return std::string();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
|
|
||||||
{
|
|
||||||
static const std::map<uint8, std::string> weather_type_map = {
|
|
||||||
{WeatherTypes::None, "None"},
|
|
||||||
{WeatherTypes::Raining, "Raining"},
|
|
||||||
{WeatherTypes::Snowing, "Snowing"}
|
|
||||||
};
|
|
||||||
|
|
||||||
return weather_type_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::constants::GetWeatherTypeName(uint8 weather_type)
|
|
||||||
{
|
|
||||||
if (!EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
|
|
||||||
{
|
|
||||||
static const std::map<uint8, std::string> emote_event_type_map = {
|
|
||||||
{ EmoteEventTypes::LeaveCombat, "Leave Combat" },
|
|
||||||
{ EmoteEventTypes::EnterCombat, "Enter Combat" },
|
|
||||||
{ EmoteEventTypes::OnDeath, "On Death" },
|
|
||||||
{ EmoteEventTypes::AfterDeath, "After Death" },
|
|
||||||
{ EmoteEventTypes::Hailed, "Hailed" },
|
|
||||||
{ EmoteEventTypes::KilledPC, "Killed PC" },
|
|
||||||
{ EmoteEventTypes::KilledNPC, "Killed NPC" },
|
|
||||||
{ EmoteEventTypes::OnSpawn, "On Spawn" },
|
|
||||||
{ EmoteEventTypes::OnDespawn, "On Despawn" }
|
|
||||||
};
|
|
||||||
|
|
||||||
return emote_event_type_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type)
|
|
||||||
{
|
|
||||||
if (!EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
|
|
||||||
{
|
|
||||||
static const std::map<uint8, std::string> emote_type_map = {
|
|
||||||
{ EmoteTypes::Emote, "Emote" },
|
|
||||||
{ EmoteTypes::Shout, "Shout" },
|
|
||||||
{ EmoteTypes::Proximity, "Proximity" }
|
|
||||||
};
|
|
||||||
|
|
||||||
return emote_type_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
|
|
||||||
{
|
|
||||||
if (!EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-158
@@ -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,42 +465,4 @@ enum BucketComparison : uint8 {
|
|||||||
BucketIsNotBetween
|
BucketIsNotBetween
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EntityFilterType {
|
|
||||||
All,
|
|
||||||
Bots,
|
|
||||||
Clients,
|
|
||||||
NPCs
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ApplySpellType {
|
|
||||||
Solo,
|
|
||||||
Group,
|
|
||||||
Raid
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
namespace HeroicBonusBucket
|
|
||||||
{
|
|
||||||
const std::string WisMaxMana = "HWIS-MaxMana";
|
|
||||||
const std::string WisManaRegen = "HWIS-ManaRegen";
|
|
||||||
const std::string WisHealAmt = "HWIS-HealAmt";
|
|
||||||
const std::string IntMaxMana = "HINT-MaxMana";
|
|
||||||
const std::string IntManaRegen = "HINT-ManaRegen";
|
|
||||||
const std::string IntSpellDmg = "HINT-SpellDmg";
|
|
||||||
const std::string StrMeleeDamage = "HSTR-MeleeDamage";
|
|
||||||
const std::string StrShieldAC = "HSTR-ShieldAC";
|
|
||||||
const std::string StrMaxEndurance = "HSTR-MaxEndurance";
|
|
||||||
const std::string StrEnduranceRegen = "HSTR-EnduranceRegen";
|
|
||||||
const std::string StaMaxHP = "HSTA-MaxHP";
|
|
||||||
const std::string StaHPRegen = "HSTA-HPRegen";
|
|
||||||
const std::string StaMaxEndurance = "HSTA-MaxEndurance";
|
|
||||||
const std::string StaEnduranceRegen = "HSTA-EnduranceRegen";
|
|
||||||
const std::string AgiAvoidance = "HAGI-Avoidance";
|
|
||||||
const std::string AgiMaxEndurance = "HAGI-MaxEndurance";
|
|
||||||
const std::string AgiEnduranceRegen = "HAGI-EnduranceRegen";
|
|
||||||
const std::string DexRangedDamage = "HDEX-RangedDamage";
|
|
||||||
const std::string DexMaxEndurance = "HDEX-MaxEndurance";
|
|
||||||
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||||
|
|||||||
+1
-7
@@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest),
|
|||||||
N(OP_AltCurrencyPurchase),
|
N(OP_AltCurrencyPurchase),
|
||||||
N(OP_AltCurrencyReclaim),
|
N(OP_AltCurrencyReclaim),
|
||||||
N(OP_AltCurrencySell),
|
N(OP_AltCurrencySell),
|
||||||
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069
|
N(OP_AltCurrencySellSelection),
|
||||||
N(OP_Animation),
|
N(OP_Animation),
|
||||||
N(OP_AnnoyingZoneUnknown),
|
N(OP_AnnoyingZoneUnknown),
|
||||||
N(OP_ApplyPoison),
|
N(OP_ApplyPoison),
|
||||||
@@ -62,7 +62,6 @@ N(OP_BeginCast),
|
|||||||
N(OP_Bind_Wound),
|
N(OP_Bind_Wound),
|
||||||
N(OP_BlockedBuffs),
|
N(OP_BlockedBuffs),
|
||||||
N(OP_BoardBoat),
|
N(OP_BoardBoat),
|
||||||
N(OP_BookButton),
|
|
||||||
N(OP_Buff),
|
N(OP_Buff),
|
||||||
N(OP_BuffCreate),
|
N(OP_BuffCreate),
|
||||||
N(OP_BuffRemoveRequest),
|
N(OP_BuffRemoveRequest),
|
||||||
@@ -72,7 +71,6 @@ N(OP_Camp),
|
|||||||
N(OP_CancelSneakHide),
|
N(OP_CancelSneakHide),
|
||||||
N(OP_CancelTask),
|
N(OP_CancelTask),
|
||||||
N(OP_CancelTrade),
|
N(OP_CancelTrade),
|
||||||
N(OP_CashReward),
|
|
||||||
N(OP_CastSpell),
|
N(OP_CastSpell),
|
||||||
N(OP_ChangeSize),
|
N(OP_ChangeSize),
|
||||||
N(OP_ChannelMessage),
|
N(OP_ChannelMessage),
|
||||||
@@ -305,7 +303,6 @@ N(OP_LockoutTimerInfo),
|
|||||||
N(OP_Login),
|
N(OP_Login),
|
||||||
N(OP_LoginAccepted),
|
N(OP_LoginAccepted),
|
||||||
N(OP_LoginComplete),
|
N(OP_LoginComplete),
|
||||||
N(OP_LoginExpansionPacketData), //added for Rof2 client to send expansion data packet. Requires login_opcodes_sod.conf to be updated.
|
|
||||||
N(OP_LoginUnknown1),
|
N(OP_LoginUnknown1),
|
||||||
N(OP_LoginUnknown2),
|
N(OP_LoginUnknown2),
|
||||||
N(OP_Logout),
|
N(OP_Logout),
|
||||||
@@ -317,7 +314,6 @@ N(OP_LootRequest),
|
|||||||
N(OP_ManaChange),
|
N(OP_ManaChange),
|
||||||
N(OP_ManaUpdate),
|
N(OP_ManaUpdate),
|
||||||
N(OP_MarkNPC),
|
N(OP_MarkNPC),
|
||||||
N(OP_MarkRaidNPC),
|
|
||||||
N(OP_Marquee),
|
N(OP_Marquee),
|
||||||
N(OP_MemorizeSpell),
|
N(OP_MemorizeSpell),
|
||||||
N(OP_Mend),
|
N(OP_Mend),
|
||||||
@@ -400,8 +396,6 @@ N(OP_PVPLeaderBoardRequest),
|
|||||||
N(OP_PVPStats),
|
N(OP_PVPStats),
|
||||||
N(OP_QueryResponseThing),
|
N(OP_QueryResponseThing),
|
||||||
N(OP_QueryUCSServerStatus),
|
N(OP_QueryUCSServerStatus),
|
||||||
N(OP_RaidDelegateAbility),
|
|
||||||
N(OP_RaidClearNPCMarks),
|
|
||||||
N(OP_RaidInvite),
|
N(OP_RaidInvite),
|
||||||
N(OP_RaidJoin),
|
N(OP_RaidJoin),
|
||||||
N(OP_RaidUpdate),
|
N(OP_RaidUpdate),
|
||||||
|
|||||||
+9
-52
@@ -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,53 +1009,4 @@ enum StartZoneIndex {
|
|||||||
SharVahl
|
SharVahl
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FVNoDropFlagRule
|
|
||||||
{
|
|
||||||
Disabled = 0,
|
|
||||||
Enabled = 1,
|
|
||||||
AdminOnly = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Anonymity : uint8
|
|
||||||
{
|
|
||||||
NotAnonymous,
|
|
||||||
Anonymous,
|
|
||||||
Roleplaying
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ZoningMessage : int8 {
|
|
||||||
ZoneNoMessage = 0,
|
|
||||||
ZoneSuccess = 1,
|
|
||||||
ZoneNotReady = -1,
|
|
||||||
ZoneValidPC = -2,
|
|
||||||
ZoneStoryZone = -3,
|
|
||||||
ZoneNoExpansion = -6,
|
|
||||||
ZoneNoExperience = -7
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class RecipeCountType : uint8
|
|
||||||
{
|
|
||||||
Component,
|
|
||||||
Container,
|
|
||||||
Fail,
|
|
||||||
Salvage,
|
|
||||||
Success
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ALT_CURRENCY_ID_RADIANT 4
|
|
||||||
#define ALT_CURRENCY_ID_EBON 5
|
|
||||||
|
|
||||||
enum ResurrectionActions
|
|
||||||
{
|
|
||||||
Decline,
|
|
||||||
Accept
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ScribeSpellActions
|
|
||||||
{
|
|
||||||
Scribe,
|
|
||||||
Memorize,
|
|
||||||
Unmemorize
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
static bool global_dictionary_init = false;
|
static bool global_dictionary_init = false;
|
||||||
void EQ::InitializeDynamicLookups() {
|
void EQ::InitializeDynamicLookups() {
|
||||||
if (global_dictionary_init)
|
if (global_dictionary_init == true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
constants::InitializeDynamicLookups();
|
constants::InitializeDynamicLookups();
|
||||||
|
|||||||
+1
-1
@@ -129,7 +129,7 @@ namespace EQ
|
|||||||
|
|
||||||
LookupEntry(const LookupEntry *lookup_entry) { }
|
LookupEntry(const LookupEntry *lookup_entry) { }
|
||||||
LookupEntry(
|
LookupEntry(
|
||||||
const InventoryTypeSize_Struct& InventoryTypeSize,
|
InventoryTypeSize_Struct InventoryTypeSize,
|
||||||
uint64 EquipmentBitmask,
|
uint64 EquipmentBitmask,
|
||||||
uint64 GeneralBitmask,
|
uint64 GeneralBitmask,
|
||||||
uint64 CursorBitmask,
|
uint64 CursorBitmask,
|
||||||
|
|||||||
@@ -236,6 +236,26 @@ uint32 EQApplicationPacket::serialize(uint16 opcode, unsigned char *dest) const
|
|||||||
return size+OpCodeBytes;
|
return size+OpCodeBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*EQProtocolPacket::EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len)
|
||||||
|
: BasePacket(buf, len),
|
||||||
|
opcode(op)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint32 offset;
|
||||||
|
opcode=ntohs(*(const uint16 *)buf);
|
||||||
|
offset=2;
|
||||||
|
|
||||||
|
if (len-offset) {
|
||||||
|
pBuffer= new unsigned char[len-offset];
|
||||||
|
memcpy(pBuffer,buf+offset,len-offset);
|
||||||
|
size=len-offset;
|
||||||
|
} else {
|
||||||
|
pBuffer=nullptr;
|
||||||
|
size=0;
|
||||||
|
}
|
||||||
|
OpMgr=&RawOpcodeManager;
|
||||||
|
}*/
|
||||||
|
|
||||||
bool EQProtocolPacket::combine(const EQProtocolPacket *rhs)
|
bool EQProtocolPacket::combine(const EQProtocolPacket *rhs)
|
||||||
{
|
{
|
||||||
bool result=false;
|
bool result=false;
|
||||||
@@ -267,6 +287,74 @@ bool result=false;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
this is the code to do app-layer combining, instead of protocol layer.
|
||||||
|
this was taken out due to complex interactions with the opcode manager,
|
||||||
|
and will require a bit more thinking (likely moving into EQStream) to
|
||||||
|
get running again... but might be a good thing some day.
|
||||||
|
|
||||||
|
bool EQApplicationPacket::combine(const EQApplicationPacket *rhs)
|
||||||
|
{
|
||||||
|
uint32 newsize=0, offset=0;
|
||||||
|
unsigned char *tmpbuffer=nullptr;
|
||||||
|
|
||||||
|
if (opcode!=OP_AppCombined) {
|
||||||
|
newsize=app_opcode_size+size+(size>254?3:1)+app_opcode_size+rhs->size+(rhs->size>254?3:1);
|
||||||
|
tmpbuffer=new unsigned char [newsize];
|
||||||
|
offset=0;
|
||||||
|
if (size>254) {
|
||||||
|
tmpbuffer[offset++]=0xff;
|
||||||
|
*(uint16 *)(tmpbuffer+offset)=htons(size);
|
||||||
|
offset+=1;
|
||||||
|
} else {
|
||||||
|
tmpbuffer[offset++]=size;
|
||||||
|
}
|
||||||
|
offset+=serialize(tmpbuffer+offset);
|
||||||
|
} else {
|
||||||
|
newsize=size+app_opcode_size+rhs->size+(rhs->size>254?3:1);
|
||||||
|
tmpbuffer=new unsigned char [newsize];
|
||||||
|
memcpy(tmpbuffer,pBuffer,size);
|
||||||
|
offset=size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rhs->size>254) {
|
||||||
|
tmpbuffer[offset++]=0xff;
|
||||||
|
*(uint16 *)(tmpbuffer+offset)=htons(rhs->size);
|
||||||
|
offset+=1;
|
||||||
|
} else {
|
||||||
|
tmpbuffer[offset++]=rhs->size;
|
||||||
|
}
|
||||||
|
offset+=rhs->serialize(tmpbuffer+offset);
|
||||||
|
|
||||||
|
size=offset;
|
||||||
|
opcode=OP_AppCombined;
|
||||||
|
|
||||||
|
delete[] pBuffer;
|
||||||
|
pBuffer=tmpbuffer;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool EQProtocolPacket::ValidateCRC(const unsigned char *buffer, int length, uint32 Key)
|
||||||
|
{
|
||||||
|
bool valid=false;
|
||||||
|
// OP_SessionRequest, OP_SessionResponse, OP_OutOfSession are not CRC'd
|
||||||
|
if (buffer[0]==0x00 && (buffer[1]==OP_SessionRequest || buffer[1]==OP_SessionResponse || buffer[1]==OP_OutOfSession)) {
|
||||||
|
valid=true;
|
||||||
|
} else {
|
||||||
|
uint16 comp_crc=CRC16(buffer,length-2,Key);
|
||||||
|
uint16 packet_crc=ntohs(*(const uint16 *)(buffer+length-2));
|
||||||
|
#ifdef EQN_DEBUG
|
||||||
|
if (packet_crc && comp_crc != packet_crc) {
|
||||||
|
std::cout << "CRC mismatch: comp=" << std::hex << comp_crc << ", packet=" << packet_crc << std::dec << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
valid = (!packet_crc || comp_crc == packet_crc);
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize)
|
uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize)
|
||||||
{
|
{
|
||||||
uint32 newlen=0;
|
uint32 newlen=0;
|
||||||
@@ -315,6 +403,55 @@ uint32 flag_offset=1,newlength;
|
|||||||
return newlength;
|
return newlength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EQProtocolPacket::ChatDecode(unsigned char *buffer, int size, int DecodeKey)
|
||||||
|
{
|
||||||
|
if ((size >= 2) && buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
|
||||||
|
int Key=DecodeKey;
|
||||||
|
unsigned char *test=(unsigned char *)malloc(size);
|
||||||
|
buffer+=2;
|
||||||
|
size-=2;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0 ; i+4 <= size ; i+=4)
|
||||||
|
{
|
||||||
|
int pt = (*(int*)&buffer[i])^(Key);
|
||||||
|
Key = (*(int*)&buffer[i]);
|
||||||
|
*(int*)&test[i]=pt;
|
||||||
|
}
|
||||||
|
unsigned char KC=Key&0xFF;
|
||||||
|
for ( ; i < size ; i++)
|
||||||
|
{
|
||||||
|
test[i]=buffer[i]^KC;
|
||||||
|
}
|
||||||
|
memcpy(buffer,test,size);
|
||||||
|
free(test);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQProtocolPacket::ChatEncode(unsigned char *buffer, int size, int EncodeKey)
|
||||||
|
{
|
||||||
|
if (buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
|
||||||
|
int Key=EncodeKey;
|
||||||
|
char *test=(char*)malloc(size);
|
||||||
|
int i;
|
||||||
|
buffer+=2;
|
||||||
|
size-=2;
|
||||||
|
for ( i = 0 ; i+4 <= size ; i+=4)
|
||||||
|
{
|
||||||
|
int pt = (*(int*)&buffer[i])^(Key);
|
||||||
|
Key = pt;
|
||||||
|
*(int*)&test[i]=pt;
|
||||||
|
}
|
||||||
|
unsigned char KC=Key&0xFF;
|
||||||
|
for ( ; i < size ; i++)
|
||||||
|
{
|
||||||
|
test[i]=buffer[i]^KC;
|
||||||
|
}
|
||||||
|
memcpy(buffer,test,size);
|
||||||
|
free(test);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EQApplicationPacket *EQApplicationPacket::Copy() const {
|
EQApplicationPacket *EQApplicationPacket::Copy() const {
|
||||||
return(new EQApplicationPacket(*this));
|
return(new EQApplicationPacket(*this));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,8 +80,11 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static bool ValidateCRC(const unsigned char *buffer, int length, uint32 Key);
|
||||||
static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
||||||
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
||||||
|
static void ChatDecode(unsigned char *buffer, int size, int DecodeKey);
|
||||||
|
static void ChatEncode(unsigned char *buffer, int size, int EncodeKey);
|
||||||
|
|
||||||
uint16 GetRawOpcode() const { return(opcode); }
|
uint16 GetRawOpcode() const { return(opcode); }
|
||||||
|
|
||||||
|
|||||||
+36
-79
@@ -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;
|
||||||
@@ -374,18 +374,18 @@ struct NewZone_Struct {
|
|||||||
/*0684*/ uint16 zone_id;
|
/*0684*/ uint16 zone_id;
|
||||||
/*0686*/ uint16 zone_instance;
|
/*0686*/ uint16 zone_instance;
|
||||||
/*0688*/ uint32 unknown688;
|
/*0688*/ uint32 unknown688;
|
||||||
/*0692*/ uint8 unknown692[8];
|
/*0692*/ uint8 unknown692[8];
|
||||||
// Titanium doesn't have a translator, but we can still safely add stuff under here without issues since client memcpy's only what it knows
|
// 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*/
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1793,17 +1793,6 @@ struct GMSummon_Struct {
|
|||||||
/*104*/ uint32 unknown2; // E0 E0 56 00
|
/*104*/ uint32 unknown2; // E0 E0 56 00
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GMFind_Struct {
|
|
||||||
char charname[64];
|
|
||||||
char gmname[64];
|
|
||||||
uint32 success;
|
|
||||||
uint32 zoneID;
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
uint32 unknown2;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet
|
struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet
|
||||||
/* 0*/ char charname[64];
|
/* 0*/ char charname[64];
|
||||||
|
|
||||||
@@ -2203,19 +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 {
|
||||||
@@ -2559,10 +2540,7 @@ struct GMEmoteZone_Struct {
|
|||||||
struct BookText_Struct {
|
struct BookText_Struct {
|
||||||
uint8 window; // where to display the text (0xFF means new window)
|
uint8 window; // where to display the text (0xFF means new window)
|
||||||
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
||||||
int16 invslot; // Only used in SoF and later clients.
|
uint32 invslot; // Only used in SoF and later clients.
|
||||||
int32 target_id;
|
|
||||||
int8 can_cast;
|
|
||||||
int8 can_scribe;
|
|
||||||
char booktext[1]; // Variable Length
|
char booktext[1]; // Variable Length
|
||||||
};
|
};
|
||||||
// This is the request to read a book.
|
// This is the request to read a book.
|
||||||
@@ -2571,18 +2549,11 @@ struct BookText_Struct {
|
|||||||
struct BookRequest_Struct {
|
struct BookRequest_Struct {
|
||||||
uint8 window; // where to display the text (0xFF means new window)
|
uint8 window; // where to display the text (0xFF means new window)
|
||||||
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
||||||
int16 invslot; // Only used in Sof and later clients;
|
uint32 invslot; // Only used in Sof and later clients;
|
||||||
int32 target_id;
|
int16 subslot; // The subslot inside of a bag if it is inside one.
|
||||||
char txtfile[20];
|
char txtfile[20];
|
||||||
};
|
};
|
||||||
|
|
||||||
// used by Scribe and CastSpell book buttons
|
|
||||||
struct BookButton_Struct
|
|
||||||
{
|
|
||||||
int16 invslot; // server slot
|
|
||||||
int32 target_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Object/Ground Spawn struct
|
** Object/Ground Spawn struct
|
||||||
** Used for Forges, Ovens, ground spawns, items dropped to ground, etc
|
** Used for Forges, Ovens, ground spawns, items dropped to ground, etc
|
||||||
@@ -3653,19 +3624,17 @@ struct LevelAppearance_Struct { //Sends a little graphic on level up
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MerchantList {
|
struct MerchantList {
|
||||||
uint32 id;
|
uint32 id;
|
||||||
uint32 slot;
|
uint32 slot;
|
||||||
uint32 item;
|
uint32 item;
|
||||||
int16 faction_required;
|
int16 faction_required;
|
||||||
int8 level_required;
|
int8 level_required;
|
||||||
uint8 min_status;
|
uint16 alt_currency_cost;
|
||||||
uint8 max_status;
|
uint32 classes_required;
|
||||||
uint16 alt_currency_cost;
|
uint8 probability;
|
||||||
uint32 classes_required;
|
|
||||||
uint8 probability;
|
|
||||||
std::string bucket_name;
|
std::string bucket_name;
|
||||||
std::string bucket_value;
|
std::string bucket_value;
|
||||||
uint8 bucket_comparison;
|
uint8 bucket_comparison;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TempMerchantList {
|
struct TempMerchantList {
|
||||||
@@ -4115,9 +4084,7 @@ struct UpdateLeadershipAA_Struct {
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
GroupLeadershipAbility_MarkNPC = 0,
|
GroupLeadershipAbility_MarkNPC = 0
|
||||||
RaidLeadershipAbility_MarkNPC = 16,
|
|
||||||
RaidLeadershipAbility_MainAssist = 19
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DoGroupLeadershipAbility_Struct
|
struct DoGroupLeadershipAbility_Struct
|
||||||
@@ -4161,9 +4128,8 @@ struct InspectBuffs_Struct {
|
|||||||
struct RaidGeneral_Struct {
|
struct RaidGeneral_Struct {
|
||||||
/*00*/ uint32 action; //=10
|
/*00*/ uint32 action; //=10
|
||||||
/*04*/ char player_name[64]; //should both be the player's name
|
/*04*/ char player_name[64]; //should both be the player's name
|
||||||
/*68*/ uint32 unknown1;
|
/*64*/ char leader_name[64];
|
||||||
/*72*/ char leader_name[64];
|
/*132*/ uint32 parameter;
|
||||||
/*136*/ uint32 parameter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RaidAddMember_Struct {
|
struct RaidAddMember_Struct {
|
||||||
@@ -4174,14 +4140,9 @@ struct RaidAddMember_Struct {
|
|||||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RaidNote_Struct {
|
|
||||||
/*000*/ RaidGeneral_Struct general;
|
|
||||||
/*140*/ char note[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RaidMOTD_Struct {
|
struct RaidMOTD_Struct {
|
||||||
/*000*/ RaidGeneral_Struct general;
|
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||||
/*140*/ char motd[1024];
|
/*136*/ char motd[0]; // max size is 1024, but reply is variable
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RaidLeadershipUpdate_Struct {
|
struct RaidLeadershipUpdate_Struct {
|
||||||
@@ -4576,7 +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*/
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5037,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;
|
||||||
@@ -5194,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;
|
||||||
@@ -5551,11 +5512,7 @@ struct ServerLootItem_Struct {
|
|||||||
uint32 aug_4; // uint32 aug_4;
|
uint32 aug_4; // uint32 aug_4;
|
||||||
uint32 aug_5; // uint32 aug_5;
|
uint32 aug_5; // uint32 aug_5;
|
||||||
uint32 aug_6; // uint32 aug_5;
|
uint32 aug_6; // uint32 aug_5;
|
||||||
bool attuned;
|
uint8 attuned;
|
||||||
std::string custom_data;
|
|
||||||
uint32 ornamenticon {};
|
|
||||||
uint32 ornamentidfile {};
|
|
||||||
uint32 ornament_hero_model {};
|
|
||||||
uint16 trivial_min_level;
|
uint16 trivial_min_level;
|
||||||
uint16 trivial_max_level;
|
uint16 trivial_max_level;
|
||||||
uint16 npc_min_level;
|
uint16 npc_min_level;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ EQStreamIdentifier::~EQStreamIdentifier() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQStreamIdentifier::RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) {
|
void EQStreamIdentifier::RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) {
|
||||||
auto p = new Patch;
|
auto p = new Patch;
|
||||||
p->signature = sig;
|
p->signature = sig;
|
||||||
p->name = name;
|
p->name = name;
|
||||||
@@ -145,7 +145,7 @@ void EQStreamIdentifier::Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EQStreamIdentifier::AddStream(std::shared_ptr<EQStreamInterface> eqs) {
|
void EQStreamIdentifier::AddStream(std::shared_ptr<EQStreamInterface> eqs) {
|
||||||
m_streams.emplace_back(Record(eqs));
|
m_streams.push_back(Record(eqs));
|
||||||
eqs = nullptr;
|
eqs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
~EQStreamIdentifier();
|
~EQStreamIdentifier();
|
||||||
|
|
||||||
//registration interface.
|
//registration interface.
|
||||||
void RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs);
|
void RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs);
|
||||||
|
|
||||||
//main processing interface
|
//main processing interface
|
||||||
void Process();
|
void Process();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -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_*/
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
EQDB EQDB::s_EQDB;
|
EQDB EQDB::s_EQDB;
|
||||||
|
|
||||||
|
EQDB::EQDB() {
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int EQDB::field_count() {
|
unsigned int EQDB::field_count() {
|
||||||
return mysql_field_count(mysql_ref);
|
return mysql_field_count(mysql_ref);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
//this is the main object exported to perl.
|
//this is the main object exported to perl.
|
||||||
class EQDB {
|
class EQDB {
|
||||||
EQDB() = default;
|
EQDB();
|
||||||
public:
|
public:
|
||||||
static EQDB *Singleton() { return(&s_EQDB); }
|
static EQDB *Singleton() { return(&s_EQDB); }
|
||||||
|
|
||||||
|
|||||||
+18
-29
@@ -19,7 +19,6 @@
|
|||||||
#include "../common/global_define.h"
|
#include "../common/global_define.h"
|
||||||
#include "eqemu_config.h"
|
#include "eqemu_config.h"
|
||||||
#include "misc_functions.h"
|
#include "misc_functions.h"
|
||||||
#include "strings.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -34,13 +33,13 @@ void EQEmuConfig::parse_config()
|
|||||||
LongName = _root["server"]["world"].get("longname", "").asString();
|
LongName = _root["server"]["world"].get("longname", "").asString();
|
||||||
WorldAddress = _root["server"]["world"].get("address", "").asString();
|
WorldAddress = _root["server"]["world"].get("address", "").asString();
|
||||||
LocalAddress = _root["server"]["world"].get("localaddress", "").asString();
|
LocalAddress = _root["server"]["world"].get("localaddress", "").asString();
|
||||||
MaxClients = Strings::ToInt(_root["server"]["world"].get("maxclients", "-1").asString());
|
MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str());
|
||||||
SharedKey = _root["server"]["world"].get("key", "").asString();
|
SharedKey = _root["server"]["world"].get("key", "").asString();
|
||||||
LoginCount = 0;
|
LoginCount = 0;
|
||||||
|
|
||||||
if (_root["server"]["world"]["loginserver"].isObject()) {
|
if (_root["server"]["world"]["loginserver"].isObject()) {
|
||||||
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
|
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
|
||||||
LoginPort = Strings::ToUnsignedInt(_root["server"]["world"]["loginserver"].get("port", "5998").asString());
|
LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
|
||||||
LoginLegacy = false;
|
LoginLegacy = false;
|
||||||
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
|
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
|
||||||
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
||||||
@@ -63,7 +62,7 @@ void EQEmuConfig::parse_config()
|
|||||||
|
|
||||||
auto loginconfig = new LoginConfig;
|
auto loginconfig = new LoginConfig;
|
||||||
loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString();
|
loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString();
|
||||||
loginconfig->LoginPort = Strings::ToUnsignedInt(_root["server"]["world"][str].get("port", "5998").asString());
|
loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str());
|
||||||
loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString();
|
loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString();
|
||||||
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
|
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
|
||||||
|
|
||||||
@@ -85,39 +84,29 @@ void EQEmuConfig::parse_config()
|
|||||||
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
|
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
|
||||||
Locked = false;
|
Locked = false;
|
||||||
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
|
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
|
||||||
|
|
||||||
auto_database_updates = false;
|
|
||||||
if (_root["server"].get("auto_database_updates", "true").asString() == "true") {
|
|
||||||
auto_database_updates = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
||||||
WorldTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["tcp"].get("port", "9000").asString());
|
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
|
||||||
|
|
||||||
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
||||||
TelnetTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["telnet"].get("port", "9001").asString());
|
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
|
||||||
TelnetEnabled = false;
|
TelnetEnabled = false;
|
||||||
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; }
|
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; }
|
||||||
|
|
||||||
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
|
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
|
||||||
WorldHTTPPort = Strings::ToUnsignedInt(_root["server"]["world"]["http"].get("port", "9080").asString());
|
WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
|
||||||
WorldHTTPEnabled = false;
|
WorldHTTPEnabled = false;
|
||||||
|
|
||||||
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
|
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
|
||||||
WorldHTTPEnabled = true;
|
WorldHTTPEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_root["server"].get("disable_config_checks", "false").asString() == "true") {
|
|
||||||
DisableConfigChecks = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UCS
|
* UCS
|
||||||
*/
|
*/
|
||||||
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
||||||
ChatPort = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "7778").asString());
|
ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
|
||||||
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
||||||
MailPort = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "7778").asString());
|
MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database
|
* Database
|
||||||
@@ -125,7 +114,7 @@ void EQEmuConfig::parse_config()
|
|||||||
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
|
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
|
||||||
DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
|
DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
|
||||||
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
|
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
|
||||||
DatabasePort = Strings::ToUnsignedInt(_root["server"]["database"].get("port", "3306").asString());
|
DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
|
||||||
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
|
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,14 +123,14 @@ void EQEmuConfig::parse_config()
|
|||||||
ContentDbUsername = _root["server"]["content_database"].get("username", "").asString();
|
ContentDbUsername = _root["server"]["content_database"].get("username", "").asString();
|
||||||
ContentDbPassword = _root["server"]["content_database"].get("password", "").asString();
|
ContentDbPassword = _root["server"]["content_database"].get("password", "").asString();
|
||||||
ContentDbHost = _root["server"]["content_database"].get("host", "").asString();
|
ContentDbHost = _root["server"]["content_database"].get("host", "").asString();
|
||||||
ContentDbPort = Strings::ToUnsignedInt(_root["server"]["content_database"].get("port", 0).asString());
|
ContentDbPort = atoi(_root["server"]["content_database"].get("port", 0).asString().c_str());
|
||||||
ContentDbName = _root["server"]["content_database"].get("db", "").asString();
|
ContentDbName = _root["server"]["content_database"].get("db", "").asString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* QS
|
* QS
|
||||||
*/
|
*/
|
||||||
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
|
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
|
||||||
QSDatabasePort = Strings::ToUnsignedInt(_root["server"]["qsdatabase"].get("port", "3306").asString());
|
QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
|
||||||
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
|
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
|
||||||
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
|
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
|
||||||
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
||||||
@@ -149,9 +138,9 @@ void EQEmuConfig::parse_config()
|
|||||||
/**
|
/**
|
||||||
* Zones
|
* Zones
|
||||||
*/
|
*/
|
||||||
DefaultStatus = Strings::ToUnsignedInt(_root["server"]["zones"].get("defaultstatus", 0).asString());
|
DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
|
||||||
ZonePortLow = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("low", "7000").asString());
|
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
|
||||||
ZonePortHigh = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("high", "7999").asString());
|
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Files
|
* Files
|
||||||
@@ -181,10 +170,10 @@ void EQEmuConfig::parse_config()
|
|||||||
/**
|
/**
|
||||||
* Launcher
|
* Launcher
|
||||||
*/
|
*/
|
||||||
RestartWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("restart", "10000").asString());
|
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
|
||||||
TerminateWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString());
|
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
|
||||||
InitialBootWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("initial", "20000").asString());
|
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
|
||||||
ZoneBootInterval = Strings::ToInt(_root["server"]["launcher"]["timers"].get("interval", "2000").asString());
|
ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str());
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString();
|
ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString();
|
||||||
#else
|
#else
|
||||||
|
|||||||
+11
-18
@@ -20,9 +20,7 @@
|
|||||||
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
#include "linked_list.h"
|
#include "linked_list.h"
|
||||||
#include "path_manager.h"
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
struct LoginConfig {
|
struct LoginConfig {
|
||||||
std::string LoginHost;
|
std::string LoginHost;
|
||||||
@@ -60,7 +58,6 @@ class EQEmuConfig
|
|||||||
uint16 WorldHTTPPort;
|
uint16 WorldHTTPPort;
|
||||||
std::string WorldHTTPMimeFile;
|
std::string WorldHTTPMimeFile;
|
||||||
std::string SharedKey;
|
std::string SharedKey;
|
||||||
bool DisableConfigChecks;
|
|
||||||
|
|
||||||
// From <chatserver/>
|
// From <chatserver/>
|
||||||
std::string ChatHost;
|
std::string ChatHost;
|
||||||
@@ -120,8 +117,6 @@ class EQEmuConfig
|
|||||||
uint16 ZonePortHigh;
|
uint16 ZonePortHigh;
|
||||||
uint8 DefaultStatus;
|
uint8 DefaultStatus;
|
||||||
|
|
||||||
bool auto_database_updates;
|
|
||||||
|
|
||||||
// uint16 DynamicCount;
|
// uint16 DynamicCount;
|
||||||
|
|
||||||
// map<string,uint16> StaticZones;
|
// map<string,uint16> StaticZones;
|
||||||
@@ -149,32 +144,30 @@ class EQEmuConfig
|
|||||||
return (_config);
|
return (_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow the use to set the conf file to be used.
|
||||||
|
static void SetConfigFile(std::string file)
|
||||||
|
{
|
||||||
|
EQEmuConfig::ConfigFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
// Load the config
|
// Load the config
|
||||||
static bool LoadConfig(const std::string& path = "")
|
static bool LoadConfig()
|
||||||
{
|
{
|
||||||
if (_config != nullptr) {
|
if (_config != nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_config = new EQEmuConfig;
|
_config = new EQEmuConfig;
|
||||||
|
|
||||||
return parseFile(path);
|
return parseFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load config file and parse data
|
// Load config file and parse data
|
||||||
static bool parseFile(const std::string& file_path = ".")
|
static bool parseFile() {
|
||||||
{
|
|
||||||
if (_config == nullptr) {
|
if (_config == nullptr) {
|
||||||
return LoadConfig(file_path);
|
return LoadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string file = fmt::format(
|
std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary);
|
||||||
"{}/{}",
|
|
||||||
(file_path.empty() ? path.GetServerPath() : file_path),
|
|
||||||
EQEmuConfig::ConfigFile
|
|
||||||
);
|
|
||||||
|
|
||||||
std::ifstream fconfig(file, std::ifstream::binary);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fconfig >> _config->_root;
|
fconfig >> _config->_root;
|
||||||
_config->parse_config();
|
_config->parse_config();
|
||||||
|
|||||||
+277
-411
@@ -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,15 +140,17 @@ 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::Error].log_to_console = static_cast<uint8>(Logs::General);
|
log_settings[Logs::Emergency].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
|
log_settings[Logs::Alert].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::Info].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::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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Category enabled status on defaults
|
* Set Category enabled status on defaults
|
||||||
@@ -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,10 +322,11 @@ void EQEmuLogSys::ProcessLogWrite(
|
|||||||
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
||||||
{
|
{
|
||||||
switch (log_category) {
|
switch (log_category) {
|
||||||
case Logs::Crash:
|
case Logs::Status:
|
||||||
case Logs::Error:
|
case Logs::Normal:
|
||||||
|
return Chat::Yellow;
|
||||||
case Logs::MySQLError:
|
case Logs::MySQLError:
|
||||||
case Logs::QuestErrors:
|
case Logs::Error:
|
||||||
return Chat::Red;
|
return Chat::Red;
|
||||||
case Logs::MySQLQuery:
|
case Logs::MySQLQuery:
|
||||||
case Logs::Debug:
|
case Logs::Debug:
|
||||||
@@ -200,208 +336,37 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
|||||||
case Logs::Commands:
|
case Logs::Commands:
|
||||||
case Logs::Mercenaries:
|
case Logs::Mercenaries:
|
||||||
return Chat::Magenta;
|
return Chat::Magenta;
|
||||||
|
case Logs::Crash:
|
||||||
|
return Chat::Red;
|
||||||
default:
|
default:
|
||||||
return Chat::Yellow;
|
return Chat::Yellow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param debug_level
|
* @param debug_level
|
||||||
* @param log_category
|
* @param log_category
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
void EQEmuLogSys::ProcessConsoleMessage(
|
void EQEmuLogSys::ProcessConsoleMessage(uint16 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// color matching in []
|
|
||||||
// ex: [<red>variable] would produce [variable] with red inside brackets
|
|
||||||
std::map<std::string, rang::fgB> colors = {
|
|
||||||
{"<black>", rang::fgB::black},
|
|
||||||
{"<green>", rang::fgB::green},
|
|
||||||
{"<yellow>", rang::fgB::yellow},
|
|
||||||
{"<blue>", rang::fgB::blue},
|
|
||||||
{"<magenta>", rang::fgB::magenta},
|
|
||||||
{"<cyan>", rang::fgB::cyan},
|
|
||||||
{"<gray>", rang::fgB::gray},
|
|
||||||
{"<red>", rang::fgB::red},
|
|
||||||
};
|
|
||||||
|
|
||||||
bool match_color = false;
|
|
||||||
for (auto &c: colors) {
|
|
||||||
if (Strings::Contains(e, c.first)) {
|
|
||||||
e = Strings::Replace(e, c.first, "");
|
|
||||||
(!is_error ? std::cout : std::cerr)
|
|
||||||
<< rang::fgB::gray
|
|
||||||
<< "["
|
|
||||||
<< rang::style::bold
|
|
||||||
<< c.second
|
|
||||||
<< e
|
|
||||||
<< rang::style::reset
|
|
||||||
<< rang::fgB::gray
|
|
||||||
<< "] ";
|
|
||||||
match_color = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// string match to colors
|
|
||||||
std::map<std::string, rang::fgB> matches = {
|
|
||||||
{"missing", rang::fgB::red},
|
|
||||||
{"error", rang::fgB::red},
|
|
||||||
{"ok", rang::fgB::green},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto &c: matches) {
|
|
||||||
if (Strings::Contains(e, c.first)) {
|
|
||||||
(!is_error ? std::cout : std::cerr)
|
|
||||||
<< rang::fgB::gray
|
|
||||||
<< "["
|
|
||||||
<< rang::style::bold
|
|
||||||
<< c.second
|
|
||||||
<< e
|
|
||||||
<< rang::style::reset
|
|
||||||
<< rang::fgB::gray
|
|
||||||
<< "] ";
|
|
||||||
match_color = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we don't match a color in either the string matching or
|
|
||||||
// the color tag matching, we default to yellow inside brackets
|
|
||||||
// if uppercase, does not get colored
|
|
||||||
if (!match_color) {
|
|
||||||
if (!is_upper) {
|
|
||||||
(!is_error ? std::cout : std::cerr)
|
|
||||||
<< rang::fgB::gray
|
|
||||||
<< "["
|
|
||||||
<< rang::style::bold
|
|
||||||
<< rang::fgB::yellow
|
|
||||||
<< e
|
|
||||||
<< rang::style::reset
|
|
||||||
<< rang::fgB::gray
|
|
||||||
<< "] ";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(!is_error ? std::cout : std::cerr)
|
|
||||||
<< (is_error ? rang::fgB::red : rang::fgB::gray)
|
|
||||||
<< e
|
|
||||||
<< " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(!is_error ? std::cout : std::cerr)
|
|
||||||
<< (is_error ? rang::fgB::red : rang::fgB::gray)
|
|
||||||
<< message
|
|
||||||
<< " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!origination_info.zone_short_name.empty()) {
|
|
||||||
(!is_error ? std::cout : std::cerr)
|
|
||||||
<<
|
|
||||||
rang::fgB::black
|
|
||||||
<<
|
|
||||||
"-- "
|
|
||||||
<<
|
|
||||||
fmt::format(
|
|
||||||
"[{}] ({}) inst_id [{}]",
|
|
||||||
origination_info.zone_short_name,
|
|
||||||
origination_info.zone_long_name,
|
|
||||||
origination_info.instance_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
(!is_error ? std::cout : std::cerr) << rang::style::reset << std::endl;
|
|
||||||
|
|
||||||
m_on_log_console_hook(log_category, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -413,6 +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
|
||||||
*
|
*
|
||||||
@@ -431,57 +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
|
va_list args;
|
||||||
bool ignore_log_legacy_format = (
|
va_start(args, message);
|
||||||
log_category == Logs::Netcode ||
|
std::string output_message = vStringFormat(message, args);
|
||||||
log_category == Logs::MySQLQuery ||
|
va_end(args);
|
||||||
log_category == Logs::MySQLError ||
|
|
||||||
log_category == Logs::PacketServerClient ||
|
|
||||||
log_category == Logs::PacketClientServer ||
|
|
||||||
log_category == Logs::PacketServerToServer
|
|
||||||
);
|
|
||||||
|
|
||||||
// remove this when we remove all legacy logs
|
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message);
|
||||||
std::string output_message = message;
|
|
||||||
if (!ignore_log_legacy_format) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, message);
|
|
||||||
output_message = vStringFormat(message, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l.log_to_console_enabled) {
|
if (log_to_console) {
|
||||||
EQEmuLogSys::ProcessConsoleMessage(
|
EQEmuLogSys::ProcessConsoleMessage(log_category, output_debug_message);
|
||||||
log_category,
|
|
||||||
output_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -533,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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -582,14 +575,10 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
|
|||||||
*/
|
*/
|
||||||
void EQEmuLogSys::SilenceConsoleLogging()
|
void EQEmuLogSys::SilenceConsoleLogging()
|
||||||
{
|
{
|
||||||
std::copy(std::begin(log_settings), std::end(log_settings), std::begin(pre_silence_settings));
|
|
||||||
|
|
||||||
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
|
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
|
||||||
log_settings[log_index].log_to_console = 0;
|
log_settings[log_index].log_to_console = 0;
|
||||||
log_settings[log_index].is_category_enabled = 0;
|
log_settings[log_index].is_category_enabled = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -597,13 +586,14 @@ void EQEmuLogSys::SilenceConsoleLogging()
|
|||||||
*/
|
*/
|
||||||
void EQEmuLogSys::EnableConsoleLogging()
|
void EQEmuLogSys::EnableConsoleLogging()
|
||||||
{
|
{
|
||||||
std::copy(std::begin(pre_silence_settings), std::end(pre_silence_settings), std::begin(log_settings));
|
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
|
||||||
|
log_settings[log_index].log_to_console = Logs::General;
|
||||||
|
log_settings[log_index].is_category_enabled = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
|
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
|
||||||
{
|
{
|
||||||
InjectTablesIfNotExist();
|
|
||||||
|
|
||||||
auto categories = LogsysCategoriesRepository::GetWhere(
|
auto categories = LogsysCategoriesRepository::GetWhere(
|
||||||
*m_database,
|
*m_database,
|
||||||
"TRUE ORDER BY log_category_id"
|
"TRUE ORDER BY log_category_id"
|
||||||
@@ -642,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);
|
||||||
@@ -650,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;
|
||||||
@@ -683,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,109 +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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmuLogSys::DisableMySQLErrorLogs()
|
|
||||||
{
|
|
||||||
log_settings[Logs::MySQLError].log_to_file = 0;
|
|
||||||
log_settings[Logs::MySQLError].log_to_console = 0;
|
|
||||||
log_settings[Logs::MySQLError].log_to_gmsay = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmuLogSys::EnableMySQLErrorLogs()
|
|
||||||
{
|
|
||||||
log_settings[Logs::MySQLError].log_to_file = 1;
|
|
||||||
log_settings[Logs::MySQLError].log_to_console = 1;
|
|
||||||
log_settings[Logs::MySQLError].log_to_gmsay = 1;
|
|
||||||
}
|
|
||||||
|
|||||||
+66
-104
@@ -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,15 +131,6 @@ namespace Logs {
|
|||||||
CombatRecord,
|
CombatRecord,
|
||||||
Hate,
|
Hate,
|
||||||
Discord,
|
Discord,
|
||||||
Faction,
|
|
||||||
PacketServerClient,
|
|
||||||
PacketClientServer,
|
|
||||||
PacketServerToServer,
|
|
||||||
Bugs,
|
|
||||||
QuestErrors,
|
|
||||||
PlayerEvents,
|
|
||||||
DataBuckets,
|
|
||||||
Zoning,
|
|
||||||
MaxCategoryID /* Don't Remove this */
|
MaxCategoryID /* Don't Remove this */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -151,7 +143,7 @@ namespace Logs {
|
|||||||
"AI",
|
"AI",
|
||||||
"Aggro",
|
"Aggro",
|
||||||
"Attack",
|
"Attack",
|
||||||
"Deprecated",
|
"Packet :: Client -> Server",
|
||||||
"Combat",
|
"Combat",
|
||||||
"Commands",
|
"Commands",
|
||||||
"Crash",
|
"Crash",
|
||||||
@@ -162,52 +154,52 @@ namespace Logs {
|
|||||||
"Inventory",
|
"Inventory",
|
||||||
"Launcher",
|
"Launcher",
|
||||||
"Netcode",
|
"Netcode",
|
||||||
"Normal (Deprecated)",
|
"Normal",
|
||||||
"Object",
|
"Object",
|
||||||
"Pathing",
|
"Pathing",
|
||||||
"QS Server (Deprecated)",
|
"QS Server",
|
||||||
"Quests",
|
"Quests",
|
||||||
"Rules",
|
"Rules",
|
||||||
"Skills",
|
"Skills",
|
||||||
"Spawns",
|
"Spawns",
|
||||||
"Spells",
|
"Spells",
|
||||||
"Status (Deprecated)",
|
"Status",
|
||||||
"TCP Connection",
|
"TCP Connection",
|
||||||
"Tasks",
|
"Tasks",
|
||||||
"Tradeskills",
|
"Tradeskills",
|
||||||
"Trading",
|
"Trading",
|
||||||
"Tribute",
|
"Tribute",
|
||||||
"UCS Server (Deprecated)",
|
"UCS Server",
|
||||||
"Web Interface (Deprecated)",
|
"WebInterface Server",
|
||||||
"World Server (Deprecated)",
|
"World Server",
|
||||||
"Zone Server (Deprecated)",
|
"Zone Server",
|
||||||
"QueryErr",
|
"MySQL Error",
|
||||||
"Query",
|
"MySQL Query",
|
||||||
"Mercenaries",
|
"Mercenaries",
|
||||||
"Quest Debug",
|
"Quest Debug",
|
||||||
"Legacy Packet Logging (Deprecated)",
|
"Packet :: Server -> Client",
|
||||||
"Legacy Packet Logging (Deprecated)",
|
"Packet :: Client -> Server Unhandled",
|
||||||
"Legacy Packet Logging (Deprecated)",
|
"Packet :: Server -> Client (Dump)",
|
||||||
"Legacy Packet Logging (Deprecated)",
|
"Packet :: Client -> Server (Dump)",
|
||||||
"Login Server (Deprecated)",
|
"Login Server",
|
||||||
"Client Login",
|
"Client Login",
|
||||||
"Headless Client (Deprecated)",
|
"Headless Client",
|
||||||
"HP Update",
|
"HP Update",
|
||||||
"FixZ",
|
"FixZ",
|
||||||
"Food",
|
"Food",
|
||||||
"Traps",
|
"Traps",
|
||||||
"NPC Roam Box",
|
"NPC Roam Box",
|
||||||
"NPC Scaling",
|
"NPC Scaling",
|
||||||
"MobAppearance",
|
"Mob Appearance",
|
||||||
"Info",
|
"Info",
|
||||||
"Warning",
|
"Warning",
|
||||||
"Critical (Deprecated)",
|
"Critical",
|
||||||
"Emergency (Deprecated)",
|
"Emergency",
|
||||||
"Alert (Deprecated)",
|
"Alert",
|
||||||
"Notice (Deprecated)",
|
"Notice",
|
||||||
"AI Scan",
|
"AI Scan Close",
|
||||||
"AI Yell",
|
"AI Yell For Help",
|
||||||
"AI CastBeneficial",
|
"AI Cast Beneficial Close",
|
||||||
"AOE Cast",
|
"AOE Cast",
|
||||||
"Entity Management",
|
"Entity Management",
|
||||||
"Flee",
|
"Flee",
|
||||||
@@ -224,19 +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",
|
|
||||||
"DataBuckets",
|
|
||||||
"Zoning",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,40 +311,32 @@ public:
|
|||||||
*/
|
*/
|
||||||
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
|
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
|
||||||
|
|
||||||
// temporary bucket to re-load after silencing
|
|
||||||
LogSettings pre_silence_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,41 +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);
|
|
||||||
|
|
||||||
void DisableMySQLErrorLogs();
|
|
||||||
void EnableMySQLErrorLogs();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// reference to database
|
// reference to database
|
||||||
Database *m_database;
|
Database *m_database;
|
||||||
std::function<void(uint16 log_category, const char *func, const std::string &)> m_on_log_gmsay_hook;
|
std::function<void(uint16 log_category, 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;
|
||||||
|
|||||||
+653
-291
File diff suppressed because it is too large
Load Diff
@@ -58,6 +58,10 @@ EQTime::EQTime()
|
|||||||
SetCurrentEQTimeOfDay(start, time(0));
|
SetCurrentEQTimeOfDay(start, time(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EQTime::~EQTime()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
|
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
|
||||||
//This function was written by the ShowEQ Project.
|
//This function was written by the ShowEQ Project.
|
||||||
//Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to.
|
//Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to.
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ public:
|
|||||||
//Constructor/destructor
|
//Constructor/destructor
|
||||||
EQTime(TimeOfDay_Struct start_eq, time_t start_real);
|
EQTime(TimeOfDay_Struct start_eq, time_t start_real);
|
||||||
EQTime();
|
EQTime();
|
||||||
~EQTime() = default;
|
~EQTime();
|
||||||
|
|
||||||
//Get functions
|
//Get functions
|
||||||
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||||
|
|||||||
+4
-4
@@ -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;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace EQ
|
|||||||
_running = true;
|
_running = true;
|
||||||
|
|
||||||
for (size_t i = 0; i < threads; ++i) {
|
for (size_t i = 0; i < threads; ++i) {
|
||||||
_threads.emplace_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
|
_threads.push_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +60,8 @@ namespace EQ
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Fn, typename... Args>
|
template<typename Fn, typename... Args>
|
||||||
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::invoke_result<Fn, Args...>::type> {
|
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
|
||||||
using return_type = typename std::invoke_result<Fn, Args...>::type;
|
using return_type = typename std::result_of<Fn(Args...)>::type;
|
||||||
|
|
||||||
auto task = std::make_shared<std::packaged_task<return_type()>>(
|
auto task = std::make_shared<std::packaged_task<return_type()>>(
|
||||||
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
|
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,214 +0,0 @@
|
|||||||
#ifndef EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H
|
|
||||||
#define EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "player_events.h"
|
|
||||||
#include "../repositories/base/base_player_event_logs_repository.h"
|
|
||||||
#include <cereal/archives/json.hpp>
|
|
||||||
#include <cereal/types/vector.hpp>
|
|
||||||
|
|
||||||
struct DiscordField {
|
|
||||||
std::string name;
|
|
||||||
std::string value;
|
|
||||||
bool is_inline;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(name),
|
|
||||||
CEREAL_NVP(value),
|
|
||||||
cereal::make_nvp("inline", is_inline)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DiscordAuthor {
|
|
||||||
std::string name;
|
|
||||||
std::string icon_url;
|
|
||||||
std::string url;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(name),
|
|
||||||
CEREAL_NVP(icon_url),
|
|
||||||
CEREAL_NVP(url)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DiscordEmbed {
|
|
||||||
std::vector<DiscordField> fields;
|
|
||||||
std::string title;
|
|
||||||
std::string description;
|
|
||||||
std::string timestamp;
|
|
||||||
DiscordAuthor author;
|
|
||||||
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(fields),
|
|
||||||
CEREAL_NVP(title),
|
|
||||||
CEREAL_NVP(description),
|
|
||||||
CEREAL_NVP(timestamp),
|
|
||||||
CEREAL_NVP(author)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DiscordWebhook {
|
|
||||||
std::vector<DiscordEmbed> embeds;
|
|
||||||
std::string content;
|
|
||||||
std::string avatar_url;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(embeds),
|
|
||||||
CEREAL_NVP(avatar_url),
|
|
||||||
CEREAL_NVP(content)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class PlayerEventDiscordFormatter {
|
|
||||||
public:
|
|
||||||
static std::string GetCurrentTimestamp();
|
|
||||||
static std::string FormatEventSay(const PlayerEvent::PlayerEventContainer &c, const PlayerEvent::SayEvent &e);
|
|
||||||
static std::string
|
|
||||||
FormatGMCommand(const PlayerEvent::PlayerEventContainer &c, const PlayerEvent::GMCommandEvent &e);
|
|
||||||
static void BuildDiscordField(
|
|
||||||
std::vector<DiscordField> *f,
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &value,
|
|
||||||
bool is_inline = true
|
|
||||||
);
|
|
||||||
static void BuildBaseEmbed(
|
|
||||||
std::vector<DiscordEmbed> *e,
|
|
||||||
const std::vector<DiscordField> &f,
|
|
||||||
PlayerEvent::PlayerEventContainer c
|
|
||||||
);
|
|
||||||
static std::string FormatWithNodata(const PlayerEvent::PlayerEventContainer &c);
|
|
||||||
|
|
||||||
static std::string FormatAAGainedEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::AAGainedEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatAAPurchasedEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::AAPurchasedEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatDeathEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::DeathEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatFishSuccessEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::FishSuccessEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatForageSuccessEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::ForageSuccessEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatDestroyItemEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::DestroyItemEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatDiscoverItemEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::DiscoverItemEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatDroppedItemEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::DroppedItemEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatLevelGainedEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::LevelGainedEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatLevelLostEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::LevelLostEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatLootItemEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::LootItemEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatGroundSpawnPickupEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::GroundSpawnPickupEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatMerchantPurchaseEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::MerchantPurchaseEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatMerchantSellEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::MerchantSellEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatNPCHandinEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::HandinEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatSkillUpEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::SkillUpEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatTaskAcceptEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::TaskAcceptEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatTaskCompleteEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::TaskCompleteEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatTaskUpdateEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::TaskUpdateEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatTradeEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::TradeEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatTraderPurchaseEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::TraderPurchaseEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatTraderSellEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::TraderSellEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatResurrectAcceptEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::ResurrectAcceptEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatSplitMoneyEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::SplitMoneyEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatCombineEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::CombineEvent &e
|
|
||||||
);
|
|
||||||
static std::string FormatZoningEvent(
|
|
||||||
const PlayerEvent::PlayerEventContainer &c,
|
|
||||||
const PlayerEvent::ZoningEvent &e
|
|
||||||
);
|
|
||||||
static DiscordWebhook BuildDiscordWebhook(
|
|
||||||
const PlayerEvent::PlayerEventContainer &p,
|
|
||||||
std::vector<DiscordEmbed> &embeds
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H
|
|
||||||
@@ -1,702 +0,0 @@
|
|||||||
#include <cereal/archives/json.hpp>
|
|
||||||
#include "player_event_logs.h"
|
|
||||||
#include "player_event_discord_formatter.h"
|
|
||||||
#include "../platform.h"
|
|
||||||
#include "../rulesys.h"
|
|
||||||
|
|
||||||
const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour
|
|
||||||
|
|
||||||
// general initialization routine
|
|
||||||
void PlayerEventLogs::Init()
|
|
||||||
{
|
|
||||||
m_process_batch_events_timer.SetTimer(RuleI(Logging, BatchPlayerEventProcessIntervalSeconds) * 1000);
|
|
||||||
m_process_retention_truncation_timer.SetTimer(PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL);
|
|
||||||
|
|
||||||
ValidateDatabaseConnection();
|
|
||||||
|
|
||||||
// initialize settings array
|
|
||||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
|
||||||
m_settings[i].id = i;
|
|
||||||
m_settings[i].event_name = PlayerEvent::EventName[i];
|
|
||||||
m_settings[i].event_enabled = 1;
|
|
||||||
m_settings[i].retention_days = 0;
|
|
||||||
m_settings[i].discord_webhook_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSettingsDefaults();
|
|
||||||
|
|
||||||
// initialize settings from database
|
|
||||||
auto s = PlayerEventLogSettingsRepository::All(*m_database);
|
|
||||||
std::vector<int> db{};
|
|
||||||
db.reserve(s.size());
|
|
||||||
for (auto &e: s) {
|
|
||||||
if (e.id >= PlayerEvent::MAX) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
m_settings[e.id] = e;
|
|
||||||
db.emplace_back(e.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert entries that don't exist in database
|
|
||||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
|
||||||
bool is_in_database = std::find(db.begin(), db.end(), i) != db.end();
|
|
||||||
bool is_deprecated = Strings::Contains(PlayerEvent::EventName[i], "Deprecated");
|
|
||||||
bool is_implemented = !Strings::Contains(PlayerEvent::EventName[i], "Unimplemented");
|
|
||||||
|
|
||||||
// remove when deprecated
|
|
||||||
if (is_deprecated && is_in_database) {
|
|
||||||
LogInfo("[Deprecated] Removing PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i);
|
|
||||||
PlayerEventLogSettingsRepository::DeleteWhere(*m_database, fmt::format("id = {}", i));
|
|
||||||
}
|
|
||||||
// remove when unimplemented if present
|
|
||||||
if (!is_implemented && is_in_database) {
|
|
||||||
LogInfo("[Unimplemented] Removing PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i);
|
|
||||||
PlayerEventLogSettingsRepository::DeleteWhere(*m_database, fmt::format("id = {}", i));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_missing_in_database = std::find(db.begin(), db.end(), i) == db.end();
|
|
||||||
if (is_missing_in_database && is_implemented && !is_deprecated) {
|
|
||||||
LogInfo(
|
|
||||||
"[New] PlayerEvent [{}] ({})",
|
|
||||||
PlayerEvent::EventName[i],
|
|
||||||
i
|
|
||||||
);
|
|
||||||
|
|
||||||
auto c = PlayerEventLogSettingsRepository::NewEntity();
|
|
||||||
c.id = i;
|
|
||||||
c.event_name = PlayerEvent::EventName[i];
|
|
||||||
c.event_enabled = m_settings[i].event_enabled;
|
|
||||||
c.retention_days = m_settings[i].retention_days;
|
|
||||||
PlayerEventLogSettingsRepository::InsertOne(*m_database, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld();
|
|
||||||
bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ();
|
|
||||||
|
|
||||||
// on initial boot process truncation
|
|
||||||
if (processing_in_world || processing_in_qs) {
|
|
||||||
ProcessRetentionTruncation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the database object, during initialization
|
|
||||||
PlayerEventLogs *PlayerEventLogs::SetDatabase(Database *db)
|
|
||||||
{
|
|
||||||
m_database = db;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validates whether the connection is valid or not, used in initialization
|
|
||||||
bool PlayerEventLogs::ValidateDatabaseConnection()
|
|
||||||
{
|
|
||||||
if (!m_database) {
|
|
||||||
LogError("No database connection");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// determines if the passed in event is enabled or not
|
|
||||||
// this is used to gate logic or events from firing off
|
|
||||||
// this is used prior to building the events, we don't want to
|
|
||||||
// build the events, send them through the stack in a function call
|
|
||||||
// only to discard them immediately afterwards, very wasteful on resources
|
|
||||||
// the quest api currently does this
|
|
||||||
bool PlayerEventLogs::IsEventEnabled(PlayerEvent::EventType event)
|
|
||||||
{
|
|
||||||
return m_settings[event].event_enabled ? m_settings[event].event_enabled : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this processes any current player events on the queue
|
|
||||||
void PlayerEventLogs::ProcessBatchQueue()
|
|
||||||
{
|
|
||||||
m_batch_queue_lock.lock();
|
|
||||||
if (m_record_batch_queue.empty()) {
|
|
||||||
m_batch_queue_lock.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BenchTimer benchmark;
|
|
||||||
|
|
||||||
// flush many
|
|
||||||
PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue);
|
|
||||||
LogPlayerEventsDetail(
|
|
||||||
"Processing batch player event log queue of [{}] took [{}]",
|
|
||||||
m_record_batch_queue.size(),
|
|
||||||
benchmark.elapsed()
|
|
||||||
);
|
|
||||||
|
|
||||||
// empty
|
|
||||||
m_record_batch_queue = {};
|
|
||||||
m_batch_queue_lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// adds a player event to the queue
|
|
||||||
void PlayerEventLogs::AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &log)
|
|
||||||
{
|
|
||||||
m_batch_queue_lock.lock();
|
|
||||||
m_record_batch_queue.emplace_back(log);
|
|
||||||
m_batch_queue_lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// fills common event data in the SendEvent function
|
|
||||||
void PlayerEventLogs::FillPlayerEvent(
|
|
||||||
const PlayerEvent::PlayerEvent &p,
|
|
||||||
PlayerEventLogsRepository::PlayerEventLogs &n
|
|
||||||
)
|
|
||||||
{
|
|
||||||
n.account_id = p.account_id;
|
|
||||||
n.character_id = p.character_id;
|
|
||||||
n.zone_id = p.zone_id;
|
|
||||||
n.instance_id = p.instance_id;
|
|
||||||
n.x = p.x;
|
|
||||||
n.y = p.y;
|
|
||||||
n.z = p.z;
|
|
||||||
n.heading = p.heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
// builds the dynamic packet used to ship the player event over the wire
|
|
||||||
// supports serializing the struct so it can be rebuilt on the other end
|
|
||||||
std::unique_ptr<ServerPacket>
|
|
||||||
PlayerEventLogs::BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e)
|
|
||||||
{
|
|
||||||
EQ::Net::DynamicPacket dyn_pack;
|
|
||||||
dyn_pack.PutSerialize(0, e);
|
|
||||||
auto pack_size = sizeof(ServerSendPlayerEvent_Struct) + dyn_pack.Length();
|
|
||||||
auto pack = std::make_unique<ServerPacket>(ServerOP_PlayerEvent, static_cast<uint32_t>(pack_size));
|
|
||||||
auto buf = reinterpret_cast<ServerSendPlayerEvent_Struct *>(pack->pBuffer);
|
|
||||||
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
|
|
||||||
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
|
|
||||||
|
|
||||||
return pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PlayerEventLogSettingsRepository::PlayerEventLogSettings *PlayerEventLogs::GetSettings() const
|
|
||||||
{
|
|
||||||
return m_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PlayerEventLogs::IsEventDiscordEnabled(int32_t event_type_id)
|
|
||||||
{
|
|
||||||
// out of bounds check
|
|
||||||
if (event_type_id >= PlayerEvent::EventType::MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure webhook id is set
|
|
||||||
if (m_settings[event_type_id].discord_webhook_id == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure there is a matching webhook to begin with
|
|
||||||
if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlayerEventLogs::GetDiscordWebhookUrlFromEventType(int32_t event_type_id)
|
|
||||||
{
|
|
||||||
// out of bounds check
|
|
||||||
if (event_type_id >= PlayerEvent::EventType::MAX) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure webhook id is set
|
|
||||||
if (m_settings[event_type_id].discord_webhook_id == 0) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure there is a matching webhook to begin with
|
|
||||||
if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) {
|
|
||||||
return LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// GM_COMMAND | [x] Implemented Formatter
|
|
||||||
// ZONING | [x] Implemented Formatter
|
|
||||||
// AA_GAIN | [x] Implemented Formatter
|
|
||||||
// AA_PURCHASE | [x] Implemented Formatter
|
|
||||||
// FORAGE_SUCCESS | [x] Implemented Formatter
|
|
||||||
// FORAGE_FAILURE | [x] Implemented Formatter
|
|
||||||
// FISH_SUCCESS | [x] Implemented Formatter
|
|
||||||
// FISH_FAILURE | [x] Implemented Formatter
|
|
||||||
// ITEM_DESTROY | [x] Implemented Formatter
|
|
||||||
// WENT_ONLINE | [x] Implemented Formatter
|
|
||||||
// WENT_OFFLINE | [x] Implemented Formatter
|
|
||||||
// LEVEL_GAIN | [x] Implemented Formatter
|
|
||||||
// LEVEL_LOSS | [x] Implemented Formatter
|
|
||||||
// LOOT_ITEM | [x] Implemented Formatter
|
|
||||||
// MERCHANT_PURCHASE | [x] Implemented Formatter
|
|
||||||
// MERCHANT_SELL | [x] Implemented Formatter
|
|
||||||
// GROUP_JOIN | [] Implemented Formatter
|
|
||||||
// GROUP_LEAVE | [] Implemented Formatter
|
|
||||||
// RAID_JOIN | [] Implemented Formatter
|
|
||||||
// RAID_LEAVE | [] Implemented Formatter
|
|
||||||
// GROUNDSPAWN_PICKUP | [x] Implemented Formatter
|
|
||||||
// NPC_HANDIN | [x] Implemented Formatter
|
|
||||||
// SKILL_UP | [x] Implemented Formatter
|
|
||||||
// TASK_ACCEPT | [x] Implemented Formatter
|
|
||||||
// TASK_UPDATE | [x] Implemented Formatter
|
|
||||||
// TASK_COMPLETE | [x] Implemented Formatter
|
|
||||||
// TRADE | [] Implemented Formatter
|
|
||||||
// GIVE_ITEM | [] Implemented Formatter
|
|
||||||
// SAY | [x] Implemented Formatter
|
|
||||||
// REZ_ACCEPTED | [x] Implemented Formatter
|
|
||||||
// DEATH | [x] Implemented Formatter
|
|
||||||
// COMBINE_FAILURE | [x] Implemented Formatter
|
|
||||||
// COMBINE_SUCCESS | [x] Implemented Formatter
|
|
||||||
// DROPPED_ITEM | [x] Implemented Formatter
|
|
||||||
// SPLIT_MONEY | [x] Implemented Formatter
|
|
||||||
// DZ_JOIN | [] Implemented Formatter
|
|
||||||
// DZ_LEAVE | [] Implemented Formatter
|
|
||||||
// TRADER_PURCHASE | [x] Implemented Formatter
|
|
||||||
// TRADER_SELL | [x] Implemented Formatter
|
|
||||||
// BANDOLIER_CREATE | [] Implemented Formatter
|
|
||||||
// BANDOLIER_SWAP | [] Implemented Formatter
|
|
||||||
// DISCOVER_ITEM | [X] Implemented Formatter
|
|
||||||
|
|
||||||
std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e)
|
|
||||||
{
|
|
||||||
std::string payload;
|
|
||||||
switch (e.player_event_log.event_type_id) {
|
|
||||||
case PlayerEvent::AA_GAIN: {
|
|
||||||
PlayerEvent::AAGainedEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatAAGainedEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::AA_PURCHASE: {
|
|
||||||
PlayerEvent::AAPurchasedEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatAAPurchasedEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::COMBINE_FAILURE:
|
|
||||||
case PlayerEvent::COMBINE_SUCCESS: {
|
|
||||||
PlayerEvent::CombineEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatCombineEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::DEATH: {
|
|
||||||
PlayerEvent::DeathEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatDeathEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::DISCOVER_ITEM: {
|
|
||||||
PlayerEvent::DiscoverItemEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatDiscoverItemEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::DROPPED_ITEM: {
|
|
||||||
PlayerEvent::DroppedItemEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatDroppedItemEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::FISH_FAILURE:
|
|
||||||
case PlayerEvent::FORAGE_FAILURE:
|
|
||||||
case PlayerEvent::WENT_ONLINE:
|
|
||||||
case PlayerEvent::WENT_OFFLINE: {
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::FISH_SUCCESS: {
|
|
||||||
PlayerEvent::FishSuccessEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatFishSuccessEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::FORAGE_SUCCESS: {
|
|
||||||
PlayerEvent::ForageSuccessEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatForageSuccessEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::ITEM_DESTROY: {
|
|
||||||
PlayerEvent::DestroyItemEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatDestroyItemEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::LEVEL_GAIN: {
|
|
||||||
PlayerEvent::LevelGainedEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatLevelGainedEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::LEVEL_LOSS: {
|
|
||||||
PlayerEvent::LevelLostEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatLevelLostEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::LOOT_ITEM: {
|
|
||||||
PlayerEvent::LootItemEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatLootItemEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::GROUNDSPAWN_PICKUP: {
|
|
||||||
PlayerEvent::GroundSpawnPickupEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatGroundSpawnPickupEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::NPC_HANDIN: {
|
|
||||||
PlayerEvent::HandinEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatNPCHandinEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::SAY: {
|
|
||||||
PlayerEvent::SayEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatEventSay(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::GM_COMMAND: {
|
|
||||||
PlayerEvent::GMCommandEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatGMCommand(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::SKILL_UP: {
|
|
||||||
PlayerEvent::SkillUpEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatSkillUpEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::SPLIT_MONEY: {
|
|
||||||
PlayerEvent::SplitMoneyEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatSplitMoneyEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::TASK_ACCEPT: {
|
|
||||||
PlayerEvent::TaskAcceptEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatTaskAcceptEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::TASK_COMPLETE: {
|
|
||||||
PlayerEvent::TaskCompleteEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatTaskCompleteEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::TASK_UPDATE: {
|
|
||||||
PlayerEvent::TaskUpdateEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatTaskUpdateEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::TRADE: {
|
|
||||||
PlayerEvent::TradeEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatTradeEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::TRADER_PURCHASE: {
|
|
||||||
PlayerEvent::TraderPurchaseEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatTraderPurchaseEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::TRADER_SELL: {
|
|
||||||
PlayerEvent::TraderSellEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatTraderSellEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::REZ_ACCEPTED: {
|
|
||||||
PlayerEvent::ResurrectAcceptEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatResurrectAcceptEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::MERCHANT_PURCHASE: {
|
|
||||||
PlayerEvent::MerchantPurchaseEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatMerchantPurchaseEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::MERCHANT_SELL: {
|
|
||||||
PlayerEvent::MerchantSellEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatMerchantSellEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlayerEvent::ZONING: {
|
|
||||||
PlayerEvent::ZoningEvent n{};
|
|
||||||
std::stringstream ss;
|
|
||||||
{
|
|
||||||
ss << e.player_event_log.event_data;
|
|
||||||
cereal::JSONInputArchive ar(ss);
|
|
||||||
n.serialize(ar);
|
|
||||||
}
|
|
||||||
|
|
||||||
payload = PlayerEventDiscordFormatter::FormatZoningEvent(e, n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
LogInfo(
|
|
||||||
"Player event [{}] ({}) Discord formatter not implemented",
|
|
||||||
e.player_event_log.event_type_name,
|
|
||||||
e.player_event_log.event_type_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
// general process function, used in world or QS depending on rule Logging:PlayerEventsQSProcess
|
|
||||||
void PlayerEventLogs::Process()
|
|
||||||
{
|
|
||||||
if (m_process_batch_events_timer.Check() || m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) {
|
|
||||||
ProcessBatchQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_process_retention_truncation_timer.Check()) {
|
|
||||||
ProcessRetentionTruncation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerEventLogs::ProcessRetentionTruncation()
|
|
||||||
{
|
|
||||||
LogInfo("Running truncation");
|
|
||||||
|
|
||||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
|
||||||
if (m_settings[i].retention_days > 0) {
|
|
||||||
int deleted_count = PlayerEventLogsRepository::DeleteWhere(
|
|
||||||
*m_database,
|
|
||||||
fmt::format(
|
|
||||||
"event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)",
|
|
||||||
i,
|
|
||||||
m_settings[i].retention_days
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (deleted_count > 0) {
|
|
||||||
LogInfo(
|
|
||||||
"Truncated [{}] events of type [{}] ({}) older than [{}] days",
|
|
||||||
deleted_count,
|
|
||||||
PlayerEvent::EventName[i],
|
|
||||||
i,
|
|
||||||
m_settings[i].retention_days
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerEventLogs::ReloadSettings()
|
|
||||||
{
|
|
||||||
for (auto &e: PlayerEventLogSettingsRepository::All(*m_database)) {
|
|
||||||
m_settings[e.id] = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const int32_t RETENTION_DAYS_DEFAULT = 7;
|
|
||||||
|
|
||||||
void PlayerEventLogs::SetSettingsDefaults()
|
|
||||||
{
|
|
||||||
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::ZONING].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::TRADE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::SAY].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::DEATH].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
|
|
||||||
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
|
|
||||||
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
|
|
||||||
|
|
||||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
|
||||||
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -1,971 +0,0 @@
|
|||||||
#ifndef EQEMU_PLAYER_EVENTS_H
|
|
||||||
#define EQEMU_PLAYER_EVENTS_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <cereal/cereal.hpp>
|
|
||||||
#include "../types.h"
|
|
||||||
#include "../repositories/player_event_logs_repository.h"
|
|
||||||
|
|
||||||
namespace PlayerEvent {
|
|
||||||
|
|
||||||
enum EventType {
|
|
||||||
GM_COMMAND = 1,
|
|
||||||
ZONING,
|
|
||||||
AA_GAIN,
|
|
||||||
AA_PURCHASE,
|
|
||||||
FORAGE_SUCCESS,
|
|
||||||
FORAGE_FAILURE,
|
|
||||||
FISH_SUCCESS,
|
|
||||||
FISH_FAILURE,
|
|
||||||
ITEM_DESTROY,
|
|
||||||
WENT_ONLINE,
|
|
||||||
WENT_OFFLINE,
|
|
||||||
LEVEL_GAIN,
|
|
||||||
LEVEL_LOSS,
|
|
||||||
LOOT_ITEM,
|
|
||||||
MERCHANT_PURCHASE,
|
|
||||||
MERCHANT_SELL,
|
|
||||||
GROUP_JOIN, // unimplemented
|
|
||||||
GROUP_LEAVE, // unimplemented
|
|
||||||
RAID_JOIN, // unimplemented
|
|
||||||
RAID_LEAVE, // unimplemented
|
|
||||||
GROUNDSPAWN_PICKUP,
|
|
||||||
NPC_HANDIN,
|
|
||||||
SKILL_UP,
|
|
||||||
TASK_ACCEPT,
|
|
||||||
TASK_UPDATE,
|
|
||||||
TASK_COMPLETE,
|
|
||||||
TRADE,
|
|
||||||
GIVE_ITEM, // unimplemented
|
|
||||||
SAY,
|
|
||||||
REZ_ACCEPTED,
|
|
||||||
DEATH,
|
|
||||||
COMBINE_FAILURE,
|
|
||||||
COMBINE_SUCCESS,
|
|
||||||
DROPPED_ITEM,
|
|
||||||
SPLIT_MONEY,
|
|
||||||
DZ_JOIN, // unimplemented
|
|
||||||
DZ_LEAVE, // unimplemented
|
|
||||||
TRADER_PURCHASE,
|
|
||||||
TRADER_SELL,
|
|
||||||
BANDOLIER_CREATE, // unimplemented
|
|
||||||
BANDOLIER_SWAP, // unimplemented
|
|
||||||
DISCOVER_ITEM,
|
|
||||||
POSSIBLE_HACK,
|
|
||||||
KILLED_NPC,
|
|
||||||
KILLED_NAMED_NPC,
|
|
||||||
KILLED_RAID_NPC,
|
|
||||||
ITEM_CREATION,
|
|
||||||
MAX // dont remove
|
|
||||||
};
|
|
||||||
|
|
||||||
// Don't ever remove items, even if they are deprecated
|
|
||||||
// If event is deprecated just tag (Deprecated) in the name
|
|
||||||
// If event is unimplemented just tag (Unimplemented) in the name
|
|
||||||
// Events don't get saved to the database if unimplemented or deprecated
|
|
||||||
// Events tagged as deprecated will get automatically removed
|
|
||||||
static const char *EventName[PlayerEvent::MAX] = {
|
|
||||||
"None",
|
|
||||||
"GM Command",
|
|
||||||
"Zoning",
|
|
||||||
"AA Gain",
|
|
||||||
"AA Purchase",
|
|
||||||
"Forage Success",
|
|
||||||
"Forage Failure",
|
|
||||||
"Fish Success",
|
|
||||||
"Fish Failure",
|
|
||||||
"Item Destroy",
|
|
||||||
"Went Online",
|
|
||||||
"Went Offline",
|
|
||||||
"Level Gain",
|
|
||||||
"Level Loss",
|
|
||||||
"Loot Item",
|
|
||||||
"Merchant Purchase",
|
|
||||||
"Merchant Sell",
|
|
||||||
"Group Join (Unimplemented)",
|
|
||||||
"Group Leave (Unimplemented)",
|
|
||||||
"Raid Join (Unimplemented)",
|
|
||||||
"Raid Leave (Unimplemented)",
|
|
||||||
"Groundspawn Pickup",
|
|
||||||
"NPC Handin",
|
|
||||||
"Skill Up",
|
|
||||||
"Task Accept",
|
|
||||||
"Task Update",
|
|
||||||
"Task Complete",
|
|
||||||
"Trade",
|
|
||||||
"Given Item (Unimplemented)",
|
|
||||||
"Say",
|
|
||||||
"Rez Accepted",
|
|
||||||
"Death",
|
|
||||||
"Combine Failure",
|
|
||||||
"Combine Success",
|
|
||||||
"Dropped Item",
|
|
||||||
"Split Money",
|
|
||||||
"DZ Join (Unimplemented)",
|
|
||||||
"DZ Leave (Unimplemented)",
|
|
||||||
"Trader Purchase",
|
|
||||||
"Trader Sell",
|
|
||||||
"Bandolier Create (Unimplemented)",
|
|
||||||
"Bandolier Swap (Unimplemented)",
|
|
||||||
"Discover Item",
|
|
||||||
"Possible Hack",
|
|
||||||
"Killed NPC",
|
|
||||||
"Killed Named NPC",
|
|
||||||
"Killed Raid NPC",
|
|
||||||
"Item Creation"
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generic struct used by all events
|
|
||||||
struct PlayerEvent {
|
|
||||||
int64 account_id;
|
|
||||||
std::string account_name;
|
|
||||||
int64 character_id;
|
|
||||||
std::string character_name;
|
|
||||||
int64 guild_id;
|
|
||||||
std::string guild_name;
|
|
||||||
int zone_id;
|
|
||||||
std::string zone_short_name;
|
|
||||||
std::string zone_long_name;
|
|
||||||
int instance_id;
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
float heading;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(account_id),
|
|
||||||
CEREAL_NVP(account_name),
|
|
||||||
CEREAL_NVP(character_id),
|
|
||||||
CEREAL_NVP(character_name),
|
|
||||||
CEREAL_NVP(guild_id),
|
|
||||||
CEREAL_NVP(guild_name),
|
|
||||||
CEREAL_NVP(zone_id),
|
|
||||||
CEREAL_NVP(zone_short_name),
|
|
||||||
CEREAL_NVP(zone_long_name),
|
|
||||||
CEREAL_NVP(instance_id),
|
|
||||||
CEREAL_NVP(x),
|
|
||||||
CEREAL_NVP(y),
|
|
||||||
CEREAL_NVP(z),
|
|
||||||
CEREAL_NVP(heading)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// contains metadata in use for things like log/discord formatters
|
|
||||||
// along with the actual event to be persisted
|
|
||||||
struct PlayerEventContainer {
|
|
||||||
PlayerEvent player_event;
|
|
||||||
PlayerEventLogsRepository::PlayerEventLogs player_event_log;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(player_event),
|
|
||||||
CEREAL_NVP(player_event_log)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// used in events with no extra data
|
|
||||||
struct EmptyEvent {
|
|
||||||
std::string noop; // noop, gets discard upstream
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(noop)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// used in Trade event
|
|
||||||
struct ItemCreationEvent {
|
|
||||||
int64 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
uint16 to_slot;
|
|
||||||
int16 charges;
|
|
||||||
uint32 aug1;
|
|
||||||
uint32 aug2;
|
|
||||||
uint32 aug3;
|
|
||||||
uint32 aug4;
|
|
||||||
uint32 aug5;
|
|
||||||
uint32 aug6;
|
|
||||||
bool attuned;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(to_slot),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(aug1),
|
|
||||||
CEREAL_NVP(aug2),
|
|
||||||
CEREAL_NVP(aug3),
|
|
||||||
CEREAL_NVP(aug4),
|
|
||||||
CEREAL_NVP(aug5),
|
|
||||||
CEREAL_NVP(aug6),
|
|
||||||
CEREAL_NVP(attuned)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// used in Trade event
|
|
||||||
struct TradeItem {
|
|
||||||
int64 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
int32 slot;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(slot)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// used in Trade event
|
|
||||||
class TradeItemEntry {
|
|
||||||
public:
|
|
||||||
uint16 slot;
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
uint16 charges;
|
|
||||||
uint32 aug_1_item_id;
|
|
||||||
std::string aug_1_item_name;
|
|
||||||
uint32 aug_2_item_id;
|
|
||||||
std::string aug_2_item_name;
|
|
||||||
uint32 aug_3_item_id;
|
|
||||||
std::string aug_3_item_name;
|
|
||||||
uint32 aug_4_item_id;
|
|
||||||
std::string aug_4_item_name;
|
|
||||||
uint32 aug_5_item_id;
|
|
||||||
std::string aug_5_item_name;
|
|
||||||
uint32 aug_6_item_id;
|
|
||||||
std::string aug_6_item_name;
|
|
||||||
bool in_bag;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(slot),
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(aug_1_item_id),
|
|
||||||
CEREAL_NVP(aug_2_item_id),
|
|
||||||
CEREAL_NVP(aug_3_item_id),
|
|
||||||
CEREAL_NVP(aug_4_item_id),
|
|
||||||
CEREAL_NVP(aug_5_item_id),
|
|
||||||
CEREAL_NVP(in_bag)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Events
|
|
||||||
*/
|
|
||||||
struct Money {
|
|
||||||
int32 platinum;
|
|
||||||
int32 gold;
|
|
||||||
int32 silver;
|
|
||||||
int32 copper;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(platinum),
|
|
||||||
CEREAL_NVP(gold),
|
|
||||||
CEREAL_NVP(silver),
|
|
||||||
CEREAL_NVP(copper)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TradeEvent {
|
|
||||||
uint32 character_1_id;
|
|
||||||
std::string character_1_name;
|
|
||||||
uint32 character_2_id;
|
|
||||||
std::string character_2_name;
|
|
||||||
Money character_1_give_money;
|
|
||||||
Money character_2_give_money;
|
|
||||||
std::vector<TradeItemEntry> character_1_give_items;
|
|
||||||
std::vector<TradeItemEntry> character_2_give_items;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(character_1_id),
|
|
||||||
CEREAL_NVP(character_1_name),
|
|
||||||
CEREAL_NVP(character_2_id),
|
|
||||||
CEREAL_NVP(character_2_name),
|
|
||||||
CEREAL_NVP(character_1_give_money),
|
|
||||||
CEREAL_NVP(character_2_give_money),
|
|
||||||
CEREAL_NVP(character_1_give_items),
|
|
||||||
CEREAL_NVP(character_2_give_items)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GMCommandEvent {
|
|
||||||
std::string message;
|
|
||||||
std::string target;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(message),
|
|
||||||
CEREAL_NVP(target)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ZoningEvent {
|
|
||||||
std::string from_zone_long_name;
|
|
||||||
std::string from_zone_short_name;
|
|
||||||
int32 from_zone_id;
|
|
||||||
int32 from_instance_id;
|
|
||||||
int32 from_instance_version;
|
|
||||||
std::string to_zone_long_name;
|
|
||||||
std::string to_zone_short_name;
|
|
||||||
int32 to_zone_id;
|
|
||||||
int32 to_instance_id;
|
|
||||||
int32 to_instance_version;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(from_zone_long_name),
|
|
||||||
CEREAL_NVP(from_zone_short_name),
|
|
||||||
CEREAL_NVP(from_zone_id),
|
|
||||||
CEREAL_NVP(from_instance_id),
|
|
||||||
CEREAL_NVP(from_instance_version),
|
|
||||||
CEREAL_NVP(to_zone_long_name),
|
|
||||||
CEREAL_NVP(to_zone_short_name),
|
|
||||||
CEREAL_NVP(to_zone_id),
|
|
||||||
CEREAL_NVP(to_instance_id),
|
|
||||||
CEREAL_NVP(to_instance_version)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AAGainedEvent {
|
|
||||||
uint32 aa_gained;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(CEREAL_NVP(aa_gained));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AAPurchasedEvent {
|
|
||||||
uint32 aa_id;
|
|
||||||
int32 aa_cost;
|
|
||||||
int32 aa_previous_id;
|
|
||||||
int32 aa_next_id;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(aa_id),
|
|
||||||
CEREAL_NVP(aa_cost),
|
|
||||||
CEREAL_NVP(aa_previous_id),
|
|
||||||
CEREAL_NVP(aa_next_id)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ForageSuccessEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FishSuccessEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DestroyItemEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
int16 charges;
|
|
||||||
std::string reason;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(reason),
|
|
||||||
CEREAL_NVP(charges)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LevelGainedEvent {
|
|
||||||
uint32 from_level;
|
|
||||||
uint8 to_level;
|
|
||||||
int levels_gained;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(from_level),
|
|
||||||
CEREAL_NVP(to_level),
|
|
||||||
CEREAL_NVP(levels_gained)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LevelLostEvent {
|
|
||||||
uint32 from_level;
|
|
||||||
uint8 to_level;
|
|
||||||
int levels_lost;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(from_level),
|
|
||||||
CEREAL_NVP(to_level),
|
|
||||||
CEREAL_NVP(levels_lost)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LootItemEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
int16 charges;
|
|
||||||
uint32 npc_id;
|
|
||||||
std::string corpse_name;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(npc_id),
|
|
||||||
CEREAL_NVP(corpse_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MerchantPurchaseEvent {
|
|
||||||
uint32 npc_id;
|
|
||||||
std::string merchant_name;
|
|
||||||
uint32 merchant_type;
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
int16 charges;
|
|
||||||
uint32 cost;
|
|
||||||
uint32 alternate_currency_id;
|
|
||||||
uint64 player_money_balance;
|
|
||||||
uint64 player_currency_balance;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(npc_id),
|
|
||||||
CEREAL_NVP(merchant_name),
|
|
||||||
CEREAL_NVP(merchant_type),
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(cost),
|
|
||||||
CEREAL_NVP(alternate_currency_id),
|
|
||||||
CEREAL_NVP(player_money_balance),
|
|
||||||
CEREAL_NVP(player_currency_balance)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MerchantSellEvent {
|
|
||||||
uint32 npc_id;
|
|
||||||
std::string merchant_name;
|
|
||||||
uint32 merchant_type;
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
int16 charges;
|
|
||||||
uint32 cost;
|
|
||||||
uint32 alternate_currency_id;
|
|
||||||
uint64 player_money_balance;
|
|
||||||
uint64 player_currency_balance;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(npc_id),
|
|
||||||
CEREAL_NVP(merchant_name),
|
|
||||||
CEREAL_NVP(merchant_type),
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(cost),
|
|
||||||
CEREAL_NVP(alternate_currency_id),
|
|
||||||
CEREAL_NVP(player_money_balance),
|
|
||||||
CEREAL_NVP(player_currency_balance)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SkillUpEvent {
|
|
||||||
uint32 skill_id;
|
|
||||||
int value;
|
|
||||||
int16 max_skill;
|
|
||||||
std::string against_who;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(skill_id),
|
|
||||||
CEREAL_NVP(value),
|
|
||||||
CEREAL_NVP(max_skill),
|
|
||||||
CEREAL_NVP(against_who)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TaskAcceptEvent {
|
|
||||||
uint32 npc_id;
|
|
||||||
std::string npc_name;
|
|
||||||
uint32 task_id;
|
|
||||||
std::string task_name;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(npc_id),
|
|
||||||
CEREAL_NVP(npc_name),
|
|
||||||
CEREAL_NVP(task_id),
|
|
||||||
CEREAL_NVP(task_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TaskUpdateEvent {
|
|
||||||
uint32 task_id;
|
|
||||||
std::string task_name;
|
|
||||||
uint32 activity_id;
|
|
||||||
uint32 done_count;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(task_id),
|
|
||||||
CEREAL_NVP(task_name),
|
|
||||||
CEREAL_NVP(activity_id),
|
|
||||||
CEREAL_NVP(done_count)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TaskCompleteEvent {
|
|
||||||
uint32 task_id;
|
|
||||||
std::string task_name;
|
|
||||||
uint32 activity_id;
|
|
||||||
uint32 done_count;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(task_id),
|
|
||||||
CEREAL_NVP(task_name),
|
|
||||||
CEREAL_NVP(activity_id),
|
|
||||||
CEREAL_NVP(done_count)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GroundSpawnPickupEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SayEvent {
|
|
||||||
std::string message;
|
|
||||||
std::string target;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(message),
|
|
||||||
CEREAL_NVP(target)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ResurrectAcceptEvent {
|
|
||||||
std::string resurrecter_name;
|
|
||||||
std::string spell_name;
|
|
||||||
uint32 spell_id;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(resurrecter_name),
|
|
||||||
CEREAL_NVP(spell_name),
|
|
||||||
CEREAL_NVP(spell_id)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CombineEvent {
|
|
||||||
uint32 recipe_id;
|
|
||||||
std::string recipe_name;
|
|
||||||
uint32 made_count;
|
|
||||||
uint32 tradeskill_id;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(recipe_id),
|
|
||||||
CEREAL_NVP(recipe_name),
|
|
||||||
CEREAL_NVP(made_count),
|
|
||||||
CEREAL_NVP(tradeskill_id)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DroppedItemEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
int16 slot_id;
|
|
||||||
uint32 charges;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(slot_id),
|
|
||||||
CEREAL_NVP(charges)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DeathEvent {
|
|
||||||
uint32 killer_id;
|
|
||||||
std::string killer_name;
|
|
||||||
int64 damage;
|
|
||||||
uint32 spell_id;
|
|
||||||
std::string spell_name;
|
|
||||||
int skill_id;
|
|
||||||
std::string skill_name;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(killer_id),
|
|
||||||
CEREAL_NVP(killer_name),
|
|
||||||
CEREAL_NVP(damage),
|
|
||||||
CEREAL_NVP(spell_id),
|
|
||||||
CEREAL_NVP(spell_name),
|
|
||||||
CEREAL_NVP(skill_id),
|
|
||||||
CEREAL_NVP(skill_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SplitMoneyEvent {
|
|
||||||
uint32 copper;
|
|
||||||
uint32 silver;
|
|
||||||
uint32 gold;
|
|
||||||
uint32 platinum;
|
|
||||||
uint64 player_money_balance;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(copper),
|
|
||||||
CEREAL_NVP(silver),
|
|
||||||
CEREAL_NVP(gold),
|
|
||||||
CEREAL_NVP(platinum),
|
|
||||||
CEREAL_NVP(player_money_balance)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TraderPurchaseEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
uint32 trader_id;
|
|
||||||
std::string trader_name;
|
|
||||||
uint32 price;
|
|
||||||
uint32 charges;
|
|
||||||
uint32 total_cost;
|
|
||||||
uint64 player_money_balance;
|
|
||||||
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(trader_id),
|
|
||||||
CEREAL_NVP(trader_name),
|
|
||||||
CEREAL_NVP(price),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(total_cost),
|
|
||||||
CEREAL_NVP(player_money_balance)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TraderSellEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
uint32 buyer_id;
|
|
||||||
std::string buyer_name;
|
|
||||||
uint32 price;
|
|
||||||
uint32 charges;
|
|
||||||
uint32 total_cost;
|
|
||||||
uint64 player_money_balance;
|
|
||||||
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(buyer_id),
|
|
||||||
CEREAL_NVP(buyer_name),
|
|
||||||
CEREAL_NVP(price),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(total_cost),
|
|
||||||
CEREAL_NVP(player_money_balance)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DiscoverItemEvent {
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class HandinEntry {
|
|
||||||
public:
|
|
||||||
uint32 item_id;
|
|
||||||
std::string item_name;
|
|
||||||
uint16 charges;
|
|
||||||
bool attuned;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(item_id),
|
|
||||||
CEREAL_NVP(item_name),
|
|
||||||
CEREAL_NVP(charges),
|
|
||||||
CEREAL_NVP(attuned)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class HandinMoney {
|
|
||||||
public:
|
|
||||||
uint32 copper;
|
|
||||||
uint32 silver;
|
|
||||||
uint32 gold;
|
|
||||||
uint32 platinum;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(copper),
|
|
||||||
CEREAL_NVP(silver),
|
|
||||||
CEREAL_NVP(gold),
|
|
||||||
CEREAL_NVP(platinum)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HandinEvent {
|
|
||||||
uint32 npc_id;
|
|
||||||
std::string npc_name;
|
|
||||||
std::vector<HandinEntry> handin_items;
|
|
||||||
HandinMoney handin_money;
|
|
||||||
std::vector<HandinEntry> return_items;
|
|
||||||
HandinMoney return_money;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(npc_id),
|
|
||||||
CEREAL_NVP(npc_name),
|
|
||||||
CEREAL_NVP(handin_items),
|
|
||||||
CEREAL_NVP(handin_money),
|
|
||||||
CEREAL_NVP(return_items),
|
|
||||||
CEREAL_NVP(return_money)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PossibleHackEvent {
|
|
||||||
std::string message;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KilledNPCEvent {
|
|
||||||
uint32 npc_id;
|
|
||||||
std::string npc_name;
|
|
||||||
uint32 combat_time_seconds;
|
|
||||||
uint64 total_damage_per_second_taken;
|
|
||||||
uint64 total_heal_per_second_taken;
|
|
||||||
|
|
||||||
// cereal
|
|
||||||
template<class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(
|
|
||||||
CEREAL_NVP(npc_id),
|
|
||||||
CEREAL_NVP(npc_name),
|
|
||||||
CEREAL_NVP(combat_time_seconds),
|
|
||||||
CEREAL_NVP(total_damage_per_second_taken),
|
|
||||||
CEREAL_NVP(total_heal_per_second_taken)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //EQEMU_PLAYER_EVENTS_H
|
|
||||||
|
|
||||||
#define RecordPlayerEventLog(event_type, event_data) do {\
|
|
||||||
if (player_event_logs.IsEventEnabled(event_type)) {\
|
|
||||||
worldserver.SendPacket(\
|
|
||||||
player_event_logs.RecordEvent(\
|
|
||||||
event_type,\
|
|
||||||
GetPlayerEvent(),\
|
|
||||||
event_data\
|
|
||||||
).get()\
|
|
||||||
);\
|
|
||||||
}\
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\
|
|
||||||
if (player_event_logs.IsEventEnabled(event_type)) {\
|
|
||||||
worldserver.SendPacket(\
|
|
||||||
player_event_logs.RecordEvent(\
|
|
||||||
event_type,\
|
|
||||||
(c)->GetPlayerEvent(),\
|
|
||||||
event_data\
|
|
||||||
).get()\
|
|
||||||
);\
|
|
||||||
}\
|
|
||||||
} while (0)
|
|
||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+33
-17
@@ -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,
|
||||||
@@ -218,14 +218,14 @@ enum { //some random constants
|
|||||||
#define HARD_LEVEL_CAP 127
|
#define HARD_LEVEL_CAP 127
|
||||||
|
|
||||||
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
|
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
|
||||||
#define USE_NPC_RANGE2 40000 //arbitrary right now
|
#define USE_NPC_RANGE2 200*200 //arbitrary right now
|
||||||
|
|
||||||
// Squared range for rampage 75.0 * 75.0 for now
|
// Squared range for rampage 75.0 * 75.0 for now
|
||||||
#define NPC_RAMPAGE_RANGE2 5625.0f
|
#define NPC_RAMPAGE_RANGE2 5625.0f
|
||||||
|
|
||||||
//the formula for experience for killing a mob.
|
//the formula for experience for killing a mob.
|
||||||
//level is the only valid variable to use
|
//level is the only valid variable to use
|
||||||
#define EXP_FORMULA (level * level * 75 * 35 / 10)
|
#define EXP_FORMULA level*level*75*35/10
|
||||||
|
|
||||||
#define HIGHEST_AA_VALUE 35
|
#define HIGHEST_AA_VALUE 35
|
||||||
|
|
||||||
@@ -240,20 +240,36 @@ enum { //some random constants
|
|||||||
|
|
||||||
//Some hard coded statuses from commands and other places:
|
//Some hard coded statuses from commands and other places:
|
||||||
enum {
|
enum {
|
||||||
minStatusToBeGM = 40,
|
minStatusToBeGM = 40,
|
||||||
minStatusToUseGMCommands = 80,
|
minStatusToUseGMCommands = 80,
|
||||||
minStatusToKick = 150,
|
minStatusToKick = 150,
|
||||||
minStatusToAvoidFalling = 100,
|
minStatusToAvoidFalling = 100,
|
||||||
minStatusToIgnoreZoneFlags = 80,
|
minStatusToHaveInvalidSpells = 80,
|
||||||
|
minStatusToHaveInvalidSkills = 80,
|
||||||
|
minStatusToIgnoreZoneFlags = 80,
|
||||||
minStatusToSeeOthersZoneFlags = 80,
|
minStatusToSeeOthersZoneFlags = 80,
|
||||||
minStatusToEditOtherGuilds = 80,
|
minStatusToEditOtherGuilds = 80,
|
||||||
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
||||||
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
||||||
commandCastSpecials = 100, //can cast special spells
|
commandZoneToSpecials = 80, //zone to cshome, out of load zones
|
||||||
commandDoAnimOthers = 100, //can #doanim on others
|
commandToggleAI = 250, //can turn NPC AI on and off
|
||||||
commandEditPlayerCorpses = 150, //can Edit Player Corpses
|
commandCastSpecials = 100, //can cast special spells
|
||||||
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
|
commandInstacast = 100, //insta-cast all #casted spells
|
||||||
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
commandLevelAboveCap = 100, //can #level players above level cap
|
||||||
|
commandLevelNPCAboveCap = 100, //can #level NPCs above level cap
|
||||||
|
commandSetSkillsOther = 100, //ability to setskills on others
|
||||||
|
commandRaceOthers = 100, //ability to #race on others
|
||||||
|
commandGenderOthers = 100, //ability to #gender on others
|
||||||
|
commandTextureOthers = 100, //ability to #texture on others
|
||||||
|
commandDoAnimOthers = 100, //can #doanim on others
|
||||||
|
commandLockZones = 101, //can lock or unlock zones
|
||||||
|
commandEditPlayerCorpses = 150, //can Edit Player Corpses
|
||||||
|
commandChangeFlags = 200, //ability to set/refresh flags
|
||||||
|
commandBanPlayers = 100, //can set bans on players
|
||||||
|
commandChangeDatarate = 201, //edit client's data rate
|
||||||
|
commandZoneToCoords = 0, //can #zone with coords
|
||||||
|
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
|
||||||
|
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -279,7 +295,7 @@ Developer configuration
|
|||||||
|
|
||||||
#define COMMON_PROFILE
|
#define COMMON_PROFILE
|
||||||
|
|
||||||
#define PROFILE_DUMP_TIME 180
|
#define PROFILE_DUMP_TIME 3*60
|
||||||
#endif //EQPROFILE
|
#endif //EQPROFILE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
-112
@@ -1,112 +0,0 @@
|
|||||||
/**
|
|
||||||
* EQEmulator: Everquest Server Emulator
|
|
||||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; version 2 of the License.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
||||||
* are required to give you total support for your newly bought product;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include "file.h"
|
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
|
||||||
#include <direct.h>
|
|
||||||
#include <conio.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <dos.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <process.h>
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool File::Exists(const std::string &name)
|
|
||||||
{
|
|
||||||
return fs::exists(fs::path{name});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param directory_name
|
|
||||||
*/
|
|
||||||
void File::Makedir(const std::string &directory_name)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
fs::create_directory(directory_name);
|
|
||||||
fs::permissions(directory_name, fs::perms::owner_all);
|
|
||||||
}
|
|
||||||
catch (const fs::filesystem_error &ex) {
|
|
||||||
std::cout << "Failed to create directory: " << directory_name << std::endl;
|
|
||||||
std::cout << ex.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string File::FindEqemuConfigPath()
|
|
||||||
{
|
|
||||||
if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) {
|
|
||||||
return File::GetCwd();
|
|
||||||
}
|
|
||||||
else if (File::Exists(fs::path{File::GetCwd() + "/../eqemu_config.json"}.string())) {
|
|
||||||
return canonical(fs::path{File::GetCwd() + "/../"}).string();
|
|
||||||
}
|
|
||||||
else if (File::Exists(fs::path{File::GetCwd() + "/login.json"}.string())) {
|
|
||||||
return File::GetCwd();
|
|
||||||
}
|
|
||||||
else if (File::Exists(fs::path{File::GetCwd() + "/../login.json"}.string())) {
|
|
||||||
return canonical(fs::path{File::GetCwd() + "/../"}).string();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string File::GetCwd()
|
|
||||||
{
|
|
||||||
return fs::current_path().string();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileContentsResult File::GetContents(const std::string &file_name)
|
|
||||||
{
|
|
||||||
std::string error;
|
|
||||||
std::ifstream f;
|
|
||||||
f.open(file_name);
|
|
||||||
std::string line;
|
|
||||||
std::string lines;
|
|
||||||
if (f.is_open()) {
|
|
||||||
while (f) {
|
|
||||||
std::getline(f, line);
|
|
||||||
lines += line + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
error = fmt::format("Couldn't open file [{}]", file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FileContentsResult{
|
|
||||||
.contents = lines,
|
|
||||||
.error = error,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include "file_util.h"
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#include <direct.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <process.h>
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool FileUtil::exists(const std::string &name)
|
||||||
|
{
|
||||||
|
std::ifstream f(name.c_str());
|
||||||
|
|
||||||
|
return f.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param directory_name
|
||||||
|
*/
|
||||||
|
void FileUtil::mkdir(const std::string& directory_name)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
struct _stat st;
|
||||||
|
if (_stat(directory_name.c_str(), &st) == 0) // exists
|
||||||
|
return;
|
||||||
|
_mkdir(directory_name.c_str());
|
||||||
|
#else
|
||||||
|
struct stat st{};
|
||||||
|
if (stat(directory_name.c_str(), &st) == 0) { // exists
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
::mkdir(directory_name.c_str(), 0755);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool file_exists(const std::string& name) {
|
||||||
|
std::ifstream f(name.c_str());
|
||||||
|
return f.good();
|
||||||
|
}
|
||||||
@@ -18,27 +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 {
|
||||||
|
|
||||||
struct FileContentsResult {
|
|
||||||
std::string contents;
|
|
||||||
std::string error;
|
|
||||||
};
|
|
||||||
|
|
||||||
class File {
|
|
||||||
public:
|
public:
|
||||||
static bool Exists(const std::string &name);
|
static bool exists(const std::string &name);
|
||||||
static void Makedir(const std::string& directory_name);
|
static void mkdir(const std::string& directory_name);
|
||||||
static FileContentsResult GetContents(const std::string &file_name);
|
|
||||||
static std::string FindEqemuConfigPath();
|
|
||||||
static std::string GetCwd();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Exists(const std::string& name);
|
bool file_exists(const std::string& name);
|
||||||
|
|
||||||
#endif //EQEMU_FILE_H
|
#endif //EQEMU_FILE_UTIL_H
|
||||||
+39
-23
@@ -20,7 +20,7 @@
|
|||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
|
||||||
//#include "misc_functions.h"
|
//#include "misc_functions.h"
|
||||||
#include "strings.h"
|
#include "string_util.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@@ -61,11 +61,9 @@ bool BaseGuildManager::LoadGuilds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto row=results.begin();row!=results.end();++row)
|
for (auto row=results.begin();row!=results.end();++row)
|
||||||
_CreateGuild(Strings::ToUnsignedInt(row[0]), row[1], Strings::ToUnsignedInt(row[2]), Strings::ToUnsignedInt(row[3]), row[4], row[5], row[6], row[7]);
|
_CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]);
|
||||||
|
|
||||||
LogInfo("Loaded [{}] Guilds", Strings::Commify(std::to_string(results.RowCount())));
|
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
|
||||||
|
|
||||||
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
|
|
||||||
results = m_db->QueryDatabase(query);
|
results = m_db->QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
@@ -75,8 +73,8 @@ bool BaseGuildManager::LoadGuilds() {
|
|||||||
|
|
||||||
for (auto row=results.begin();row!=results.end();++row)
|
for (auto row=results.begin();row!=results.end();++row)
|
||||||
{
|
{
|
||||||
uint32 guild_id = Strings::ToUnsignedInt(row[0]);
|
uint32 guild_id = atoi(row[0]);
|
||||||
uint8 rankn = Strings::ToUnsignedInt(row[1]);
|
uint8 rankn = atoi(row[1]);
|
||||||
|
|
||||||
if(rankn > GUILD_MAX_RANK) {
|
if(rankn > GUILD_MAX_RANK) {
|
||||||
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
|
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
|
||||||
@@ -131,7 +129,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
|||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
|
|
||||||
info = _CreateGuild(guild_id, row[0], Strings::ToUnsignedInt(row[1]), Strings::ToUnsignedInt(row[2]), row[3], row[4], row[5], row[6]);
|
info = _CreateGuild(guild_id, row[0], atoi(row[1]), atoi(row[2]), row[3], row[4], row[5], row[6]);
|
||||||
|
|
||||||
query = StringFormat("SELECT guild_id, `rank`, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
|
query = StringFormat("SELECT guild_id, `rank`, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
|
||||||
"FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id);
|
"FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id);
|
||||||
@@ -144,7 +142,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
|||||||
|
|
||||||
for (auto row=results.begin();row!=results.end();++row)
|
for (auto row=results.begin();row!=results.end();++row)
|
||||||
{
|
{
|
||||||
uint8 rankn = Strings::ToUnsignedInt(row[1]);
|
uint8 rankn = atoi(row[1]);
|
||||||
|
|
||||||
if(rankn > GUILD_MAX_RANK) {
|
if(rankn > GUILD_MAX_RANK) {
|
||||||
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
|
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
|
||||||
@@ -787,7 +785,9 @@ bool BaseGuildManager::GetBankerFlag(uint32 CharID)
|
|||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
|
|
||||||
return Strings::ToBool(row[0]);
|
bool IsBanker = atoi(row[0]);
|
||||||
|
|
||||||
|
return IsBanker;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseGuildManager::DBSetAltFlag(uint32 charid, bool is_alt)
|
bool BaseGuildManager::DBSetAltFlag(uint32 charid, bool is_alt)
|
||||||
@@ -815,7 +815,9 @@ bool BaseGuildManager::GetAltFlag(uint32 CharID)
|
|||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
|
|
||||||
return Strings::ToBool(row[0]);
|
bool IsAlt = atoi(row[0]);
|
||||||
|
|
||||||
|
return IsAlt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseGuildManager::DBSetTributeFlag(uint32 charid, bool enabled) {
|
bool BaseGuildManager::DBSetTributeFlag(uint32 charid, bool enabled) {
|
||||||
@@ -862,26 +864,35 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//factored out so I dont have to copy this crap.
|
||||||
|
#ifdef BOTS
|
||||||
|
#define GuildMemberBaseQuery \
|
||||||
|
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
|
||||||
|
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
|
||||||
|
" g.`banker`, g.`public_note`, g.`alt`" \
|
||||||
|
" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` "
|
||||||
|
#else
|
||||||
#define GuildMemberBaseQuery \
|
#define GuildMemberBaseQuery \
|
||||||
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
|
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
|
||||||
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
|
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
|
||||||
" g.`banker`, g.`public_note`, g.`alt` " \
|
" g.`banker`, g.`public_note`, g.`alt` " \
|
||||||
" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` "
|
" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` "
|
||||||
|
#endif
|
||||||
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
|
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
|
||||||
//fields from `characer_`
|
//fields from `characer_`
|
||||||
into.char_id = Strings::ToUnsignedInt(row[0]);
|
into.char_id = atoi(row[0]);
|
||||||
into.char_name = row[1];
|
into.char_name = row[1];
|
||||||
into.class_ = Strings::ToUnsignedInt(row[2]);
|
into.class_ = atoi(row[2]);
|
||||||
into.level = Strings::ToUnsignedInt(row[3]);
|
into.level = atoi(row[3]);
|
||||||
into.time_last_on = Strings::ToUnsignedInt(row[4]);
|
into.time_last_on = atoul(row[4]);
|
||||||
into.zone_id = Strings::ToUnsignedInt(row[5]);
|
into.zone_id = atoi(row[5]);
|
||||||
|
|
||||||
//fields from `guild_members`, leave at defaults if missing
|
//fields from `guild_members`, leave at defaults if missing
|
||||||
into.guild_id = row[6] ? Strings::ToUnsignedInt(row[6]) : GUILD_NONE;
|
into.guild_id = row[6] ? atoi(row[6]) : GUILD_NONE;
|
||||||
into.rank = row[7] ? Strings::ToUnsignedInt(row[7]) : (GUILD_MAX_RANK+1);
|
into.rank = row[7] ? atoi(row[7]) : (GUILD_MAX_RANK+1);
|
||||||
into.tribute_enable = row[8] ? (row[8][0] == '0'?false:true) : false;
|
into.tribute_enable = row[8] ? (row[8][0] == '0'?false:true) : false;
|
||||||
into.total_tribute = row[9] ? Strings::ToUnsignedInt(row[9]) : 0;
|
into.total_tribute = row[9] ? atoi(row[9]) : 0;
|
||||||
into.last_tribute = row[10]? Strings::ToUnsignedInt(row[10]) : 0; //timestamp
|
into.last_tribute = row[10]? atoul(row[10]) : 0; //timestamp
|
||||||
into.banker = row[11]? (row[11][0] == '0'?false:true) : false;
|
into.banker = row[11]? (row[11][0] == '0'?false:true) : false;
|
||||||
into.public_note = row[12]? row[12] : "";
|
into.public_note = row[12]? row[12] : "";
|
||||||
into.alt = row[13]? (row[13][0] == '0'?false:true) : false;
|
into.alt = row[13]? (row[13][0] == '0'?false:true) : false;
|
||||||
@@ -956,8 +967,13 @@ 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;
|
||||||
auto results = m_db->QueryDatabase(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);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1254,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2119
-2844
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@
|
|||||||
//#include "races.h"
|
//#include "races.h"
|
||||||
//#include "rulesys.h"
|
//#include "rulesys.h"
|
||||||
//#include "shareddb.h"
|
//#include "shareddb.h"
|
||||||
#include "strings.h"
|
#include "string_util.h"
|
||||||
|
|
||||||
#include "../common/light_source.h"
|
#include "../common/light_source.h"
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
fail_state = swapRaceClass;
|
fail_state = swapRaceClass;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (deity_id && source_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & source_item->Deity)) {
|
if (deity_id && source_item->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & source_item->Deity)) {
|
||||||
fail_state = swapDeity;
|
fail_state = swapDeity;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -379,7 +379,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
fail_state = swapRaceClass;
|
fail_state = swapRaceClass;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (deity_id && destination_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & destination_item->Deity)) {
|
if (deity_id && destination_item->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & destination_item->Deity)) {
|
||||||
fail_state = swapDeity;
|
fail_state = swapDeity;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -412,12 +412,11 @@ bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
|
|||||||
// If there are no charges left on the item,
|
// If there are no charges left on the item,
|
||||||
if (item_to_delete->GetCharges() <= 0) {
|
if (item_to_delete->GetCharges() <= 0) {
|
||||||
// If the item is stackable (e.g arrows), or
|
// If the item is stackable (e.g arrows), or
|
||||||
// the item is not a charged item, or is expendable, delete it
|
// the item is not stackable, and is not a charged item, or is expendable, delete it
|
||||||
if (
|
if (item_to_delete->IsStackable() ||
|
||||||
item_to_delete->IsStackable() ||
|
(!item_to_delete->IsStackable() &&
|
||||||
item_to_delete->GetItem()->MaxCharges == 0 ||
|
((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable()))
|
||||||
item_to_delete->IsExpendable()
|
) {
|
||||||
) {
|
|
||||||
// Item can now be destroyed
|
// Item can now be destroyed
|
||||||
InventoryProfile::MarkDirty(item_to_delete);
|
InventoryProfile::MarkDirty(item_to_delete);
|
||||||
return true;
|
return true;
|
||||||
@@ -1444,7 +1443,7 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == INVALID_INDEX) {
|
if (result == INVALID_INDEX) {
|
||||||
LogError("Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
|
LogError("InventoryProfile::_PutItem: Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
|
||||||
InventoryProfile::MarkDirty(inst); // Slot not found, clean up
|
InventoryProfile::MarkDirty(inst); // Slot not found, clean up
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1719,17 +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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
@@ -203,12 +197,12 @@ namespace EQ
|
|||||||
void dumpBankItems();
|
void dumpBankItems();
|
||||||
void dumpSharedBankItems();
|
void dumpSharedBankItems();
|
||||||
|
|
||||||
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, const std::string& value);
|
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value);
|
||||||
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, int value);
|
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value);
|
||||||
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, float value);
|
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value);
|
||||||
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, bool value);
|
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value);
|
||||||
std::string GetCustomItemData(int16 slot_id, const std::string& identifier);
|
std::string GetCustomItemData(int16 slot_id, std::string identifier);
|
||||||
static const int GetItemStatValue(uint32 item_id, const std::string& identifier);
|
static int GetItemStatValue(uint32 item_id, const char* identifier);
|
||||||
protected:
|
protected:
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Protected Methods
|
// Protected Methods
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -37,7 +37,7 @@ namespace EQ {
|
|||||||
Creates a named binary semaphore, basically a semaphore that is init S <- 1
|
Creates a named binary semaphore, basically a semaphore that is init S <- 1
|
||||||
\param name The name of this mutex.
|
\param name The name of this mutex.
|
||||||
*/
|
*/
|
||||||
IPCMutex(const std::string& name);
|
IPCMutex(std::string name);
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
~IPCMutex();
|
~IPCMutex();
|
||||||
|
|||||||
+2
-28
@@ -169,33 +169,11 @@ uint8 EQ::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit)
|
|||||||
|
|
||||||
bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const
|
bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const
|
||||||
{
|
{
|
||||||
if (!(Races & GetPlayerRaceBit(race_id))) {
|
if (!(Races & GetPlayerRaceBit(race_id)))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
|
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id))))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EQ::ItemData::IsClassEquipable(uint16 class_id) const
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EQ::ItemData::IsRaceEquipable(uint16 race_id) const
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!(Races & GetPlayerRaceBit(race_id))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -230,10 +208,6 @@ bool EQ::ItemData::IsTypeShield() const
|
|||||||
return (ItemType == item::ItemTypeShield);
|
return (ItemType == item::ItemTypeShield);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemData::IsQuestItem() const {
|
|
||||||
return QuestItemFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item)
|
bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item)
|
||||||
{
|
{
|
||||||
if (!l_item || !r_item)
|
if (!l_item || !r_item)
|
||||||
|
|||||||
+159
-167
@@ -355,198 +355,190 @@ namespace EQ
|
|||||||
|
|
||||||
struct ItemData {
|
struct ItemData {
|
||||||
// Non packet based fields
|
// Non packet based fields
|
||||||
uint8 MinStatus {};
|
uint8 MinStatus;
|
||||||
|
|
||||||
// Packet based fields
|
// Packet based fields
|
||||||
uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book
|
uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book
|
||||||
char Name[64] {}; // Name
|
char Name[64]; // Name
|
||||||
char Lore[80] {}; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
||||||
char IDFile[30] {}; // Visible model
|
char IDFile[30]; // Visible model
|
||||||
uint32 ID {}; // Unique ID (also PK for DB)
|
uint32 ID; // Unique ID (also PK for DB)
|
||||||
int32 Weight {}; // Item weight * 10
|
int32 Weight; // Item weight * 10
|
||||||
uint8 NoRent{} ; // No Rent: 0=norent, 255=not norent
|
uint8 NoRent; // No Rent: 0=norent, 255=not norent
|
||||||
uint8 NoDrop {}; // No Drop: 0=nodrop, 255=not nodrop
|
uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop
|
||||||
uint8 Size {}; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant
|
uint8 Size; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant
|
||||||
uint32 Slots {}; // Bitfield for which slots this item can be used in
|
uint32 Slots; // Bitfield for which slots this item can be used in
|
||||||
uint32 Price {}; // Item cost (?)
|
uint32 Price; // Item cost (?)
|
||||||
uint32 Icon {}; // Icon Number
|
uint32 Icon; // Icon Number
|
||||||
int32 LoreGroup {}; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
||||||
bool LoreFlag {}; // This will be true if LoreGroup is non-zero
|
bool LoreFlag; // This will be true if LoreGroup is non-zero
|
||||||
bool PendingLoreFlag {};
|
bool PendingLoreFlag;
|
||||||
bool ArtifactFlag {};
|
bool ArtifactFlag;
|
||||||
bool SummonedFlag {};
|
bool SummonedFlag;
|
||||||
uint8 FVNoDrop {}; // Firiona Vie nodrop flag
|
uint8 FVNoDrop; // Firiona Vie nodrop flag
|
||||||
uint32 Favor {}; // Individual favor
|
uint32 Favor; // Individual favor
|
||||||
uint32 GuildFavor {}; // Guild favor
|
uint32 GuildFavor; // Guild favor
|
||||||
uint32 PointType {};
|
uint32 PointType;
|
||||||
|
|
||||||
//uint32 Unk117;
|
//uint32 Unk117;
|
||||||
//uint32 Unk118;
|
//uint32 Unk118;
|
||||||
//uint32 Unk121;
|
//uint32 Unk121;
|
||||||
//uint32 Unk124;
|
//uint32 Unk124;
|
||||||
|
|
||||||
uint8 BagType {}; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
|
uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
|
||||||
uint8 BagSlots {}; // Number of slots: can only be 2, 4, 6, 8, or 10
|
uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10
|
||||||
uint8 BagSize {}; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
|
uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
|
||||||
uint8 BagWR {}; // 0->100
|
uint8 BagWR; // 0->100
|
||||||
|
|
||||||
bool BenefitFlag {};
|
bool BenefitFlag;
|
||||||
bool Tradeskills {}; // Is this a tradeskill item?
|
bool Tradeskills; // Is this a tradeskill item?
|
||||||
int8 CR {}; // Save vs Cold
|
int8 CR; // Save vs Cold
|
||||||
int8 DR {}; // Save vs Disease
|
int8 DR; // Save vs Disease
|
||||||
int8 PR {}; // Save vs Poison
|
int8 PR; // Save vs Poison
|
||||||
int8 MR {}; // Save vs Magic
|
int8 MR; // Save vs Magic
|
||||||
int8 FR {}; // Save vs Fire
|
int8 FR; // Save vs Fire
|
||||||
int8 AStr {}; // Strength
|
int8 AStr; // Strength
|
||||||
int8 ASta {}; // Stamina
|
int8 ASta; // Stamina
|
||||||
int8 AAgi {}; // Agility
|
int8 AAgi; // Agility
|
||||||
int8 ADex {}; // Dexterity
|
int8 ADex; // Dexterity
|
||||||
int8 ACha {}; // Charisma
|
int8 ACha; // Charisma
|
||||||
int8 AInt {}; // Intelligence
|
int8 AInt; // Intelligence
|
||||||
int8 AWis {}; // Wisdom
|
int8 AWis; // Wisdom
|
||||||
int32 HP {}; // HP
|
int32 HP; // HP
|
||||||
int32 Mana {}; // Mana
|
int32 Mana; // Mana
|
||||||
int32 AC {}; // AC
|
int32 AC; // AC
|
||||||
uint32 Deity {}; // Bitmask of Deities that can equip this item
|
uint32 Deity; // Bitmask of Deities that can equip this item
|
||||||
//uint32 Unk033
|
//uint32 Unk033
|
||||||
int32 SkillModValue {}; // % Mod to skill specified in SkillModType
|
int32 SkillModValue; // % Mod to skill specified in SkillModType
|
||||||
int32 SkillModMax {}; // Max skill point modification
|
int32 SkillModMax; // Max skill point modification
|
||||||
uint32 SkillModType {}; // Type of skill for SkillModValue to apply to
|
uint32 SkillModType; // Type of skill for SkillModValue to apply to
|
||||||
uint32 BaneDmgRace {}; // Bane Damage Race
|
uint32 BaneDmgRace; // Bane Damage Race
|
||||||
int32 BaneDmgAmt {}; // Bane Damage Body Amount
|
int32 BaneDmgAmt; // Bane Damage Body Amount
|
||||||
uint32 BaneDmgBody {}; // Bane Damage Body
|
uint32 BaneDmgBody; // Bane Damage Body
|
||||||
bool Magic {}; // True=Magic Item, False=not
|
bool Magic; // True=Magic Item, False=not
|
||||||
int32 CastTime_ {};
|
int32 CastTime_;
|
||||||
uint8 ReqLevel {}; // Required Level to use item
|
uint8 ReqLevel; // Required Level to use item
|
||||||
uint32 BardType {}; // Bard Skill Type
|
uint32 BardType; // Bard Skill Type
|
||||||
int32 BardValue {}; // Bard Skill Amount
|
int32 BardValue; // Bard Skill Amount
|
||||||
int8 Light {}; // Light
|
int8 Light; // Light
|
||||||
uint8 Delay {}; // Delay * 10
|
uint8 Delay; // Delay * 10
|
||||||
uint8 RecLevel {}; // Recommended level to use item
|
uint8 RecLevel; // Recommended level to use item
|
||||||
uint8 RecSkill {}; // Recommended skill to use item (refers to primary skill of item)
|
uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item)
|
||||||
uint8 ElemDmgType {}; // Elemental Damage Type (1=magic, 2=fire)
|
uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire)
|
||||||
uint8 ElemDmgAmt {}; // Elemental Damage
|
uint8 ElemDmgAmt; // Elemental Damage
|
||||||
uint8 Range {}; // Range of item
|
uint8 Range; // Range of item
|
||||||
uint32 Damage {}; // Delay between item usage (in 0.1 sec increments)
|
uint32 Damage; // Delay between item usage (in 0.1 sec increments)
|
||||||
uint32 Color {}; // RR GG BB 00 <-- as it appears in pc
|
uint32 Color; // RR GG BB 00 <-- as it appears in pc
|
||||||
uint32 Classes {}; // Bitfield of classes that can equip item (1 << class#)
|
uint32 Classes; // Bitfield of classes that can equip item (1 << class#)
|
||||||
uint32 Races {}; // Bitfield of races that can equip item (1 << race#)
|
uint32 Races; // Bitfield of races that can equip item (1 << race#)
|
||||||
//uint32 Unk054 {};
|
//uint32 Unk054;
|
||||||
int16 MaxCharges {}; // Maximum charges items can hold: -1 if not a chargeable item
|
int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
|
||||||
uint8 ItemType {}; // Item Type/Skill (itemClass* from above)
|
uint8 ItemType; // Item Type/Skill (itemClass* from above)
|
||||||
int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
|
int32 SubType; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
|
||||||
uint8 Material {}; // Item material type
|
uint8 Material; // Item material type
|
||||||
uint32 HerosForgeModel {};// Hero's Forge Armor Model Type (2-13?)
|
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
|
||||||
float SellRate {}; // Sell rate
|
float SellRate; // Sell rate
|
||||||
//uint32 Unk059 {};
|
//uint32 Unk059;
|
||||||
union {
|
union {
|
||||||
uint32 Fulfilment; // Food fulfilment (How long it lasts)
|
uint32 Fulfilment; // Food fulfilment (How long it lasts)
|
||||||
uint32 CastTime; // Cast Time for clicky effects, in milliseconds
|
uint32 CastTime; // Cast Time for clicky effects, in milliseconds
|
||||||
};
|
};
|
||||||
uint32 EliteMaterial {};
|
uint32 EliteMaterial;
|
||||||
int32 ProcRate {};
|
int32 ProcRate;
|
||||||
int8 CombatEffects {}; // PoP: Combat Effects +
|
int8 CombatEffects; // PoP: Combat Effects +
|
||||||
int8 Shielding {}; // PoP: Shielding %
|
int8 Shielding; // PoP: Shielding %
|
||||||
int8 StunResist {}; // PoP: Stun Resist %
|
int8 StunResist; // PoP: Stun Resist %
|
||||||
int8 StrikeThrough {}; // PoP: Strike Through %
|
int8 StrikeThrough; // PoP: Strike Through %
|
||||||
int32 ExtraDmgSkill {};
|
uint32 ExtraDmgSkill;
|
||||||
int32 ExtraDmgAmt {};
|
uint32 ExtraDmgAmt;
|
||||||
int8 SpellShield {}; // PoP: Spell Shield %
|
int8 SpellShield; // PoP: Spell Shield %
|
||||||
int8 Avoidance {}; // PoP: Avoidance +
|
int8 Avoidance; // PoP: Avoidance +
|
||||||
int8 Accuracy {}; // PoP: Accuracy +
|
int8 Accuracy; // PoP: Accuracy +
|
||||||
uint32 CharmFileID {};
|
uint32 CharmFileID;
|
||||||
int32 FactionMod1 {}; // Faction Mod 1
|
int32 FactionMod1; // Faction Mod 1
|
||||||
int32 FactionMod2 {}; // Faction Mod 2
|
int32 FactionMod2; // Faction Mod 2
|
||||||
int32 FactionMod3 {}; // Faction Mod 3
|
int32 FactionMod3; // Faction Mod 3
|
||||||
int32 FactionMod4 {}; // Faction Mod 4
|
int32 FactionMod4; // Faction Mod 4
|
||||||
int32 FactionAmt1 {}; // Faction Amt 1
|
int32 FactionAmt1; // Faction Amt 1
|
||||||
int32 FactionAmt2 {}; // Faction Amt 2
|
int32 FactionAmt2; // Faction Amt 2
|
||||||
int32 FactionAmt3 {}; // Faction Amt 3
|
int32 FactionAmt3; // Faction Amt 3
|
||||||
int32 FactionAmt4 {}; // Faction Amt 4
|
int32 FactionAmt4; // Faction Amt 4
|
||||||
char CharmFile[32] {}; // ?
|
char CharmFile[32]; // ?
|
||||||
uint32 AugType {};
|
uint32 AugType;
|
||||||
uint8 AugSlotType[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Type
|
uint8 AugSlotType[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Type
|
||||||
uint8 AugSlotVisible[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Visible
|
uint8 AugSlotVisible[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Visible
|
||||||
uint8 AugSlotUnk2[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
uint8 AugSlotUnk2[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
||||||
uint32 LDoNTheme {};
|
uint32 LDoNTheme;
|
||||||
uint32 LDoNPrice {};
|
uint32 LDoNPrice;
|
||||||
uint32 LDoNSold {};
|
uint32 LDoNSold;
|
||||||
uint32 BaneDmgRaceAmt {};
|
uint32 BaneDmgRaceAmt;
|
||||||
uint32 AugRestrict {};
|
uint32 AugRestrict;
|
||||||
int32 Endur {};
|
int32 Endur;
|
||||||
int32 DotShielding {};
|
int32 DotShielding;
|
||||||
int32 Attack {};
|
int32 Attack;
|
||||||
int32 Regen {};
|
int32 Regen;
|
||||||
int32 ManaRegen {};
|
int32 ManaRegen;
|
||||||
int32 EnduranceRegen {};
|
int32 EnduranceRegen;
|
||||||
int32 Haste {};
|
int32 Haste;
|
||||||
int32 DamageShield {};
|
int32 DamageShield;
|
||||||
uint32 RecastDelay {};
|
uint32 RecastDelay;
|
||||||
int RecastType {};
|
int RecastType;
|
||||||
uint32 AugDistiller {};
|
uint32 AugDistiller;
|
||||||
bool Attuneable {};
|
bool Attuneable;
|
||||||
bool NoPet {};
|
bool NoPet;
|
||||||
bool PotionBelt {};
|
bool PotionBelt;
|
||||||
bool Stackable {};
|
bool Stackable;
|
||||||
bool NoTransfer {};
|
bool NoTransfer;
|
||||||
bool QuestItemFlag {};
|
bool QuestItemFlag;
|
||||||
int16 StackSize {};
|
int16 StackSize;
|
||||||
uint8 PotionBeltSlots {};
|
uint8 PotionBeltSlots;
|
||||||
item::ItemEffect_Struct Click {};
|
item::ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
|
||||||
item::ItemEffect_Struct Proc {};
|
|
||||||
item::ItemEffect_Struct Worn {};
|
|
||||||
item::ItemEffect_Struct Focus {};
|
|
||||||
item::ItemEffect_Struct Scroll {};
|
|
||||||
item::ItemEffect_Struct Bard {};
|
|
||||||
|
|
||||||
uint8 Book {}; // 0=Not book, 1=Book
|
uint8 Book; // 0=Not book, 1=Book
|
||||||
uint32 BookType {};
|
uint32 BookType;
|
||||||
char Filename[33] {}; // Filename for book data
|
char Filename[33]; // Filename for book data
|
||||||
// Begin SoF Fields
|
// Begin SoF Fields
|
||||||
int32 SVCorruption {};
|
int32 SVCorruption;
|
||||||
uint32 Purity {};
|
uint32 Purity;
|
||||||
uint8 EvolvingItem {};
|
uint8 EvolvingItem;
|
||||||
uint32 EvolvingID {};
|
uint32 EvolvingID;
|
||||||
uint8 EvolvingLevel {};
|
uint8 EvolvingLevel;
|
||||||
uint8 EvolvingMax {};
|
uint8 EvolvingMax;
|
||||||
uint32 BackstabDmg {};
|
uint32 BackstabDmg;
|
||||||
uint32 DSMitigation {};
|
uint32 DSMitigation;
|
||||||
int32 HeroicStr {};
|
int32 HeroicStr;
|
||||||
int32 HeroicInt {};
|
int32 HeroicInt;
|
||||||
int32 HeroicWis {};
|
int32 HeroicWis;
|
||||||
int32 HeroicAgi {};
|
int32 HeroicAgi;
|
||||||
int32 HeroicDex {};
|
int32 HeroicDex;
|
||||||
int32 HeroicSta {};
|
int32 HeroicSta;
|
||||||
int32 HeroicCha {};
|
int32 HeroicCha;
|
||||||
int32 HeroicMR {};
|
int32 HeroicMR;
|
||||||
int32 HeroicFR {};
|
int32 HeroicFR;
|
||||||
int32 HeroicCR {};
|
int32 HeroicCR;
|
||||||
int32 HeroicDR {};
|
int32 HeroicDR;
|
||||||
int32 HeroicPR {};
|
int32 HeroicPR;
|
||||||
int32 HeroicSVCorrup {};
|
int32 HeroicSVCorrup;
|
||||||
int32 HealAmt {};
|
int32 HealAmt;
|
||||||
int32 SpellDmg {};
|
int32 SpellDmg;
|
||||||
uint32 LDoNSellBackRate {};
|
uint32 LDoNSellBackRate;
|
||||||
uint32 ScriptFileID {};
|
uint32 ScriptFileID;
|
||||||
uint16 ExpendableArrow {};
|
uint16 ExpendableArrow;
|
||||||
uint32 Clairvoyance {};
|
uint32 Clairvoyance;
|
||||||
char ClickName[65] {};
|
char ClickName[65];
|
||||||
char ProcName[65] {};
|
char ProcName[65];
|
||||||
char WornName[65] {};
|
char WornName[65];
|
||||||
char FocusName[65] {};
|
char FocusName[65];
|
||||||
char ScrollName[65] {};
|
char ScrollName[65];
|
||||||
//BardName
|
//BardName
|
||||||
|
|
||||||
bool IsEquipable(uint16 Race, uint16 Class) const;
|
bool IsEquipable(uint16 Race, uint16 Class) const;
|
||||||
bool IsClassEquipable(uint16 Class) const;
|
|
||||||
bool IsRaceEquipable(uint16 Race) const;
|
|
||||||
bool IsClassCommon() const;
|
bool IsClassCommon() const;
|
||||||
bool IsClassBag() const;
|
bool IsClassBag() const;
|
||||||
bool IsClassBook() const;
|
bool IsClassBook() const;
|
||||||
bool IsType1HWeapon() const;
|
bool IsType1HWeapon() const;
|
||||||
bool IsType2HWeapon() const;
|
bool IsType2HWeapon() const;
|
||||||
bool IsTypeShield() const;
|
bool IsTypeShield() const;
|
||||||
bool IsQuestItem() const;
|
|
||||||
|
|
||||||
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
|
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
|
||||||
bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); }
|
bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); }
|
||||||
|
|||||||
+187
-257
@@ -17,14 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "inventory_profile.h"
|
#include "inventory_profile.h"
|
||||||
#include "../common/data_verification.h"
|
|
||||||
//#include "classes.h"
|
//#include "classes.h"
|
||||||
//#include "global_define.h"
|
//#include "global_define.h"
|
||||||
//#include "item_instance.h"
|
//#include "item_instance.h"
|
||||||
//#include "races.h"
|
//#include "races.h"
|
||||||
#include "rulesys.h"
|
#include "rulesys.h"
|
||||||
#include "shareddb.h"
|
#include "shareddb.h"
|
||||||
#include "strings.h"
|
#include "string_util.h"
|
||||||
|
|
||||||
//#include "../common/light_source.h"
|
//#include "../common/light_source.h"
|
||||||
|
|
||||||
@@ -58,62 +57,108 @@ static inline int32 GetNextItemInstSerialNumber() {
|
|||||||
// class EQ::ItemInstance
|
// class EQ::ItemInstance
|
||||||
//
|
//
|
||||||
EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
|
EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
|
||||||
|
m_use_type = ItemInstNormal;
|
||||||
if (item) {
|
if(item) {
|
||||||
m_item = new ItemData(*item);
|
m_item = new ItemData(*item);
|
||||||
|
} else {
|
||||||
|
m_item = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_charges = charges;
|
m_charges = charges;
|
||||||
|
m_price = 0;
|
||||||
if (m_item && m_item->IsClassCommon()) {
|
m_attuned = false;
|
||||||
|
m_merchantslot = 0;
|
||||||
|
if (m_item && m_item->IsClassCommon())
|
||||||
m_color = m_item->Color;
|
m_color = m_item->Color;
|
||||||
}
|
else
|
||||||
|
m_color = 0;
|
||||||
|
m_merchantcount = 1;
|
||||||
|
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||||
|
|
||||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
m_exp = 0;
|
||||||
|
m_evolveLvl = 0;
|
||||||
|
m_activated = false;
|
||||||
|
m_scaledItem = nullptr;
|
||||||
|
m_evolveInfo = nullptr;
|
||||||
|
m_scaling = false;
|
||||||
|
m_ornamenticon = 0;
|
||||||
|
m_ornamentidfile = 0;
|
||||||
|
m_ornament_hero_model = 0;
|
||||||
|
m_recast_timestamp = 0;
|
||||||
|
m_new_id_file = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) {
|
EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) {
|
||||||
|
m_use_type = ItemInstNormal;
|
||||||
m_item = db->GetItem(item_id);
|
m_item = db->GetItem(item_id);
|
||||||
|
if(m_item) {
|
||||||
if (m_item) {
|
|
||||||
m_item = new ItemData(*m_item);
|
m_item = new ItemData(*m_item);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
m_item = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_charges = charges;
|
m_charges = charges;
|
||||||
|
m_price = 0;
|
||||||
if (m_item && m_item->IsClassCommon()) {
|
m_merchantslot = 0;
|
||||||
|
m_attuned=false;
|
||||||
|
if (m_item && m_item->IsClassCommon())
|
||||||
m_color = m_item->Color;
|
m_color = m_item->Color;
|
||||||
} else {
|
else
|
||||||
m_color = 0;
|
m_color = 0;
|
||||||
}
|
m_merchantcount = 1;
|
||||||
|
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||||
|
|
||||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
m_exp = 0;
|
||||||
|
m_evolveLvl = 0;
|
||||||
|
m_activated = false;
|
||||||
|
m_scaledItem = nullptr;
|
||||||
|
m_evolveInfo = nullptr;
|
||||||
|
m_scaling = false;
|
||||||
|
m_ornamenticon = 0;
|
||||||
|
m_ornamentidfile = 0;
|
||||||
|
m_ornament_hero_model = 0;
|
||||||
|
m_recast_timestamp = 0;
|
||||||
|
m_new_id_file = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) {
|
EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) {
|
||||||
m_use_type = use_type;
|
m_use_type = use_type;
|
||||||
|
m_item = nullptr;
|
||||||
|
m_charges = 0;
|
||||||
|
m_price = 0;
|
||||||
|
m_attuned = false;
|
||||||
|
m_merchantslot = 0;
|
||||||
|
m_color = 0;
|
||||||
|
|
||||||
|
m_exp = 0;
|
||||||
|
m_evolveLvl = 0;
|
||||||
|
m_activated = false;
|
||||||
|
m_scaledItem = nullptr;
|
||||||
|
m_evolveInfo = nullptr;
|
||||||
|
m_scaling = false;
|
||||||
|
m_ornamenticon = 0;
|
||||||
|
m_ornamentidfile = 0;
|
||||||
|
m_ornament_hero_model = 0;
|
||||||
|
m_recast_timestamp = 0;
|
||||||
|
m_new_id_file = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a copy of an EQ::ItemInstance object
|
// Make a copy of an EQ::ItemInstance object
|
||||||
EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
||||||
{
|
{
|
||||||
m_use_type = copy.m_use_type;
|
m_use_type=copy.m_use_type;
|
||||||
|
if(copy.m_item)
|
||||||
if (copy.m_item) {
|
|
||||||
m_item = new ItemData(*copy.m_item);
|
m_item = new ItemData(*copy.m_item);
|
||||||
} else {
|
else
|
||||||
m_item = nullptr;
|
m_item = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
m_charges = copy.m_charges;
|
|
||||||
m_price = copy.m_price;
|
|
||||||
m_color = copy.m_color;
|
|
||||||
m_merchantslot = copy.m_merchantslot;
|
|
||||||
m_currentslot = copy.m_currentslot;
|
|
||||||
m_attuned = copy.m_attuned;
|
|
||||||
m_merchantcount = copy.m_merchantcount;
|
|
||||||
|
|
||||||
|
m_charges=copy.m_charges;
|
||||||
|
m_price=copy.m_price;
|
||||||
|
m_color=copy.m_color;
|
||||||
|
m_merchantslot=copy.m_merchantslot;
|
||||||
|
m_currentslot=copy.m_currentslot;
|
||||||
|
m_attuned=copy.m_attuned;
|
||||||
|
m_merchantcount=copy.m_merchantcount;
|
||||||
// Copy container contents
|
// Copy container contents
|
||||||
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
|
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
|
||||||
ItemInstance* inst_old = it->second;
|
ItemInstance* inst_old = it->second;
|
||||||
@@ -123,42 +168,37 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
|||||||
inst_new = inst_old->Clone();
|
inst_new = inst_old->Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst_new) {
|
if (inst_new != nullptr) {
|
||||||
m_contents[it->first] = inst_new;
|
m_contents[it->first] = inst_new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string>::const_iterator iter;
|
std::map<std::string, std::string>::const_iterator iter;
|
||||||
for (iter = copy.m_custom_data.begin(); iter != copy.m_custom_data.end(); ++iter) {
|
for (iter = copy.m_custom_data.begin(); iter != copy.m_custom_data.end(); ++iter) {
|
||||||
m_custom_data[iter->first] = iter->second;
|
m_custom_data[iter->first] = iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_SerialNumber = copy.m_SerialNumber;
|
m_SerialNumber = copy.m_SerialNumber;
|
||||||
m_custom_data = copy.m_custom_data;
|
m_custom_data = copy.m_custom_data;
|
||||||
m_timers = copy.m_timers;
|
m_timers = copy.m_timers;
|
||||||
|
|
||||||
m_exp = copy.m_exp;
|
m_exp = copy.m_exp;
|
||||||
m_evolveLvl = copy.m_evolveLvl;
|
m_evolveLvl = copy.m_evolveLvl;
|
||||||
m_activated = copy.m_activated;
|
m_activated = copy.m_activated;
|
||||||
|
if (copy.m_scaledItem)
|
||||||
if (copy.m_scaledItem) {
|
|
||||||
m_scaledItem = new ItemData(*copy.m_scaledItem);
|
m_scaledItem = new ItemData(*copy.m_scaledItem);
|
||||||
} else {
|
else
|
||||||
m_scaledItem = nullptr;
|
m_scaledItem = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if (copy.m_evolveInfo) {
|
if(copy.m_evolveInfo)
|
||||||
m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo);
|
m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo);
|
||||||
} else {
|
else
|
||||||
m_evolveInfo = nullptr;
|
m_evolveInfo = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
m_scaling = copy.m_scaling;
|
m_scaling = copy.m_scaling;
|
||||||
m_ornamenticon = copy.m_ornamenticon;
|
m_ornamenticon = copy.m_ornamenticon;
|
||||||
m_ornamentidfile = copy.m_ornamentidfile;
|
m_ornamentidfile = copy.m_ornamentidfile;
|
||||||
m_ornament_hero_model = copy.m_ornament_hero_model;
|
m_ornament_hero_model = copy.m_ornament_hero_model;
|
||||||
m_recast_timestamp = copy.m_recast_timestamp;
|
m_recast_timestamp = copy.m_recast_timestamp;
|
||||||
m_new_id_file = copy.m_new_id_file;
|
m_new_id_file = copy.m_new_id_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up container contents
|
// Clean up container contents
|
||||||
@@ -176,13 +216,11 @@ bool EQ::ItemInstance::IsType(item::ItemClass item_class) const
|
|||||||
// IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr'
|
// IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr'
|
||||||
|
|
||||||
// Check usage type
|
// Check usage type
|
||||||
if (m_use_type == ItemInstWorldContainer && item_class == item::ItemClassBag) {
|
if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_item) {
|
if (!m_item)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return (m_item->ItemClass == item_class);
|
return (m_item->ItemClass == item_class);
|
||||||
}
|
}
|
||||||
@@ -205,145 +243,96 @@ bool EQ::ItemInstance::IsClassBook() const
|
|||||||
// Is item stackable?
|
// Is item stackable?
|
||||||
bool EQ::ItemInstance::IsStackable() const
|
bool EQ::ItemInstance::IsStackable() const
|
||||||
{
|
{
|
||||||
return (m_item && m_item->Stackable);
|
if (!m_item)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_item->Stackable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::IsCharged() const
|
bool EQ::ItemInstance::IsCharged() const
|
||||||
{
|
{
|
||||||
if (!m_item) {
|
if (!m_item)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (m_item->MaxCharges > 1) {
|
if (m_item->MaxCharges > 1)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can item be equipped?
|
// Can item be equipped?
|
||||||
bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const
|
bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->Slots) {
|
if (!m_item || (m_item->Slots == 0))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return m_item->IsEquipable(race, class_);
|
return m_item->IsEquipable(race, class_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can item be equipped by Class?
|
|
||||||
bool EQ::ItemInstance::IsClassEquipable(uint16 class_) const
|
|
||||||
{
|
|
||||||
if (!m_item || !m_item->Slots) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_item->IsClassEquipable(class_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can item be equipped by Race?
|
|
||||||
bool EQ::ItemInstance::IsRaceEquipable(uint16 race) const
|
|
||||||
{
|
|
||||||
if (!m_item || !m_item->Slots) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_item->IsRaceEquipable(race);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can equip at this slot?
|
// Can equip at this slot?
|
||||||
bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
|
bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->Slots) {
|
if (!m_item)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
|
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return ((m_item->Slots & (1 << slot_id)) != 0);
|
return ((m_item->Slots & (1 << slot_id)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::IsAugmentable() const
|
bool EQ::ItemInstance::IsAugmentable() const
|
||||||
{
|
{
|
||||||
if (!m_item) {
|
if (!m_item)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
|
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
|
||||||
if (m_item->AugSlotType[index] != 0) {
|
if (m_item->AugSlotType[index] != 0)
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
|
bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
if (!m_item || !m_item->IsClassCommon())
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
int index = invslot::EQUIPMENT_BEGIN;
|
int index = invslot::EQUIPMENT_BEGIN;
|
||||||
for (; index <= invslot::EQUIPMENT_END; ++index) {
|
for (; index <= invslot::EQUIPMENT_END; ++index) {
|
||||||
if (m_item->Slots & (1 << index)) {
|
if (m_item->Slots & (1 << index)) {
|
||||||
if (aug_wear_slots & (1 << index)) {
|
if (aug_wear_slots & (1 << index))
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (index <= EQ::invslot::EQUIPMENT_END);
|
return (index <= EQ::invslot::EQUIPMENT_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
|
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augtype) const
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
if (!m_item || !m_item->IsClassCommon())
|
||||||
return INVALID_INDEX;
|
return INVALID_INDEX;
|
||||||
}
|
|
||||||
|
|
||||||
auto i = invaug::SOCKET_BEGIN;
|
int index = invaug::SOCKET_BEGIN;
|
||||||
for (; i <= invaug::SOCKET_END; ++i) {
|
for (; index <= invaug::SOCKET_END; ++index) {
|
||||||
if (GetItem(i)) {
|
if (GetItem(index)) { continue; }
|
||||||
continue;
|
if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype)))
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
augment_type == -1 ||
|
|
||||||
(
|
|
||||||
m_item->AugSlotType[i] &&
|
|
||||||
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
|
return (index <= invaug::SOCKET_END) ? index : INVALID_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const
|
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
if (!m_item || !m_item->IsClassCommon())
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) {
|
||||||
(
|
|
||||||
!GetItem(slot) &&
|
|
||||||
m_item->AugSlotVisible[slot]
|
|
||||||
) &&
|
|
||||||
augment_type == -1 ||
|
|
||||||
(
|
|
||||||
m_item->AugSlotType[slot] &&
|
|
||||||
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve item inside container
|
// Retrieve item inside container
|
||||||
@@ -359,10 +348,9 @@ EQ::ItemInstance* EQ::ItemInstance::GetItem(uint8 index) const
|
|||||||
|
|
||||||
uint32 EQ::ItemInstance::GetItemID(uint8 slot) const
|
uint32 EQ::ItemInstance::GetItemID(uint8 slot) const
|
||||||
{
|
{
|
||||||
const auto item = GetItem(slot);
|
ItemInstance *item = GetItem(slot);
|
||||||
if (item) {
|
if (item)
|
||||||
return item->GetID();
|
return item->GetID();
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -486,21 +474,14 @@ uint8 EQ::ItemInstance::FirstOpenSlot() const
|
|||||||
|
|
||||||
uint8 EQ::ItemInstance::GetTotalItemCount() const
|
uint8 EQ::ItemInstance::GetTotalItemCount() const
|
||||||
{
|
{
|
||||||
if (!m_item) {
|
if (!m_item)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
uint8 item_count = 1;
|
uint8 item_count = 1;
|
||||||
|
|
||||||
if (!m_item->IsClassBag()) {
|
if (m_item && !m_item->IsClassBag()) { return item_count; }
|
||||||
return item_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) {
|
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } }
|
||||||
if (GetItem(index)) {
|
|
||||||
++item_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return item_count;
|
return item_count;
|
||||||
}
|
}
|
||||||
@@ -519,108 +500,86 @@ bool EQ::ItemInstance::IsNoneEmptyContainer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve augment inside item
|
// Retrieve augment inside item
|
||||||
EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 augment_index) const
|
EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 slot) const
|
||||||
{
|
{
|
||||||
if (m_item && m_item->IsClassCommon()) {
|
if (m_item && m_item->IsClassCommon())
|
||||||
return GetItem(augment_index);
|
return GetItem(slot);
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::IsOrnamentationAugment(EQ::ItemInstance* augment) const
|
EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugtype) const
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->IsClassCommon() || !augment) {
|
if (!m_item || !m_item->IsClassCommon()) { return nullptr; }
|
||||||
return false;
|
if (ornamentationAugtype == 0) { return nullptr; }
|
||||||
}
|
|
||||||
|
|
||||||
const auto augment_item = augment->GetItem();
|
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++)
|
||||||
if (!augment_item) {
|
{
|
||||||
return false;
|
if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype)
|
||||||
}
|
{
|
||||||
|
const char *item_IDFile = GetAugment(i)->GetItem()->IDFile;
|
||||||
const std::string& idfile = augment_item->IDFile;
|
if (
|
||||||
|
(strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0
|
||||||
if (
|
|| strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0)
|
||||||
EQ::ValueWithin(
|
&& GetAugment(i)->GetItem()->HerosForgeModel == 0
|
||||||
augment->GetAugmentType(),
|
)
|
||||||
OrnamentationAugmentTypes::StandardOrnamentation,
|
{
|
||||||
OrnamentationAugmentTypes::SpecialOrnamentation
|
continue;
|
||||||
) ||
|
}
|
||||||
(
|
return GetAugment(i);
|
||||||
idfile != "IT63" &&
|
|
||||||
idfile != "IT64"
|
|
||||||
) ||
|
|
||||||
augment_item->HerosForgeModel
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAugment() const
|
|
||||||
{
|
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
|
|
||||||
const auto augment = GetAugment(i);
|
|
||||||
if (augment && IsOrnamentationAugment(augment)) {
|
|
||||||
return augment;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const
|
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const {
|
||||||
{
|
|
||||||
// Not a Hero Forge item.
|
// Not a Hero Forge item.
|
||||||
if (m_ornament_hero_model == 0 || material_slot < 0) {
|
if (m_ornament_hero_model == 0 || material_slot < 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
// Item is using an explicit Hero Forge ID
|
// Item is using an explicit Hero Forge ID
|
||||||
if (m_ornament_hero_model >= 1000) {
|
if (m_ornament_hero_model >= 1000)
|
||||||
return m_ornament_hero_model;
|
return m_ornament_hero_model;
|
||||||
}
|
|
||||||
|
|
||||||
// Item is using a shorthand ID
|
// Item is using a shorthand ID
|
||||||
return (m_ornament_hero_model * 100) + material_slot;
|
return (m_ornament_hero_model * 100) + material_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::UpdateOrnamentationInfo()
|
bool EQ::ItemInstance::UpdateOrnamentationInfo() {
|
||||||
{
|
if (!m_item || !m_item->IsClassCommon())
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
const auto augment = GetOrnamentationAugment();
|
bool ornamentSet = false;
|
||||||
|
|
||||||
if (augment) {
|
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||||
const auto augment_item = GetOrnamentationAugment()->GetItem();
|
if (GetOrnamentationAug(ornamentationAugtype))
|
||||||
|
{
|
||||||
if (augment_item) {
|
const ItemData* ornamentItem;
|
||||||
SetOrnamentIcon(augment_item->Icon);
|
ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||||
SetOrnamentHeroModel(augment_item->HerosForgeModel);
|
if (ornamentItem != nullptr)
|
||||||
|
{
|
||||||
if (strlen(augment_item->IDFile) > 2) {
|
SetOrnamentIcon(ornamentItem->Icon);
|
||||||
SetOrnamentationIDFile(Strings::ToUnsignedInt(&augment_item->IDFile[2]));
|
SetOrnamentHeroModel(ornamentItem->HerosForgeModel);
|
||||||
} else {
|
if (strlen(ornamentItem->IDFile) > 2)
|
||||||
|
{
|
||||||
|
SetOrnamentationIDFile(atoi(&ornamentItem->IDFile[2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SetOrnamentationIDFile(0);
|
SetOrnamentationIDFile(0);
|
||||||
}
|
}
|
||||||
|
ornamentSet = true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetOrnamentIcon(0);
|
||||||
|
SetOrnamentHeroModel(0);
|
||||||
|
SetOrnamentationIDFile(0);
|
||||||
|
}
|
||||||
|
|
||||||
SetOrnamentIcon(0);
|
return ornamentSet;
|
||||||
SetOrnamentHeroModel(0);
|
|
||||||
SetOrnamentationIDFile(0);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) {
|
bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) {
|
||||||
@@ -670,13 +629,12 @@ bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *C
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 EQ::ItemInstance::GetAugmentItemID(uint8 augment_index) const
|
uint32 EQ::ItemInstance::GetAugmentItemID(uint8 slot) const
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
if (!m_item || !m_item->IsClassCommon())
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return GetItemID(augment_index);
|
return GetItemID(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an augment to the item
|
// Add an augment to the item
|
||||||
@@ -720,14 +678,12 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
|
|||||||
|
|
||||||
bool EQ::ItemInstance::IsAugmented()
|
bool EQ::ItemInstance::IsAugmented()
|
||||||
{
|
{
|
||||||
if (!m_item || !m_item->IsClassCommon()) {
|
if (!m_item || !m_item->IsClassCommon())
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) {
|
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
|
||||||
if (GetAugmentItemID(slot_id)) {
|
if (GetAugmentItemID(index))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -836,20 +792,7 @@ std::string EQ::ItemInstance::GetCustomDataString() const {
|
|||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::ItemInstance::SetCustomDataString(const std::string& str)
|
std::string EQ::ItemInstance::GetCustomData(std::string identifier) {
|
||||||
{
|
|
||||||
auto components = Strings::Split(str, "^");
|
|
||||||
auto value_count = components.size() / 2;
|
|
||||||
|
|
||||||
for (auto i = 0; i < value_count; i++) {
|
|
||||||
auto identifier = components[i * 2];
|
|
||||||
auto value = components[(i * 2) + 1];
|
|
||||||
|
|
||||||
SetCustomData(identifier, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) {
|
|
||||||
std::map<std::string, std::string>::const_iterator iter = m_custom_data.find(identifier);
|
std::map<std::string, std::string>::const_iterator iter = m_custom_data.find(identifier);
|
||||||
if (iter != m_custom_data.end()) {
|
if (iter != m_custom_data.end()) {
|
||||||
return iter->second;
|
return iter->second;
|
||||||
@@ -858,33 +801,33 @@ std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::ItemInstance::SetCustomData(const std::string& identifier, const std::string& value) {
|
void EQ::ItemInstance::SetCustomData(std::string identifier, std::string value) {
|
||||||
DeleteCustomData(identifier);
|
DeleteCustomData(identifier);
|
||||||
m_custom_data[identifier] = value;
|
m_custom_data[identifier] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::ItemInstance::SetCustomData(const std::string& identifier, int value) {
|
void EQ::ItemInstance::SetCustomData(std::string identifier, int value) {
|
||||||
DeleteCustomData(identifier);
|
DeleteCustomData(identifier);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << value;
|
ss << value;
|
||||||
m_custom_data[identifier] = ss.str();
|
m_custom_data[identifier] = ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::ItemInstance::SetCustomData(const std::string& identifier, float value) {
|
void EQ::ItemInstance::SetCustomData(std::string identifier, float value) {
|
||||||
DeleteCustomData(identifier);
|
DeleteCustomData(identifier);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << value;
|
ss << value;
|
||||||
m_custom_data[identifier] = ss.str();
|
m_custom_data[identifier] = ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::ItemInstance::SetCustomData(const std::string& identifier, bool value) {
|
void EQ::ItemInstance::SetCustomData(std::string identifier, bool value) {
|
||||||
DeleteCustomData(identifier);
|
DeleteCustomData(identifier);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << value;
|
ss << value;
|
||||||
m_custom_data[identifier] = ss.str();
|
m_custom_data[identifier] = ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::ItemInstance::DeleteCustomData(const std::string& identifier) {
|
void EQ::ItemInstance::DeleteCustomData(std::string identifier) {
|
||||||
auto iter = m_custom_data.find(identifier);
|
auto iter = m_custom_data.find(identifier);
|
||||||
if (iter != m_custom_data.end()) {
|
if (iter != m_custom_data.end()) {
|
||||||
m_custom_data.erase(iter);
|
m_custom_data.erase(iter);
|
||||||
@@ -936,9 +879,8 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
|
|||||||
|
|
||||||
void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
||||||
// if there's no actual item, don't do anything
|
// if there's no actual item, don't do anything
|
||||||
if (!m_item) {
|
if (!m_item)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// initialize scaling items
|
// initialize scaling items
|
||||||
if (m_item->CharmFileID != 0) {
|
if (m_item->CharmFileID != 0) {
|
||||||
@@ -947,7 +889,7 @@ void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initialize evolving items
|
// initialize evolving items
|
||||||
else if (db && m_item->LoreGroup >= 1000) {
|
else if ((db) && m_item->LoreGroup >= 1000 && m_item->LoreGroup != -1) {
|
||||||
// not complete yet
|
// not complete yet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1273,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;
|
||||||
@@ -1779,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
|
||||||
//
|
//
|
||||||
|
|||||||
+38
-57
@@ -51,11 +51,6 @@ typedef enum {
|
|||||||
byFlagNotSet //apply action if the flag is NOT set
|
byFlagNotSet //apply action if the flag is NOT set
|
||||||
} byFlagSetting;
|
} byFlagSetting;
|
||||||
|
|
||||||
enum OrnamentationAugmentTypes {
|
|
||||||
StandardOrnamentation = 20,
|
|
||||||
SpecialOrnamentation = 21
|
|
||||||
};
|
|
||||||
|
|
||||||
class SharedDatabase;
|
class SharedDatabase;
|
||||||
|
|
||||||
// ########################################
|
// ########################################
|
||||||
@@ -97,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;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -106,10 +99,9 @@ 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 int GetAugmentType() const { return m_item ? m_item->AugType : 0; }
|
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); }
|
||||||
inline uint32 GetAugmentRestriction() const { return m_item ? m_item->AugRestrict : 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); }
|
||||||
|
|
||||||
@@ -133,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);
|
||||||
@@ -142,8 +134,7 @@ namespace EQ
|
|||||||
bool IsAugmented();
|
bool IsAugmented();
|
||||||
bool ContainsAugmentByID(uint32 item_id);
|
bool ContainsAugmentByID(uint32 item_id);
|
||||||
int CountAugmentByID(uint32 item_id);
|
int CountAugmentByID(uint32 item_id);
|
||||||
bool IsOrnamentationAugment(EQ::ItemInstance* augment) const;
|
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
|
||||||
ItemInstance* GetOrnamentationAugment() const;
|
|
||||||
bool UpdateOrnamentationInfo();
|
bool UpdateOrnamentationInfo();
|
||||||
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
||||||
|
|
||||||
@@ -157,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; }
|
||||||
|
|
||||||
@@ -182,13 +171,12 @@ namespace EQ
|
|||||||
void SetAttuned(bool flag) { m_attuned = flag; }
|
void SetAttuned(bool flag) { m_attuned = flag; }
|
||||||
|
|
||||||
std::string GetCustomDataString() const;
|
std::string GetCustomDataString() const;
|
||||||
std::string GetCustomData(const std::string &identifier);
|
std::string GetCustomData(std::string identifier);
|
||||||
void SetCustomDataString(const std::string& str);
|
void SetCustomData(std::string identifier, std::string value);
|
||||||
void SetCustomData(const std::string &identifier, const std::string& value);
|
void SetCustomData(std::string identifier, int value);
|
||||||
void SetCustomData(const std::string &identifier, int value);
|
void SetCustomData(std::string identifier, float value);
|
||||||
void SetCustomData(const std::string &identifier, float value);
|
void SetCustomData(std::string identifier, bool value);
|
||||||
void SetCustomData(const std::string &identifier, bool value);
|
void DeleteCustomData(std::string identifier);
|
||||||
void DeleteCustomData(const std::string& identifier);
|
|
||||||
|
|
||||||
// Allows treatment of this object as though it were a pointer to m_item
|
// Allows treatment of this object as though it were a pointer to m_item
|
||||||
operator bool() const { return (m_item != nullptr); }
|
operator bool() const { return (m_item != nullptr); }
|
||||||
@@ -241,13 +229,6 @@ namespace EQ
|
|||||||
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)
|
||||||
@@ -311,33 +292,33 @@ namespace EQ
|
|||||||
|
|
||||||
void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; }
|
void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; }
|
||||||
|
|
||||||
ItemInstTypes m_use_type {ItemInstNormal}; // Usage type for item
|
ItemInstTypes m_use_type; // Usage type for item
|
||||||
const ItemData* m_item {nullptr}; // Ptr to item data
|
const ItemData* m_item; // Ptr to item data
|
||||||
int16 m_charges {0}; // # of charges for chargeable items
|
int16 m_charges; // # of charges for chargeable items
|
||||||
uint32 m_price {0}; // Bazaar /trader price
|
uint32 m_price; // Bazaar /trader price
|
||||||
uint32 m_color {0};
|
uint32 m_color;
|
||||||
uint32 m_merchantslot {0};
|
uint32 m_merchantslot;
|
||||||
int16 m_currentslot {0};
|
int16 m_currentslot;
|
||||||
bool m_attuned {false};
|
bool m_attuned;
|
||||||
int32 m_merchantcount {1}; //number avaliable on the merchant, -1=unlimited
|
int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited
|
||||||
int32 m_SerialNumber {0}; // 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 {0};
|
uint32 m_exp;
|
||||||
int8 m_evolveLvl {0};
|
int8 m_evolveLvl;
|
||||||
bool m_activated {false};
|
bool m_activated;
|
||||||
ItemData* m_scaledItem {nullptr};
|
ItemData* m_scaledItem;
|
||||||
::EvolveInfo* m_evolveInfo {nullptr};
|
::EvolveInfo* m_evolveInfo;
|
||||||
bool m_scaling {false};
|
bool m_scaling;
|
||||||
uint32 m_ornamenticon {0};
|
uint32 m_ornamenticon;
|
||||||
uint32 m_ornamentidfile {0};
|
uint32 m_ornamentidfile;
|
||||||
uint32 m_new_id_file {0};
|
uint32 m_new_id_file;
|
||||||
uint32 m_ornament_hero_model {0};
|
uint32 m_ornament_hero_model;
|
||||||
uint32 m_recast_timestamp {0};
|
uint32 m_recast_timestamp;
|
||||||
int m_task_delivered_count {0};
|
|
||||||
|
|
||||||
// Items inside of this item (augs or contents) {};
|
//
|
||||||
std::map<uint8, ItemInstance*> m_contents {}; // Zero-based index: min=0, max=9
|
// Items inside of this item (augs or contents);
|
||||||
std::map<std::string, std::string> m_custom_data {};
|
std::map<uint8, ItemInstance*> m_contents; // Zero-based index: min=0, max=9
|
||||||
std::map<std::string, ::Timer> m_timers {};
|
std::map<std::string, std::string> m_custom_data;
|
||||||
|
std::map<std::string, ::Timer> m_timers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-24640
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user