mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 16:28:28 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c6ec2117a |
@@ -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}"
|
||||
}
|
||||
}
|
||||
+10
-81
@@ -1,8 +1,7 @@
|
||||
---
|
||||
|
||||
kind: pipeline
|
||||
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
|
||||
concurrency:
|
||||
@@ -11,88 +10,18 @@ concurrency:
|
||||
volumes:
|
||||
- name: cache
|
||||
host:
|
||||
path: /var/lib/cache-release
|
||||
path: /var/lib/cache
|
||||
|
||||
steps:
|
||||
- name: Build Linux X64
|
||||
image: akkadius/eqemu-server:v14
|
||||
environment:
|
||||
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
|
||||
- name: server-build
|
||||
# Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20
|
||||
image: akkadius/eqemu-server:v11
|
||||
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_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O0 -g -DNDEBUG" -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
|
||||
- curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json
|
||||
- ./bin/tests
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /home/eqemu/.ccache/
|
||||
|
||||
---
|
||||
|
||||
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/
|
||||
|
||||
.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/*
|
||||
|
||||
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
|
||||
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
|
||||
Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator.
|
||||
|
||||
mkdir 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
|
||||
|
||||
|
||||
-3246
File diff suppressed because it is too large
Load Diff
+12
-40
@@ -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})
|
||||
|
||||
@@ -12,37 +12,17 @@ IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 20)
|
||||
SET(CMAKE_CXX_STANDARD 17)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF)
|
||||
OPTION(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON)
|
||||
|
||||
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)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
ADD_DEFINITIONS(-DCRASH_LOGGING)
|
||||
ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17
|
||||
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
|
||||
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)
|
||||
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
|
||||
ENDIF(MSVC)
|
||||
@@ -139,16 +119,10 @@ ELSE()
|
||||
MESSAGE(STATUS "* mbedTLS: MISSING *")
|
||||
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 "**************************************************")
|
||||
|
||||
#options
|
||||
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
|
||||
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
|
||||
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
|
||||
OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
|
||||
@@ -202,6 +176,10 @@ IF(EQEMU_COMMANDS_LOGGING)
|
||||
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
|
||||
ENDIF(EQEMU_COMMANDS_LOGGING)
|
||||
|
||||
IF(EQEMU_ENABLE_BOTS)
|
||||
ADD_DEFINITIONS(-DBOTS)
|
||||
ENDIF(EQEMU_ENABLE_BOTS)
|
||||
|
||||
#database
|
||||
IF(MySQL_FOUND AND MariaDB_FOUND)
|
||||
SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use:
|
||||
@@ -333,10 +311,6 @@ ELSE()
|
||||
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
ENDIF()
|
||||
|
||||
IF (EQEMU_BUILD_STATIC)
|
||||
SET(ZLIB_LIBRARY_LIBS libz.a)
|
||||
ENDIF(EQEMU_BUILD_STATIC)
|
||||
|
||||
MESSAGE(STATUS "")
|
||||
MESSAGE(STATUS "**************************************************")
|
||||
MESSAGE(STATUS "* Library Usage *")
|
||||
@@ -366,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/websocketpp")
|
||||
|
||||
# silence obnoxious deprecation message
|
||||
ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
|
||||
OPTION(EQEMU_BUILD_LOGGING "Build Logging (To speed up compilation)" ON)
|
||||
IF(EQEMU_BUILD_LOGGING)
|
||||
ADD_DEFINITIONS(-DBUILD_LOGGING)
|
||||
ENDIF()
|
||||
|
||||
IF(TLS_LIBRARY_ENABLED)
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS})
|
||||
@@ -401,10 +377,6 @@ IF(PERL_LIBRARY_ENABLED)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
|
||||
ADD_DEFINITIONS(-DEMBPERL)
|
||||
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()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# EQEmulator Core Server
|
||||
| Drone (Linux x64) | Drone (Windows x64) |
|
||||
|:---:|:---:|
|
||||
|[](http://drone.akkadius.com/EQEmu/Server) |[](http://drone.akkadius.com/EQEmu/Server) |
|
||||
|Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) |
|
||||
|:---:|:---:|:---:|
|
||||
|[](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.5)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||
|
||||
add_subdirectory(import)
|
||||
add_subdirectory(export)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||
|
||||
SET(export_sources
|
||||
main.cpp
|
||||
|
||||
@@ -86,7 +86,7 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
content_db.SetMySQL(database);
|
||||
content_db.SetMysql(database.getMySQL());
|
||||
}
|
||||
|
||||
LogSys.SetDatabase(&database)
|
||||
@@ -183,7 +183,7 @@ bool SkillUsable(SharedDatabase *db, int skill_id, int class_id)
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
if (row[0] && Strings::ToInt(row[0]) > 0) {
|
||||
if (row[0] && atoi(row[0]) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level)
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
return Strings::ToInt(row[0]);
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
void ExportSkillCaps(SharedDatabase *db)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||
|
||||
SET(import_sources
|
||||
main.cpp
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
#include "../../common/content/world_content_service.h"
|
||||
#include "../../common/zone_store.h"
|
||||
#include "../../common/path_manager.h"
|
||||
#include "../../common/repositories/base_data_repository.h"
|
||||
#include "../../common/file.h"
|
||||
|
||||
EQEmuLogSys LogSys;
|
||||
WorldContentService content_service;
|
||||
@@ -85,7 +83,7 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
content_db.SetMySQL(database);
|
||||
content_db.SetMysql(database.getMySQL());
|
||||
}
|
||||
|
||||
LogSys.SetDatabase(&database)
|
||||
@@ -243,10 +241,10 @@ void ImportSkillCaps(SharedDatabase *db) {
|
||||
}
|
||||
|
||||
int class_id, skill_id, level, cap;
|
||||
class_id = Strings::ToInt(split[0].c_str());
|
||||
skill_id = Strings::ToInt(split[1].c_str());
|
||||
level = Strings::ToInt(split[2].c_str());
|
||||
cap = Strings::ToInt(split[3].c_str());
|
||||
class_id = atoi(split[0].c_str());
|
||||
skill_id = atoi(split[1].c_str());
|
||||
level = atoi(split[2].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)",
|
||||
class_id, skill_id, level, cap);
|
||||
@@ -257,45 +255,50 @@ void ImportSkillCaps(SharedDatabase *db) {
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ImportBaseData(SharedDatabase *db)
|
||||
{
|
||||
void ImportBaseData(SharedDatabase *db) {
|
||||
LogInfo("Importing Base Data");
|
||||
|
||||
const std::string& file_name = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
|
||||
|
||||
const auto& file_contents = File::GetContents(file_name);
|
||||
if (!file_contents.error.empty()) {
|
||||
LogError("{}", file_contents.error);
|
||||
std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
|
||||
FILE *f = fopen(file.c_str(), "r");
|
||||
if(!f) {
|
||||
LogError("Unable to open {} to read, skipping.", file);
|
||||
return;
|
||||
}
|
||||
|
||||
db->QueryDatabase("DELETE FROM base_data");
|
||||
std::string delete_sql = "DELETE FROM base_data";
|
||||
db->QueryDatabase(delete_sql);
|
||||
|
||||
std::vector<BaseDataRepository::BaseData> v;
|
||||
char buffer[2048];
|
||||
while(fgets(buffer, 2048, f)) {
|
||||
auto split = Strings::Split(buffer, '^');
|
||||
|
||||
auto e = BaseDataRepository::NewEntity();
|
||||
|
||||
for (const auto& line: Strings::Split(file_contents.contents, "\n")) {
|
||||
const auto& line_data = Strings::Split(line, '^');
|
||||
|
||||
if (line_data.size() < 10) {
|
||||
if(split.size() < 10) {
|
||||
continue;
|
||||
}
|
||||
|
||||
e.level = static_cast<uint8_t>(Strings::ToUnsignedInt(line_data[0]));
|
||||
e.class_ = static_cast<uint8_t>(Strings::ToUnsignedInt(line_data[1]));
|
||||
e.hp = Strings::ToFloat(line_data[2]);
|
||||
e.mana = Strings::ToFloat(line_data[3]);
|
||||
e.end = Strings::ToFloat(line_data[4]);
|
||||
e.hp_regen = Strings::ToFloat(line_data[5]);
|
||||
e.end_regen = Strings::ToFloat(line_data[6]);
|
||||
e.hp_fac = Strings::ToFloat(line_data[7]);
|
||||
e.mana_fac = Strings::ToFloat(line_data[8]);
|
||||
e.end_fac = Strings::ToFloat(line_data[9]);
|
||||
std::string sql;
|
||||
int level, class_id;
|
||||
double hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac;
|
||||
|
||||
v.emplace_back(e);
|
||||
level = atoi(split[0].c_str());
|
||||
class_id = atoi(split[1].c_str());
|
||||
hp = atof(split[2].c_str());
|
||||
mana = atof(split[3].c_str());
|
||||
end = atof(split[4].c_str());
|
||||
unk1 = atof(split[5].c_str());
|
||||
unk2 = atof(split[6].c_str());
|
||||
hp_fac = atof(split[7].c_str());
|
||||
mana_fac = atof(split[8].c_str());
|
||||
end_fac = atof(split[9].c_str());
|
||||
|
||||
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)",
|
||||
level, class_id, hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac);
|
||||
|
||||
db->QueryDatabase(sql);
|
||||
}
|
||||
|
||||
BaseDataRepository::InsertMany(*db, v);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ImportDBStrings(SharedDatabase *db) {
|
||||
@@ -336,8 +339,8 @@ void ImportDBStrings(SharedDatabase *db) {
|
||||
int id, type;
|
||||
std::string value;
|
||||
|
||||
id = Strings::ToInt(split[0].c_str());
|
||||
type = Strings::ToInt(split[1].c_str());
|
||||
id = atoi(split[0].c_str());
|
||||
type = atoi(split[1].c_str());
|
||||
|
||||
if(split.size() >= 3) {
|
||||
value = ::Strings::Escape(split[2]);
|
||||
|
||||
+16
-39
@@ -1,4 +1,4 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||
|
||||
SET(common_sources
|
||||
base_packet.cpp
|
||||
@@ -13,10 +13,8 @@ SET(common_sources
|
||||
crc32.cpp
|
||||
database/database_dump_service.cpp
|
||||
database.cpp
|
||||
database_conversions.cpp
|
||||
database_instances.cpp
|
||||
database/database_update_manifest.cpp
|
||||
database/database_update_manifest_bots.cpp
|
||||
database/database_update.cpp
|
||||
dbcore.cpp
|
||||
deity.cpp
|
||||
dynamic_zone_base.cpp
|
||||
@@ -35,11 +33,9 @@ SET(common_sources
|
||||
eq_stream_proxy.cpp
|
||||
eqtime.cpp
|
||||
event_sub.cpp
|
||||
events/player_event_logs.cpp
|
||||
events/player_event_discord_formatter.cpp
|
||||
expedition_lockout_timer.cpp
|
||||
extprofile.cpp
|
||||
discord/discord_manager.cpp
|
||||
discord_manager.cpp
|
||||
faction.cpp
|
||||
file.cpp
|
||||
guild_base.cpp
|
||||
@@ -68,8 +64,6 @@ SET(common_sources
|
||||
path_manager.cpp
|
||||
perl_eqdb.cpp
|
||||
perl_eqdb_res.cpp
|
||||
process/process.cpp
|
||||
process.cpp
|
||||
proc_launcher.cpp
|
||||
profanity_manager.cpp
|
||||
ptimer.cpp
|
||||
@@ -90,7 +84,6 @@ SET(common_sources
|
||||
timer.cpp
|
||||
unix.cpp
|
||||
platform.cpp
|
||||
json/json.hpp
|
||||
json/jsoncpp.cpp
|
||||
zone_store.cpp
|
||||
net/console_server.cpp
|
||||
@@ -188,8 +181,6 @@ SET(repositories
|
||||
repositories/base/base_char_create_combinations_repository.h
|
||||
repositories/base/base_char_create_point_allocations_repository.h
|
||||
repositories/base/base_char_recipe_list_repository.h
|
||||
repositories/base/base_chatchannels_repository.h
|
||||
repositories/base/base_chatchannel_reserved_names_repository.h
|
||||
repositories/base/base_completed_shared_tasks_repository.h
|
||||
repositories/base/base_completed_shared_task_activity_state_repository.h
|
||||
repositories/base/base_completed_shared_task_members_repository.h
|
||||
@@ -204,6 +195,7 @@ SET(repositories
|
||||
repositories/base/base_dynamic_zones_repository.h
|
||||
repositories/base/base_dynamic_zone_members_repository.h
|
||||
repositories/base/base_dynamic_zone_templates_repository.h
|
||||
repositories/base/base_eventlog_repository.h
|
||||
repositories/base/base_expeditions_repository.h
|
||||
repositories/base/base_expedition_lockouts_repository.h
|
||||
repositories/base/base_faction_association_repository.h
|
||||
@@ -222,10 +214,8 @@ SET(repositories
|
||||
repositories/base/base_group_leaders_repository.h
|
||||
repositories/base/base_guilds_repository.h
|
||||
repositories/base/base_guild_ranks_repository.h
|
||||
repositories/base/base_guild_permissions_repository.h
|
||||
repositories/base/base_guild_members_repository.h
|
||||
repositories/base/base_guild_bank_repository.h
|
||||
repositories/base/base_guild_relations_repository.h
|
||||
repositories/base/base_hackers_repository.h
|
||||
repositories/base/base_horses_repository.h
|
||||
repositories/base/base_instance_list_repository.h
|
||||
repositories/base/base_instance_list_player_repository.h
|
||||
@@ -233,6 +223,7 @@ SET(repositories
|
||||
repositories/base/base_inventory_snapshots_repository.h
|
||||
repositories/base/base_ip_exemptions_repository.h
|
||||
repositories/base/base_items_repository.h
|
||||
repositories/base/base_item_tick_repository.h
|
||||
repositories/base/base_ldon_trap_entries_repository.h
|
||||
repositories/base/base_ldon_trap_templates_repository.h
|
||||
repositories/base/base_level_exp_mods_repository.h
|
||||
@@ -270,8 +261,6 @@ SET(repositories
|
||||
repositories/base/base_pets_equipmentset_repository.h
|
||||
repositories/base/base_pets_equipmentset_entries_repository.h
|
||||
repositories/base/base_player_titlesets_repository.h
|
||||
repositories/base/base_player_event_log_settings_repository.h
|
||||
repositories/base/base_player_event_logs_repository.h
|
||||
repositories/base/base_quest_globals_repository.h
|
||||
repositories/base/base_raid_details_repository.h
|
||||
repositories/base/base_raid_members_repository.h
|
||||
@@ -368,8 +357,6 @@ SET(repositories
|
||||
repositories/char_create_combinations_repository.h
|
||||
repositories/char_create_point_allocations_repository.h
|
||||
repositories/char_recipe_list_repository.h
|
||||
repositories/chatchannels_repository.h
|
||||
repositories/chatchannel_reserved_names_repository.h
|
||||
repositories/completed_shared_tasks_repository.h
|
||||
repositories/completed_shared_task_activity_state_repository.h
|
||||
repositories/completed_shared_task_members_repository.h
|
||||
@@ -384,6 +371,7 @@ SET(repositories
|
||||
repositories/dynamic_zones_repository.h
|
||||
repositories/dynamic_zone_members_repository.h
|
||||
repositories/dynamic_zone_templates_repository.h
|
||||
repositories/eventlog_repository.h
|
||||
repositories/expeditions_repository.h
|
||||
repositories/expedition_lockouts_repository.h
|
||||
repositories/faction_association_repository.h
|
||||
@@ -402,10 +390,8 @@ SET(repositories
|
||||
repositories/group_leaders_repository.h
|
||||
repositories/guilds_repository.h
|
||||
repositories/guild_ranks_repository.h
|
||||
repositories/guild_permissions_repository.h
|
||||
repositories/guild_members_repository.h
|
||||
repositories/guild_bank_repository.h
|
||||
repositories/guild_relations_repository.h
|
||||
repositories/hackers_repository.h
|
||||
repositories/horses_repository.h
|
||||
repositories/instance_list_repository.h
|
||||
repositories/instance_list_player_repository.h
|
||||
@@ -413,6 +399,7 @@ SET(repositories
|
||||
repositories/inventory_snapshots_repository.h
|
||||
repositories/ip_exemptions_repository.h
|
||||
repositories/items_repository.h
|
||||
repositories/item_tick_repository.h
|
||||
repositories/ldon_trap_entries_repository.h
|
||||
repositories/ldon_trap_templates_repository.h
|
||||
repositories/level_exp_mods_repository.h
|
||||
@@ -450,8 +437,6 @@ SET(repositories
|
||||
repositories/pets_equipmentset_repository.h
|
||||
repositories/pets_equipmentset_entries_repository.h
|
||||
repositories/player_titlesets_repository.h
|
||||
repositories/player_event_log_settings_repository.h
|
||||
repositories/player_event_logs_repository.h
|
||||
repositories/quest_globals_repository.h
|
||||
repositories/raid_details_repository.h
|
||||
repositories/raid_members_repository.h
|
||||
@@ -497,6 +482,7 @@ SET(repositories
|
||||
SET(common_headers
|
||||
additive_lagged_fibonacci_engine.h
|
||||
base_packet.h
|
||||
base_data.h
|
||||
bodytypes.h
|
||||
classes.h
|
||||
compression.h
|
||||
@@ -513,11 +499,10 @@ SET(common_headers
|
||||
data_verification.h
|
||||
database.h
|
||||
database_schema.h
|
||||
database/database_update.h
|
||||
dbcore.h
|
||||
deity.h
|
||||
discord/discord.h
|
||||
discord/discord_manager.h
|
||||
discord_manager.h
|
||||
dynamic_zone_base.h
|
||||
emu_constants.h
|
||||
emu_limits.h
|
||||
@@ -540,9 +525,7 @@ SET(common_headers
|
||||
eq_stream_locator.h
|
||||
eq_stream_proxy.h
|
||||
eqtime.h
|
||||
events/player_event_logs.h
|
||||
events/player_event_discord_formatter.h
|
||||
events/player_events.h
|
||||
errmsg.h
|
||||
event_sub.h
|
||||
expedition_lockout_timer.h
|
||||
extprofile.h
|
||||
@@ -564,9 +547,10 @@ SET(common_headers
|
||||
item_fieldlist.h
|
||||
item_instance.h
|
||||
json_config.h
|
||||
languages.h
|
||||
light_source.h
|
||||
linked_list.h
|
||||
loot.h
|
||||
loottable.h
|
||||
mail_oplist.h
|
||||
md5.h
|
||||
memory_buffer.h
|
||||
@@ -584,15 +568,12 @@ SET(common_headers
|
||||
packet_functions.h
|
||||
path_manager.cpp
|
||||
platform.h
|
||||
process/process.h
|
||||
process.h
|
||||
proc_launcher.h
|
||||
profanity_manager.h
|
||||
profiler.h
|
||||
ptimer.h
|
||||
queue.h
|
||||
races.h
|
||||
raid.h
|
||||
random.h
|
||||
rdtsc.h
|
||||
rulesys.h
|
||||
@@ -616,11 +597,11 @@ SET(common_headers
|
||||
unix.h
|
||||
useperl.h
|
||||
version.h
|
||||
zone_numbers.h
|
||||
zone_store.h
|
||||
event/event_loop.h
|
||||
event/task.h
|
||||
event/timer.h
|
||||
json/json_archive_single_line.h
|
||||
json/json.h
|
||||
json/json-forwards.h
|
||||
net/console_server.h
|
||||
@@ -669,13 +650,12 @@ SET(common_headers
|
||||
patches/uf_limits.h
|
||||
patches/uf_ops.h
|
||||
patches/uf_structs.h
|
||||
termcolor/rang.hpp
|
||||
stacktrace/backward.hpp
|
||||
StackWalker/StackWalker.h
|
||||
util/memory_stream.h
|
||||
util/directory.h
|
||||
util/uuid.h
|
||||
)
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Event FILES
|
||||
event/event_loop.h
|
||||
@@ -792,8 +772,5 @@ IF (UNIX)
|
||||
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
||||
ENDIF (UNIX)
|
||||
|
||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
||||
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
|
||||
ENDIF()
|
||||
|
||||
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __EQEMU_COMMON_BASE_DATA_H
|
||||
#define __EQEMU_COMMON_BASE_DATA_H
|
||||
|
||||
struct BaseDataStruct
|
||||
{
|
||||
double base_hp;
|
||||
double base_mana;
|
||||
double base_end;
|
||||
double hp_regen;
|
||||
double end_regen;
|
||||
double hp_factor;
|
||||
double mana_factor;
|
||||
double endurance_factor;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -64,6 +64,4 @@ typedef enum {
|
||||
} bodyType;
|
||||
/* bodytypes above 64 make the mob not show up */
|
||||
|
||||
constexpr int format_as(bodyType type) { return static_cast<int>(type); }
|
||||
|
||||
#endif
|
||||
|
||||
+447
-348
File diff suppressed because it is too large
Load Diff
+92
-101
@@ -19,106 +19,97 @@
|
||||
#define CLASSES_CH
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace Class {
|
||||
constexpr uint8 None = 0;
|
||||
constexpr uint8 Warrior = 1;
|
||||
constexpr uint8 Cleric = 2;
|
||||
constexpr uint8 Paladin = 3;
|
||||
constexpr uint8 Ranger = 4;
|
||||
constexpr uint8 ShadowKnight = 5;
|
||||
constexpr uint8 Druid = 6;
|
||||
constexpr uint8 Monk = 7;
|
||||
constexpr uint8 Bard = 8;
|
||||
constexpr uint8 Rogue = 9;
|
||||
constexpr uint8 Shaman = 10;
|
||||
constexpr uint8 Necromancer = 11;
|
||||
constexpr uint8 Wizard = 12;
|
||||
constexpr uint8 Magician = 13;
|
||||
constexpr uint8 Enchanter = 14;
|
||||
constexpr uint8 Beastlord = 15;
|
||||
constexpr uint8 Berserker = 16;
|
||||
constexpr uint8 WarriorGM = 20;
|
||||
constexpr uint8 ClericGM = 21;
|
||||
constexpr uint8 PaladinGM = 22;
|
||||
constexpr uint8 RangerGM = 23;
|
||||
constexpr uint8 ShadowKnightGM = 24;
|
||||
constexpr uint8 DruidGM = 25;
|
||||
constexpr uint8 MonkGM = 26;
|
||||
constexpr uint8 BardGM = 27;
|
||||
constexpr uint8 RogueGM = 28;
|
||||
constexpr uint8 ShamanGM = 29;
|
||||
constexpr uint8 NecromancerGM = 30;
|
||||
constexpr uint8 WizardGM = 31;
|
||||
constexpr uint8 MagicianGM = 32;
|
||||
constexpr uint8 EnchanterGM = 33;
|
||||
constexpr uint8 BeastlordGM = 34;
|
||||
constexpr uint8 BerserkerGM = 35;
|
||||
constexpr uint8 Banker = 40;
|
||||
constexpr uint8 Merchant = 41;
|
||||
constexpr uint8 DiscordMerchant = 59;
|
||||
constexpr uint8 AdventureRecruiter = 60;
|
||||
constexpr uint8 AdventureMerchant = 61;
|
||||
constexpr uint8 LDoNTreasure = 62;
|
||||
constexpr uint8 TributeMaster = 63;
|
||||
constexpr uint8 GuildTributeMaster = 64;
|
||||
constexpr uint8 GuildBanker = 66;
|
||||
constexpr uint8 NorrathsKeepersMerchant = 67;
|
||||
constexpr uint8 DarkReignMerchant = 68;
|
||||
constexpr uint8 FellowshipMaster = 69;
|
||||
constexpr uint8 AlternateCurrencyMerchant = 70;
|
||||
constexpr uint8 MercenaryLiaison = 71;
|
||||
#define WARRIOR 1
|
||||
#define CLERIC 2
|
||||
#define PALADIN 3
|
||||
#define RANGER 4
|
||||
#define SHADOWKNIGHT 5
|
||||
#define DRUID 6
|
||||
#define MONK 7
|
||||
#define BARD 8
|
||||
#define ROGUE 9
|
||||
#define SHAMAN 10
|
||||
#define NECROMANCER 11
|
||||
#define WIZARD 12
|
||||
#define MAGICIAN 13
|
||||
#define ENCHANTER 14
|
||||
#define BEASTLORD 15
|
||||
#define BERSERKER 16
|
||||
#define WARRIORGM 20
|
||||
#define CLERICGM 21
|
||||
#define PALADINGM 22
|
||||
#define RANGERGM 23
|
||||
#define SHADOWKNIGHTGM 24
|
||||
#define DRUIDGM 25
|
||||
#define MONKGM 26
|
||||
#define BARDGM 27
|
||||
#define ROGUEGM 28
|
||||
#define SHAMANGM 29
|
||||
#define NECROMANCERGM 30
|
||||
#define WIZARDGM 31
|
||||
#define MAGICIANGM 32
|
||||
#define ENCHANTERGM 33
|
||||
#define BEASTLORDGM 34
|
||||
#define BERSERKERGM 35
|
||||
#define BANKER 40
|
||||
#define MERCHANT 41
|
||||
#define DISCORD_MERCHANT 59
|
||||
#define ADVENTURE_RECRUITER 60
|
||||
#define ADVENTURE_MERCHANT 61
|
||||
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva
|
||||
#define TRIBUTE_MASTER 63
|
||||
#define GUILD_TRIBUTE_MASTER 64 // not sure
|
||||
#define GUILD_BANKER 66
|
||||
#define NORRATHS_KEEPERS_MERCHANT 67
|
||||
#define DARK_REIGN_MERCHANT 68
|
||||
#define FELLOWSHIP_MASTER 69
|
||||
#define ALT_CURRENCY_MERCHANT 70
|
||||
#define MERCENARY_MASTER 71
|
||||
|
||||
constexpr uint8 PLAYER_CLASS_COUNT = 16;
|
||||
constexpr uint16 ALL_CLASSES_BITMASK = 65535;
|
||||
};
|
||||
|
||||
static std::map<uint8, uint16> player_class_bitmasks = {
|
||||
{Class::Warrior, 1},
|
||||
{Class::Cleric, 2},
|
||||
{Class::Paladin, 4},
|
||||
{Class::Ranger, 8},
|
||||
{Class::ShadowKnight, 16},
|
||||
{Class::Druid, 32},
|
||||
{Class::Monk, 64},
|
||||
{Class::Bard, 128},
|
||||
{Class::Rogue, 256},
|
||||
{Class::Shaman, 512},
|
||||
{Class::Necromancer, 1024},
|
||||
{Class::Wizard, 2048},
|
||||
{Class::Magician, 4096},
|
||||
{Class::Enchanter, 8192},
|
||||
{Class::Beastlord, 16384},
|
||||
{Class::Berserker, 32768},
|
||||
};
|
||||
// player class values
|
||||
#define PLAYER_CLASS_UNKNOWN 0
|
||||
#define PLAYER_CLASS_WARRIOR 1
|
||||
#define PLAYER_CLASS_CLERIC 2
|
||||
#define PLAYER_CLASS_PALADIN 3
|
||||
#define PLAYER_CLASS_RANGER 4
|
||||
#define PLAYER_CLASS_SHADOWKNIGHT 5
|
||||
#define PLAYER_CLASS_DRUID 6
|
||||
#define PLAYER_CLASS_MONK 7
|
||||
#define PLAYER_CLASS_BARD 8
|
||||
#define PLAYER_CLASS_ROGUE 9
|
||||
#define PLAYER_CLASS_SHAMAN 10
|
||||
#define PLAYER_CLASS_NECROMANCER 11
|
||||
#define PLAYER_CLASS_WIZARD 12
|
||||
#define PLAYER_CLASS_MAGICIAN 13
|
||||
#define PLAYER_CLASS_ENCHANTER 14
|
||||
#define PLAYER_CLASS_BEASTLORD 15
|
||||
#define PLAYER_CLASS_BERSERKER 16
|
||||
|
||||
static std::string shadow_knight_class_name = (
|
||||
RuleB(World, UseOldShadowKnightClassExport) ?
|
||||
"Shadowknight" :
|
||||
"Shadow Knight"
|
||||
);
|
||||
#define PLAYER_CLASS_COUNT 16
|
||||
|
||||
static std::map<uint8, std::string> class_names = {
|
||||
{Class::Warrior, "Warrior"},
|
||||
{Class::Cleric, "Cleric"},
|
||||
{Class::Paladin, "Paladin"},
|
||||
{Class::Ranger, "Ranger"},
|
||||
{Class::ShadowKnight, shadow_knight_class_name},
|
||||
{Class::Druid, "Druid"},
|
||||
{Class::Monk, "Monk"},
|
||||
{Class::Bard, "Bard"},
|
||||
{Class::Rogue, "Rogue"},
|
||||
{Class::Shaman, "Shaman"},
|
||||
{Class::Necromancer, "Necromancer"},
|
||||
{Class::Wizard, "Wizard"},
|
||||
{Class::Magician, "Magician"},
|
||||
{Class::Enchanter, "Enchanter"},
|
||||
{Class::Beastlord, "Beastlord"},
|
||||
{Class::Berserker, "Berserker"},
|
||||
};
|
||||
|
||||
// player class bits
|
||||
#define PLAYER_CLASS_UNKNOWN_BIT 0
|
||||
#define PLAYER_CLASS_WARRIOR_BIT 1
|
||||
#define PLAYER_CLASS_CLERIC_BIT 2
|
||||
#define PLAYER_CLASS_PALADIN_BIT 4
|
||||
#define PLAYER_CLASS_RANGER_BIT 8
|
||||
#define PLAYER_CLASS_SHADOWKNIGHT_BIT 16
|
||||
#define PLAYER_CLASS_DRUID_BIT 32
|
||||
#define PLAYER_CLASS_MONK_BIT 64
|
||||
#define PLAYER_CLASS_BARD_BIT 128
|
||||
#define PLAYER_CLASS_ROGUE_BIT 256
|
||||
#define PLAYER_CLASS_SHAMAN_BIT 512
|
||||
#define PLAYER_CLASS_NECROMANCER_BIT 1024
|
||||
#define PLAYER_CLASS_WIZARD_BIT 2048
|
||||
#define PLAYER_CLASS_MAGICIAN_BIT 4096
|
||||
#define PLAYER_CLASS_ENCHANTER_BIT 8192
|
||||
#define PLAYER_CLASS_BEASTLORD_BIT 16384
|
||||
#define PLAYER_CLASS_BERSERKER_BIT 32768
|
||||
|
||||
#define PLAYER_CLASS_ALL_MASK 65535 // was 65536
|
||||
|
||||
|
||||
#define ARMOR_TYPE_UNKNOWN 0
|
||||
@@ -133,12 +124,13 @@ static std::map<uint8, std::string> class_names = {
|
||||
|
||||
|
||||
const char* GetClassIDName(uint8 class_id, 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 GetPlayerClassBit(uint8 class_id);
|
||||
|
||||
uint8 GetPlayerClassValue(uint8 class_id);
|
||||
uint16 GetPlayerClassBit(uint8 class_id);
|
||||
uint8 GetClassIDFromPlayerClassValue(uint32 player_class_value);
|
||||
uint8 GetClassIDFromPlayerClassBit(uint32 player_class_bit);
|
||||
|
||||
bool IsFighterClass(uint8 class_id);
|
||||
bool IsSpellFighterClass(uint8 class_id);
|
||||
@@ -147,8 +139,7 @@ bool IsHybridClass(uint8 class_id);
|
||||
bool IsCasterClass(uint8 class_id);
|
||||
bool IsINTCasterClass(uint8 class_id);
|
||||
bool IsWISCasterClass(uint8 class_id);
|
||||
bool IsHeroicINTCasterClass(uint8 class_id);
|
||||
bool IsHeroicWISCasterClass(uint8 class_id);
|
||||
|
||||
bool IsPlateClass(uint8 class_id);
|
||||
bool IsChainClass(uint8 class_id);
|
||||
bool IsLeatherClass(uint8 class_id);
|
||||
|
||||
@@ -39,15 +39,15 @@ namespace EQEmuCommand {
|
||||
{
|
||||
if (cmd[{"-d", "--debug"}]) {
|
||||
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 << "\nFlags:\n";
|
||||
for (auto &flag: cmd.flags())
|
||||
for (auto &flag : cmd.flags())
|
||||
std::cout << '\t' << flag << std::endl;
|
||||
|
||||
std::cout << "\nParameters:\n";
|
||||
for (auto ¶m: cmd.params())
|
||||
for (auto ¶m : cmd.params())
|
||||
std::cout << '\t' << param.first << " : " << param.second << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -69,22 +69,22 @@ namespace EQEmuCommand {
|
||||
{
|
||||
bool arguments_filled = true;
|
||||
|
||||
int index = 2;
|
||||
for (auto &arg: arguments) {
|
||||
int index = 2;
|
||||
for (auto &arg : arguments) {
|
||||
if (cmd(arg).str().empty() && cmd(index).str().empty()) {
|
||||
arguments_filled = false;
|
||||
}
|
||||
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;
|
||||
for (auto &arg: arguments) {
|
||||
for (auto &arg : arguments) {
|
||||
arguments_string += " " + arg;
|
||||
}
|
||||
|
||||
std::string options_string;
|
||||
for (auto &opt: options) {
|
||||
for (auto &opt : options) {
|
||||
options_string += " " + opt + "\n";
|
||||
}
|
||||
|
||||
@@ -124,6 +124,14 @@ namespace EQEmuCommand {
|
||||
)
|
||||
{
|
||||
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"}]) {
|
||||
std::cout << std::endl;
|
||||
std::cout <<
|
||||
@@ -134,7 +142,9 @@ namespace EQEmuCommand {
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
|
||||
// Get max command length for padding length
|
||||
/**
|
||||
* Get max command length for padding length
|
||||
*/
|
||||
int max_command_length = 0;
|
||||
|
||||
for (auto &it: in_function_map) {
|
||||
@@ -145,14 +155,18 @@ namespace EQEmuCommand {
|
||||
}
|
||||
}
|
||||
|
||||
// Display command menu
|
||||
/**
|
||||
* Display command menu
|
||||
*/
|
||||
std::string command_section;
|
||||
for (auto &it: in_function_map) {
|
||||
description.clear();
|
||||
description = "";
|
||||
|
||||
(it.second)(argc, argv, cmd, description);
|
||||
|
||||
// Print section header
|
||||
/**
|
||||
* Print section header
|
||||
*/
|
||||
std::string command_prefix = it.first.substr(0, it.first.find(":"));
|
||||
|
||||
if (command_prefix.find("test") != std::string::npos) {
|
||||
@@ -164,7 +178,9 @@ namespace EQEmuCommand {
|
||||
std::cout << termcolor::reset << command_prefix << std::endl;
|
||||
}
|
||||
|
||||
// Print commands
|
||||
/**
|
||||
* Print commands
|
||||
*/
|
||||
std::stringstream command;
|
||||
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
|
||||
printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str());
|
||||
@@ -175,15 +191,6 @@ namespace EQEmuCommand {
|
||||
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) {
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "../database.h"
|
||||
#include "../rulesys.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include "../loottable.h"
|
||||
#include "../repositories/content_flags_repository.h"
|
||||
|
||||
|
||||
@@ -119,7 +120,7 @@ std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
@@ -23,17 +23,11 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../loottable.h"
|
||||
#include "../repositories/content_flags_repository.h"
|
||||
|
||||
class Database;
|
||||
|
||||
struct ContentFlags {
|
||||
int16 min_expansion;
|
||||
int16 max_expansion;
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
};
|
||||
|
||||
namespace Expansion {
|
||||
static const int EXPANSION_ALL = -1;
|
||||
static const int EXPANSION_FILTER_MAX = 99;
|
||||
@@ -173,7 +167,7 @@ public:
|
||||
std::vector<std::string> GetContentFlagsDisabled();
|
||||
bool IsContentFlagEnabled(const std::string& content_flag);
|
||||
bool IsContentFlagDisabled(const std::string& content_flag);
|
||||
void SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags);
|
||||
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
|
||||
void ReloadContentFlags();
|
||||
WorldContentService * SetExpansionContext();
|
||||
|
||||
|
||||
+45
-119
@@ -1,94 +1,47 @@
|
||||
#include "global_define.h"
|
||||
#include "eqemu_logsys.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)
|
||||
inline std::string random_string(size_t length)
|
||||
{
|
||||
// can configure multiple endpoints if need be
|
||||
std::vector<std::string> endpoints = {
|
||||
"https://spire.akkadius.com/api/v1/analytics/server-crash-report",
|
||||
// "http://localhost:3010/api/v1/analytics/server-crash-report", // development
|
||||
auto randchar = []() -> char {
|
||||
const char charset[] = "0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
const size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[static_cast<size_t>(std::rand()) % max_index];
|
||||
};
|
||||
std::string str(length, 0);
|
||||
std::generate_n(str.begin(), length, randchar);
|
||||
return str;
|
||||
}
|
||||
|
||||
auto config = EQEmuConfig::get();
|
||||
for (auto &e: endpoints) {
|
||||
uri u(e);
|
||||
std::string execute(const std::string &cmd, bool return_result = true)
|
||||
{
|
||||
std::string random = "/tmp/" + random_string(25);
|
||||
const char *file_name = random.c_str();
|
||||
|
||||
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 (return_result) {
|
||||
#ifdef _WINDOWS
|
||||
std::system((cmd + " > " + file_name + " 2>&1").c_str());
|
||||
#else
|
||||
std::system((cmd + " > " + file_name + " 2>&1").c_str());
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std::system((cmd).c_str());
|
||||
}
|
||||
|
||||
std::string result;
|
||||
|
||||
if (return_result) {
|
||||
std::ifstream file(file_name);
|
||||
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
|
||||
std::remove(file_name);
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
|
||||
@@ -101,30 +54,22 @@ public:
|
||||
EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { }
|
||||
virtual void OnOutput(LPCSTR szText) {
|
||||
char buffer[4096];
|
||||
for (int i = 0; i < 4096; ++i) {
|
||||
if (szText[i] == 0) {
|
||||
for(int i = 0; i < 4096; ++i) {
|
||||
if(szText[i] == 0) {
|
||||
buffer[i] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
if (szText[i] == '\n' || szText[i] == '\r') {
|
||||
if(szText[i] == '\n' || szText[i] == '\r') {
|
||||
buffer[i] = ' ';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
buffer[i] = szText[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::string line = buffer;
|
||||
_lines.push_back(line);
|
||||
|
||||
Log(Logs::General, Logs::Crash, buffer);
|
||||
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)
|
||||
@@ -198,20 +143,7 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
||||
|
||||
if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
|
||||
{
|
||||
EQEmuStackWalker sw;
|
||||
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);
|
||||
}
|
||||
EQEmuStackWalker sw; sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
|
||||
}
|
||||
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
@@ -235,7 +167,7 @@ void set_exception_handler() {
|
||||
|
||||
void print_trace()
|
||||
{
|
||||
bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU");
|
||||
bool does_gdb_exist = execute("gdb -v").find("GNU") != std::string::npos;
|
||||
if (!does_gdb_exist) {
|
||||
LogCrash(
|
||||
"[Error] GDB is not installed, if you want crash dumps on Linux to work properly you will need GDB installed"
|
||||
@@ -244,12 +176,12 @@ void print_trace()
|
||||
}
|
||||
|
||||
auto uid = geteuid();
|
||||
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
|
||||
std::string temp_output_file = "/tmp/dump-output";
|
||||
|
||||
// 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) {
|
||||
bool has_passwordless_sudo = execute("sudo -n true").find("a password is required") == std::string::npos;
|
||||
if (!has_passwordless_sudo) {
|
||||
LogCrash(
|
||||
"[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root."
|
||||
);
|
||||
@@ -278,22 +210,16 @@ void print_trace()
|
||||
abort(); /* If gdb failed to start */
|
||||
}
|
||||
else {
|
||||
waitpid(child_pid, nullptr, 0);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
}
|
||||
|
||||
std::ifstream input(temp_output_file);
|
||||
std::string crash_report;
|
||||
for (std::string line; getline(input, line);) {
|
||||
LogCrash("{}", line);
|
||||
crash_report += fmt::format("{}\n", line);
|
||||
}
|
||||
|
||||
std::remove(temp_output_file.c_str());
|
||||
|
||||
if (RuleB(Analytics, CrashReporting)) {
|
||||
SendCrashReport(crash_report);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ namespace cron
|
||||
{
|
||||
try
|
||||
{
|
||||
return static_cast<cron_int>(Strings::ToUnsignedInt(text.data()));
|
||||
return static_cast<cron_int>(std::stoul(text.data()));
|
||||
}
|
||||
catch (std::exception const & ex)
|
||||
{
|
||||
|
||||
+288
-338
File diff suppressed because it is too large
Load Diff
+25
-15
@@ -34,6 +34,8 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
//atoi is not uint32 or uint32 safe!!!!
|
||||
#define atoul(str) strtoul(str, nullptr, 10)
|
||||
|
||||
class MySQLRequestResult;
|
||||
class Client;
|
||||
@@ -106,6 +108,9 @@ public:
|
||||
bool MoveCharacterToZone(uint32 character_id, uint32 zone_id);
|
||||
bool ReserveName(uint32 account_id, char *name);
|
||||
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp);
|
||||
bool SetHackerFlag(const char *accountname, const char *charactername, const char *hacked);
|
||||
bool SetMQDetectionFlag(const char *accountname, const char *charactername, const char *hacked, const char *zone);
|
||||
bool SetMQDetectionFlag(const char *accountname, const char *charactername, const std::string &hacked, const char *zone);
|
||||
bool UpdateName(const char *oldname, const char *newname);
|
||||
bool CopyCharacter(
|
||||
const std::string& source_character_name,
|
||||
@@ -140,33 +145,33 @@ public:
|
||||
|
||||
/* Instancing */
|
||||
|
||||
bool AddClientToInstance(uint16 instance_id, uint32 character_id);
|
||||
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id);
|
||||
bool AddClientToInstance(uint16 instance_id, uint32 char_id);
|
||||
bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id);
|
||||
bool CheckInstanceExists(uint16 instance_id);
|
||||
bool CheckInstanceExpired(uint16 instance_id);
|
||||
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
|
||||
bool GetUnusedInstanceID(uint16 &instance_id);
|
||||
bool IsGlobalInstance(uint16 instance_id);
|
||||
bool GlobalInstance(uint16 instance_id);
|
||||
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
|
||||
bool RemoveClientsFromInstance(uint16 instance_id);
|
||||
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id);
|
||||
bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id);
|
||||
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
|
||||
|
||||
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
|
||||
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id);
|
||||
uint8_t GetInstanceVersion(uint16 instance_id);
|
||||
uint16 GetInstanceVersion(uint16 instance_id);
|
||||
uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma);
|
||||
uint32 GetInstanceZoneID(uint16 instance_id);
|
||||
uint32 VersionFromInstanceID(uint16 instance_id);
|
||||
uint32 ZoneIDFromInstanceID(uint16 instance_id);
|
||||
|
||||
void AssignGroupToInstance(uint32 gid, uint32 instance_id);
|
||||
void AssignRaidToInstance(uint32 rid, uint32 instance_id);
|
||||
void BuryCorpsesInInstance(uint16 instance_id);
|
||||
void DeleteInstance(uint16 instance_id);
|
||||
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id);
|
||||
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id);
|
||||
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids);
|
||||
void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid);
|
||||
void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid);
|
||||
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list);
|
||||
void PurgeExpiredInstances();
|
||||
void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
|
||||
void CleanupInstanceCorpses();
|
||||
|
||||
/* Adventure related. */
|
||||
|
||||
@@ -189,10 +194,10 @@ public:
|
||||
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
|
||||
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
|
||||
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
|
||||
uint8 GetAgreementFlag(uint32 account_id);
|
||||
uint8 GetAgreementFlag(uint32 acctid);
|
||||
|
||||
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
||||
void SetAgreementFlag(uint32 account_id);
|
||||
void SetAgreementFlag(uint32 acctid);
|
||||
|
||||
int GetIPExemption(std::string account_ip);
|
||||
void SetIPExemption(std::string account_ip, int exemption_amount);
|
||||
@@ -227,11 +232,16 @@ public:
|
||||
|
||||
void PurgeAllDeletedDataBuckets();
|
||||
|
||||
/* Database Conversions 'database_conversions.cpp' */
|
||||
|
||||
bool CheckDatabaseConversions();
|
||||
bool CheckDatabaseConvertCorpseDeblob();
|
||||
bool CheckDatabaseConvertPPDeblob();
|
||||
|
||||
/* Database Variables */
|
||||
|
||||
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();
|
||||
|
||||
/* General Queries */
|
||||
@@ -259,7 +269,7 @@ public:
|
||||
void ClearInvSnapshots(bool from_now = false);
|
||||
|
||||
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
|
||||
void SourceSqlFromUrl(std::string url);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
#include "../eqemu_config.h"
|
||||
#include "../database_schema.h"
|
||||
#include "../file.h"
|
||||
#include "../process/process.h"
|
||||
#include "../termcolor/rang.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@@ -37,12 +35,43 @@
|
||||
#else
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <thread>
|
||||
|
||||
#endif
|
||||
|
||||
#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
|
||||
*/
|
||||
@@ -59,7 +88,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
|
||||
*/
|
||||
bool DatabaseDumpService::IsTarAvailable()
|
||||
{
|
||||
std::string version_output = Process::execute("tar --version");
|
||||
std::string version_output = execute("tar --version");
|
||||
|
||||
return version_output.find("GNU tar") != std::string::npos;
|
||||
}
|
||||
@@ -70,7 +99,7 @@ bool DatabaseDumpService::IsTarAvailable()
|
||||
*/
|
||||
bool DatabaseDumpService::Is7ZipAvailable()
|
||||
{
|
||||
std::string version_output = Process::execute("7z --help");
|
||||
std::string version_output = execute("7z --help");
|
||||
|
||||
return version_output.find("7-Zip") != std::string::npos;
|
||||
}
|
||||
@@ -88,13 +117,11 @@ bool DatabaseDumpService::HasCompressionBinary()
|
||||
*/
|
||||
std::string DatabaseDumpService::GetMySQLVersion()
|
||||
{
|
||||
std::string version_output = Process::execute("mysql --version");
|
||||
std::string version_output = execute("mysql --version");
|
||||
|
||||
return Strings::Trim(version_output);
|
||||
}
|
||||
|
||||
const std::string CREDENTIALS_FILE = "login.my.cnf";
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
@@ -103,66 +130,128 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
|
||||
auto config = EQEmuConfig::get();
|
||||
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
|
||||
return fmt::format(
|
||||
"mysqldump --defaults-extra-file={} {}",
|
||||
CREDENTIALS_FILE,
|
||||
"mysqldump -u {} -p{} -h {} --port={} {}",
|
||||
config->ContentDbUsername,
|
||||
config->ContentDbPassword,
|
||||
config->ContentDbHost,
|
||||
config->ContentDbPort,
|
||||
config->ContentDbName
|
||||
);
|
||||
};
|
||||
|
||||
return fmt::format(
|
||||
"mysqldump --defaults-extra-file={} {}",
|
||||
CREDENTIALS_FILE,
|
||||
"mysqldump -u {} -p{} -h {} --port={} {}",
|
||||
config->DatabaseUsername,
|
||||
config->DatabasePassword,
|
||||
config->DatabaseHost,
|
||||
config->DatabasePort,
|
||||
config->DatabaseDB
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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 Strings::Trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::string DatabaseDumpService::GetBotTablesList()
|
||||
{
|
||||
return Strings::Join(DatabaseSchema::GetBotTables(), " ");
|
||||
}
|
||||
|
||||
std::string DatabaseDumpService::GetMercTablesList()
|
||||
{
|
||||
return Strings::Join(DatabaseSchema::GetMercTables(), " ");
|
||||
std::string tables_list;
|
||||
std::vector<std::string> tables = DatabaseSchema::GetBotTables();
|
||||
for (const auto &table : tables) {
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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 Strings::Trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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 Strings::Trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::string DatabaseDumpService::GetSystemTablesList()
|
||||
{
|
||||
auto system_tables = DatabaseSchema::GetServerTables();
|
||||
auto version_tables = DatabaseSchema::GetVersionTables();
|
||||
std::string tables_list;
|
||||
|
||||
system_tables.insert(
|
||||
std::end(system_tables),
|
||||
std::begin(version_tables),
|
||||
std::end(version_tables)
|
||||
);
|
||||
std::vector<std::string> tables = DatabaseSchema::GetServerTables();
|
||||
for (const auto &table : tables) {
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Join(system_tables, " ");
|
||||
tables = DatabaseSchema::GetVersionTables();
|
||||
for (const auto &table : tables) {
|
||||
tables_list += table + " ";
|
||||
}
|
||||
|
||||
return Strings::Trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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 Strings::Trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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 Strings::Trim(tables_list);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,7 +286,7 @@ std::string DatabaseDumpService::GetDumpFileNameWithPath()
|
||||
return GetSetDumpPath() + GetDumpFileName();
|
||||
}
|
||||
|
||||
void DatabaseDumpService::DatabaseDump()
|
||||
void DatabaseDumpService::Dump()
|
||||
{
|
||||
if (!IsMySQLInstalled()) {
|
||||
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
|
||||
@@ -248,11 +337,6 @@ void DatabaseDumpService::DatabaseDump()
|
||||
dump_descriptor += "-bots";
|
||||
}
|
||||
|
||||
if (IsDumpMercTables()) {
|
||||
tables_to_dump += GetMercTablesList() + " ";
|
||||
dump_descriptor += "-mercs";
|
||||
}
|
||||
|
||||
if (IsDumpSystemTables()) {
|
||||
tables_to_dump += GetSystemTablesList() + " ";
|
||||
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()) {
|
||||
SetDumpFileName(GetDumpFileName() + dump_descriptor);
|
||||
}
|
||||
@@ -296,6 +375,14 @@ void DatabaseDumpService::DatabaseDump()
|
||||
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
|
||||
}
|
||||
|
||||
std::string execute_command = fmt::format(
|
||||
"{} {} {} {}",
|
||||
GetBaseMySQLDumpCommand(),
|
||||
options,
|
||||
tables_to_dump,
|
||||
pipe_file
|
||||
);
|
||||
|
||||
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
|
||||
File::Makedir(GetSetDumpPath());
|
||||
}
|
||||
@@ -303,69 +390,33 @@ void DatabaseDumpService::DatabaseDump()
|
||||
if (IsDumpDropTableSyntaxOnly()) {
|
||||
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' ');
|
||||
|
||||
for (auto &table: tables) {
|
||||
for (auto &table : tables) {
|
||||
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
|
||||
}
|
||||
|
||||
if (tables_to_dump.empty()) {
|
||||
std::cerr << "No tables were specified" << std::endl;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
const auto execute_command = fmt::format(
|
||||
"{} {} {} {}",
|
||||
GetBaseMySQLDumpCommand(),
|
||||
options,
|
||||
tables_to_dump,
|
||||
pipe_file
|
||||
);
|
||||
|
||||
LogInfo("Backing up database [{}]", execute_command);
|
||||
LogInfo("This can take a few minutes depending on the size of your database");
|
||||
LogInfo("LOADING... PLEASE WAIT...");
|
||||
|
||||
BuildCredentialsFile();
|
||||
std::string execution_result = Process::execute(execute_command);
|
||||
if (!execution_result.empty() && IsDumpOutputToConsole()) {
|
||||
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
|
||||
if (!execution_result.empty()) {
|
||||
std::cout << execution_result;
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump));
|
||||
LogInfo("Dumping Tables [{}]", tables_to_dump);
|
||||
}
|
||||
|
||||
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
|
||||
|
||||
if (IsDumpWithCompression() && !IsDumpOutputToConsole()) {
|
||||
if (HasCompressionBinary()) {
|
||||
LogInfo("Compression requested. Compressing dump [{}.sql]", GetDumpFileNameWithPath());
|
||||
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
|
||||
|
||||
if (IsTarAvailable()) {
|
||||
Process::execute(
|
||||
execute(
|
||||
fmt::format(
|
||||
"tar -zcvf {}.tar.gz -C {} {}.sql",
|
||||
GetDumpFileNameWithPath(),
|
||||
@@ -374,10 +425,9 @@ void DatabaseDumpService::DatabaseDump()
|
||||
)
|
||||
);
|
||||
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
|
||||
RemoveSqlBackup();
|
||||
}
|
||||
else if (Is7ZipAvailable()) {
|
||||
Process::execute(
|
||||
execute(
|
||||
fmt::format(
|
||||
"7z a -t7z {}.zip {}.sql",
|
||||
GetDumpFileNameWithPath(),
|
||||
@@ -385,7 +435,6 @@ void DatabaseDumpService::DatabaseDump()
|
||||
)
|
||||
);
|
||||
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
|
||||
RemoveSqlBackup();
|
||||
}
|
||||
else {
|
||||
LogInfo("Compression requested, but no available compression binary was found");
|
||||
@@ -396,8 +445,6 @@ void DatabaseDumpService::DatabaseDump()
|
||||
}
|
||||
}
|
||||
|
||||
RemoveCredentialsFile();
|
||||
|
||||
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
|
||||
// LogDebug("[{}] dump-path", GetSetDumpPath());
|
||||
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
|
||||
@@ -560,68 +607,3 @@ void DatabaseDumpService::SetDumpBotTables(bool dump_bot_tables)
|
||||
{
|
||||
DatabaseDumpService::dump_bot_tables = dump_bot_tables;
|
||||
}
|
||||
|
||||
bool DatabaseDumpService::IsDumpMercTables() const
|
||||
{
|
||||
return dump_merc_tables;
|
||||
}
|
||||
|
||||
void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables)
|
||||
{
|
||||
DatabaseDumpService::dump_merc_tables = dump_merc_tables;
|
||||
}
|
||||
|
||||
void DatabaseDumpService::RemoveSqlBackup()
|
||||
{
|
||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
||||
if (File::Exists(file)) {
|
||||
std::filesystem::remove(file);
|
||||
}
|
||||
|
||||
RemoveCredentialsFile();
|
||||
}
|
||||
|
||||
void DatabaseDumpService::BuildCredentialsFile()
|
||||
{
|
||||
auto config = EQEmuConfig::get();
|
||||
std::ofstream out(CREDENTIALS_FILE);
|
||||
if (out.is_open()) {
|
||||
if (IsDumpContentTables() && !config->ContentDbHost.empty()) {
|
||||
out << "[mysqldump]" << std::endl;
|
||||
out << "user=" << config->ContentDbUsername << std::endl;
|
||||
out << "password=" << config->ContentDbPassword << std::endl;
|
||||
out << "host=" << config->ContentDbHost << std::endl;
|
||||
out << "port=" << config->ContentDbPort << std::endl;
|
||||
out << "default-character-set=utf8" << std::endl;
|
||||
}
|
||||
else {
|
||||
out << "[mysqldump]" << std::endl;
|
||||
out << "user=" << config->DatabaseUsername << std::endl;
|
||||
out << "password=" << config->DatabasePassword << std::endl;
|
||||
out << "host=" << config->DatabaseHost << std::endl;
|
||||
out << "port=" << config->DatabasePort << std::endl;
|
||||
out << "default-character-set=utf8" << std::endl;
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
else {
|
||||
LogError("Failed to open credentials file for writing");
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseDumpService::RemoveCredentialsFile()
|
||||
{
|
||||
if (File::Exists(CREDENTIALS_FILE)) {
|
||||
std::filesystem::remove(CREDENTIALS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseDumpService::IsDumpStaticInstanceData()
|
||||
{
|
||||
return dump_static_instance_data;
|
||||
}
|
||||
|
||||
void DatabaseDumpService::SetDumpStaticInstanceData(bool b)
|
||||
{
|
||||
dump_static_instance_data = b;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
class DatabaseDumpService {
|
||||
public:
|
||||
void DatabaseDump();
|
||||
void Dump();
|
||||
bool IsDumpAllTables() const;
|
||||
void SetDumpAllTables(bool dump_all_tables);
|
||||
bool IsDumpWithNoData() const;
|
||||
@@ -55,11 +55,6 @@ public:
|
||||
void SetDumpStateTables(bool dump_state_tables);
|
||||
bool IsDumpBotTables() const;
|
||||
void SetDumpBotTables(bool dump_bot_tables);
|
||||
bool IsDumpMercTables() const;
|
||||
void SetDumpMercTables(bool dump_bot_tables);
|
||||
|
||||
void SetDumpStaticInstanceData(bool b);
|
||||
bool IsDumpStaticInstanceData();
|
||||
|
||||
private:
|
||||
bool dump_all_tables = false;
|
||||
@@ -75,18 +70,15 @@ private:
|
||||
bool dump_output_to_console = false;
|
||||
bool dump_drop_table_syntax_only = false;
|
||||
bool dump_bot_tables = false;
|
||||
bool dump_merc_tables = false;
|
||||
bool dump_static_instance_data = false;
|
||||
|
||||
std::string dump_path;
|
||||
std::string dump_file_name;
|
||||
|
||||
std::string execute(const std::string &cmd, bool return_result);
|
||||
bool IsMySQLInstalled();
|
||||
std::string GetMySQLVersion();
|
||||
std::string GetBaseMySQLDumpCommand();
|
||||
std::string GetPlayerTablesList();
|
||||
std::string GetBotTablesList();
|
||||
std::string GetMercTablesList();
|
||||
std::string GetSystemTablesList();
|
||||
std::string GetStateTablesList();
|
||||
std::string GetContentTablesList();
|
||||
@@ -97,9 +89,6 @@ private:
|
||||
std::string GetDumpFileNameWithPath();
|
||||
std::string GetSetDumpPath();
|
||||
std::string GetQueryServTables();
|
||||
void RemoveSqlBackup();
|
||||
void BuildCredentialsFile();
|
||||
void RemoveCredentialsFile();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,324 +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(const ManifestEntry& e)
|
||||
{
|
||||
auto results = (e.content_schema_update ? m_content_database : m_database)->QueryDatabase(e.check);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// check if we are running in a terminal
|
||||
bool is_atty()
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
return ::_isatty(_fileno(stdin));
|
||||
#else
|
||||
return isatty(fileno(stdin));
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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);
|
||||
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 = (e.content_schema_update ? m_content_database : 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");
|
||||
|
||||
// if terminal attached then prompt for skip
|
||||
if (is_atty()) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
errored_migration = true;
|
||||
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;
|
||||
}
|
||||
|
||||
DatabaseUpdate *DatabaseUpdate::SetContentDatabase(Database *db)
|
||||
{
|
||||
m_content_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,40 +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
|
||||
bool content_schema_update{}; // if true, this migration is a content schema update and should be ran against the content database
|
||||
};
|
||||
|
||||
struct DatabaseVersion {
|
||||
int server_database_version;
|
||||
int bots_database_version;
|
||||
};
|
||||
|
||||
class DatabaseUpdate {
|
||||
public:
|
||||
DatabaseVersion GetDatabaseVersions();
|
||||
DatabaseVersion GetBinaryDatabaseVersions();
|
||||
void CheckDbUpdates();
|
||||
std::string GetQueryResult(const ManifestEntry& e);
|
||||
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);
|
||||
DatabaseUpdate *SetContentDatabase(Database *db);
|
||||
bool HasPendingUpdates();
|
||||
private:
|
||||
Database *m_database;
|
||||
Database *m_content_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,148 +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;
|
||||
)",
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9041,
|
||||
.description = "2023_12_04_bot_timers.sql",
|
||||
.check = "SHOW COLUMNS FROM `bot_timers` LIKE 'recast_time'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_timers`
|
||||
ADD COLUMN `recast_time` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `timer_value`,
|
||||
ADD COLUMN `is_spell` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `recast_time`,
|
||||
ADD COLUMN `is_disc` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `is_spell`,
|
||||
ADD COLUMN `spell_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `is_disc`,
|
||||
ADD COLUMN `is_item` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `spell_id`,
|
||||
ADD COLUMN `item_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `is_item`;
|
||||
ALTER TABLE `bot_timers`
|
||||
DROP FOREIGN KEY `FK_bot_timers_1`;
|
||||
ALTER TABLE `bot_timers`
|
||||
DROP PRIMARY KEY;
|
||||
ALTER TABLE `bot_timers`
|
||||
ADD PRIMARY KEY (`bot_id`, `timer_id`, `spell_id`, `item_id`);
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9042,
|
||||
.description = "2024_01_27_delete_bot_foreign_keys.sql",
|
||||
.check = "SHOW CREATE TABLE `bot_stances`",
|
||||
.condition = "contains",
|
||||
.match = "FOREIGN",
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_buffs` DROP FOREIGN KEY `FK_bot_buffs_1`;
|
||||
ALTER TABLE `bot_heal_rotations` DROP FOREIGN KEY `FK_bot_heal_rotations`;
|
||||
ALTER TABLE `bot_heal_rotation_members` DROP FOREIGN KEY `FK_bot_heal_rotation_members_1`;
|
||||
ALTER TABLE `bot_heal_rotation_members` DROP FOREIGN KEY `FK_bot_heal_rotation_members_2`;
|
||||
ALTER TABLE `bot_heal_rotation_targets` DROP FOREIGN KEY `FK_bot_heal_rotation_targets`;
|
||||
ALTER TABLE `bot_inventories` DROP FOREIGN KEY `FK_bot_inventories_1`;
|
||||
ALTER TABLE `bot_pets` DROP FOREIGN KEY `FK_bot_pets_1`;
|
||||
ALTER TABLE `bot_pet_buffs` DROP FOREIGN KEY `FK_bot_pet_buffs_1`;
|
||||
ALTER TABLE `bot_pet_inventories` DROP FOREIGN KEY `FK_bot_pet_inventories_1`;
|
||||
ALTER TABLE `bot_stances` DROP FOREIGN KEY `FK_bot_stances_1`;
|
||||
)"
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
// .description = "some_new_migration.sql",
|
||||
// .check = "SHOW COLUMNS FROM `table_name` LIKE 'column_name'",
|
||||
// .condition = "empty",
|
||||
// .match = "",
|
||||
// .sql = R"(
|
||||
//
|
||||
//)"
|
||||
};
|
||||
|
||||
// see struct definitions for what each field does
|
||||
// struct ManifestEntry {
|
||||
// int version{}; // database version of the migration
|
||||
// std::string description{}; // description of the migration ex: "add_new_table" or "add_index_to_table"
|
||||
// std::string check{}; // query that checks against the condition
|
||||
// std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
||||
// std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
||||
// std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
||||
// };
|
||||
File diff suppressed because it is too large
Load Diff
+365
-358
@@ -20,17 +20,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/strings.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/repositories/character_corpses_repository.h"
|
||||
#include "../common/repositories/dynamic_zone_members_repository.h"
|
||||
#include "../common/repositories/dynamic_zones_repository.h"
|
||||
#include "../common/repositories/group_id_repository.h"
|
||||
#include "../common/repositories/instance_list_repository.h"
|
||||
#include "../common/repositories/instance_list_player_repository.h"
|
||||
#include "../common/repositories/raid_members_repository.h"
|
||||
#include "../common/repositories/respawn_times_repository.h"
|
||||
#include "../common/repositories/spawn_condition_values_repository.h"
|
||||
#include "repositories/spawn2_disabled_repository.h"
|
||||
|
||||
|
||||
#include "database.h"
|
||||
|
||||
@@ -50,242 +41,251 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
|
||||
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id)
|
||||
/**
|
||||
* @param instance_id
|
||||
* @param char_id
|
||||
* @return
|
||||
*/
|
||||
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
|
||||
{
|
||||
auto e = InstanceListPlayerRepository::NewEntity();
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `instance_list_player` (id, charid) "
|
||||
"VALUES "
|
||||
"(%lu, %lu)",
|
||||
(unsigned long) instance_id,
|
||||
(unsigned long) char_id
|
||||
);
|
||||
|
||||
e.id = instance_id;
|
||||
e.charid = character_id;
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return InstanceListPlayerRepository::ReplaceOne(*this, e);
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id)
|
||||
bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id)
|
||||
{
|
||||
if (!instance_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto l = InstanceListPlayerRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"id = {} AND charid = {}",
|
||||
instance_id,
|
||||
character_id
|
||||
)
|
||||
);
|
||||
if (l.empty()) {
|
||||
std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::CheckInstanceExists(uint16 instance_id)
|
||||
{
|
||||
if (!instance_id) {
|
||||
return false;
|
||||
}
|
||||
bool Database::CheckInstanceExists(uint16 instance_id) {
|
||||
std::string query = StringFormat(
|
||||
"SELECT "
|
||||
"`id` "
|
||||
"FROM "
|
||||
"`instance_list` "
|
||||
"WHERE "
|
||||
"`id` = %u",
|
||||
instance_id
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
||||
if (!i.id) {
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::CheckInstanceExpired(uint16 instance_id)
|
||||
{
|
||||
if (!instance_id) {
|
||||
|
||||
int32 start_time = 0;
|
||||
int32 duration = 0;
|
||||
uint32 never_expires = 0;
|
||||
|
||||
std::string query = StringFormat(
|
||||
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
|
||||
instance_id
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
||||
if (!i.id) {
|
||||
if (results.RowCount() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i.never_expires) {
|
||||
auto row = results.begin();
|
||||
|
||||
start_time = atoi(row[0]);
|
||||
duration = atoi(row[1]);
|
||||
never_expires = atoi(row[2]);
|
||||
|
||||
if (never_expires == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
timeval tv{};
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
return (i.start_time + i.duration) <= tv.tv_sec;
|
||||
return (start_time + duration) <= tv.tv_sec;
|
||||
|
||||
}
|
||||
|
||||
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
|
||||
{
|
||||
auto e = InstanceListRepository::NewEntity();
|
||||
std::string query = StringFormat(
|
||||
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
|
||||
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
|
||||
instance_id,
|
||||
zone_id,
|
||||
version,
|
||||
duration
|
||||
);
|
||||
|
||||
e.id = instance_id;
|
||||
e.zone = zone_id;
|
||||
e.version = version;
|
||||
e.start_time = std::time(nullptr);
|
||||
e.duration = duration;
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return InstanceListRepository::InsertOne(*this, e).id;
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
||||
{
|
||||
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
|
||||
uint32 max_instance_id = 32000;
|
||||
uint32 max = 32000;
|
||||
|
||||
// sanity check reserved
|
||||
if (max_reserved_instance_id >= max_instance_id) {
|
||||
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 > {}",
|
||||
std::string query = StringFormat(
|
||||
"SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
|
||||
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);
|
||||
|
||||
// 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 = 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) {
|
||||
instance_id = 0;
|
||||
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 (!row[0]) {
|
||||
instance_id = max_reserved_instance_id + 1;
|
||||
return true;
|
||||
if (max_reserved_instance_id > max) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
max_reserved_instance_id++;
|
||||
}
|
||||
|
||||
// check that id is within limits
|
||||
if (Strings::ToInt(row[0]) <= max_instance_id) {
|
||||
instance_id = Strings::ToInt(row[0]);
|
||||
return true;
|
||||
}
|
||||
instance_id = max_reserved_instance_id;
|
||||
|
||||
// no available instance ids
|
||||
instance_id = 0;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::IsGlobalInstance(uint16 instance_id)
|
||||
bool Database::GlobalInstance(uint16 instance_id)
|
||||
{
|
||||
if (!instance_id) {
|
||||
return false;
|
||||
}
|
||||
std::string query = StringFormat(
|
||||
"SELECT "
|
||||
"is_global "
|
||||
"FROM "
|
||||
"instance_list "
|
||||
"WHERE "
|
||||
"id = %u "
|
||||
"LIMIT 1 ",
|
||||
instance_id
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
||||
if (!i.id) {
|
||||
if (!results.Success())
|
||||
return false;
|
||||
}
|
||||
|
||||
return i.is_global;
|
||||
if (results.RowCount() == 0)
|
||||
return false;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return (atoi(row[0]) == 1) ? true : false;
|
||||
}
|
||||
|
||||
bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id)
|
||||
{
|
||||
return InstanceListPlayerRepository::DeleteWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"id = {} AND charid = {}",
|
||||
instance_id,
|
||||
char_id
|
||||
)
|
||||
);
|
||||
std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu",
|
||||
(unsigned long)instance_id, (unsigned long)char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
|
||||
bool Database::RemoveClientsFromInstance(uint16 instance_id)
|
||||
{
|
||||
return InstanceListPlayerRepository::DeleteOne(*this, instance_id);
|
||||
std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id)
|
||||
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id)
|
||||
{
|
||||
//we are not saved to this instance so set our instance to 0
|
||||
if (!IsGlobalInstance(instance_id) && !CheckInstanceByCharID(instance_id, character_id)) {
|
||||
if (!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CheckInstanceExpired(instance_id)) {
|
||||
if (CheckInstanceExpired(instance_id))
|
||||
{
|
||||
DeleteInstance(instance_id);
|
||||
return false;
|
||||
}
|
||||
@@ -295,102 +295,99 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id)
|
||||
|
||||
bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id)
|
||||
{
|
||||
auto l = InstanceListRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"id = {} AND zone = {}",
|
||||
instance_id,
|
||||
zone_id
|
||||
)
|
||||
);
|
||||
if (l.empty()) {
|
||||
|
||||
std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u", instance_id, zone_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16 Database::GetInstanceID(uint32 zone_id, uint32 character_id, int16 version)
|
||||
uint16 Database::GetInstanceID(uint32 zone, uint32 character_id, int16 version)
|
||||
{
|
||||
if (!zone_id) {
|
||||
if (!zone)
|
||||
return 0;
|
||||
|
||||
std::string query = StringFormat(
|
||||
"SELECT "
|
||||
"instance_list.id "
|
||||
"FROM "
|
||||
"instance_list, "
|
||||
"instance_list_player "
|
||||
"WHERE "
|
||||
"instance_list.zone = %u "
|
||||
"AND instance_list.version = %u "
|
||||
"AND instance_list.id = instance_list_player.id "
|
||||
"AND instance_list_player.charid = %u "
|
||||
"LIMIT 1; ",
|
||||
zone,
|
||||
version,
|
||||
character_id
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
uint16 Database::GetInstanceVersion(uint16 instance_id) {
|
||||
if (instance_id == 0)
|
||||
return 0;
|
||||
|
||||
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
|
||||
{
|
||||
uint32 start_time = 0;
|
||||
uint32 duration = 0;
|
||||
uint32 never_expires = 0;
|
||||
|
||||
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
{
|
||||
is_perma = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto query = fmt::format(
|
||||
"SELECT instance_list.id FROM "
|
||||
"instance_list, instance_list_player WHERE "
|
||||
"instance_list.zone = {} AND "
|
||||
"instance_list.version = {} AND "
|
||||
"instance_list.id = instance_list_player.id AND "
|
||||
"instance_list_player.charid = {} "
|
||||
"LIMIT 1;",
|
||||
zone_id,
|
||||
version,
|
||||
character_id
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
if (results.RowCount() == 0)
|
||||
{
|
||||
is_perma = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return static_cast<uint16>(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)
|
||||
{
|
||||
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) {
|
||||
if (never_expires == 1)
|
||||
{
|
||||
is_perma = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -399,194 +396,204 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
|
||||
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
return ((i.start_time + i.duration) - tv.tv_sec);
|
||||
return ((start_time + duration) - tv.tv_sec);
|
||||
}
|
||||
|
||||
uint32 Database::GetInstanceZoneID(uint16 instance_id)
|
||||
uint32 Database::VersionFromInstanceID(uint16 instance_id)
|
||||
{
|
||||
if (!instance_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
||||
if (!i.id) {
|
||||
return 0;
|
||||
}
|
||||
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return i.zone;
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
uint32 Database::ZoneIDFromInstanceID(uint16 instance_id)
|
||||
{
|
||||
|
||||
std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
|
||||
{
|
||||
auto zone_id = GetInstanceZoneID(instance_id);
|
||||
auto version = GetInstanceVersion(instance_id);
|
||||
|
||||
auto l = GroupIdRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"groupid = {}",
|
||||
group_id
|
||||
)
|
||||
);
|
||||
if (l.empty()) {
|
||||
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
|
||||
uint16 version = VersionFromInstanceID(instance_id);
|
||||
|
||||
std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& e : l) {
|
||||
if (!GetInstanceID(zone_id, e.charid, version)) {
|
||||
AddClientToInstance(instance_id, e.charid);
|
||||
}
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
uint32 charid = atoi(row[0]);
|
||||
if (GetInstanceID(zone_id, charid, version) == 0)
|
||||
AddClientToInstance(instance_id, charid);
|
||||
}
|
||||
}
|
||||
|
||||
void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
|
||||
{
|
||||
auto zone_id = GetInstanceZoneID(instance_id);
|
||||
auto version = GetInstanceVersion(instance_id);
|
||||
|
||||
auto l = RaidMembersRepository::GetWhere(
|
||||
*this,
|
||||
uint32 zone_id = ZoneIDFromInstanceID(instance_id);
|
||||
uint16 version = VersionFromInstanceID(instance_id);
|
||||
|
||||
std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
uint32 charid = atoi(row[0]);
|
||||
if (GetInstanceID(zone_id, charid, version) == 0)
|
||||
AddClientToInstance(instance_id, charid);
|
||||
}
|
||||
}
|
||||
|
||||
void Database::BuryCorpsesInInstance(uint16 instance_id) {
|
||||
QueryDatabase(
|
||||
fmt::format(
|
||||
"raidid = {}",
|
||||
raid_id
|
||||
"UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id = {}",
|
||||
instance_id
|
||||
)
|
||||
);
|
||||
if (l.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& e : l) {
|
||||
if (!GetInstanceID(zone_id, e.charid, version)) {
|
||||
AddClientToInstance(instance_id, e.charid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database::DeleteInstance(uint16 instance_id)
|
||||
{
|
||||
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);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||
|
||||
CharacterCorpsesRepository::BuryInstance(*this, instance_id);
|
||||
BuryCorpsesInInstance(instance_id);
|
||||
}
|
||||
|
||||
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id)
|
||||
void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid)
|
||||
{
|
||||
auto instance_id = GetInstanceID(zone_id, character_id, version);
|
||||
if (instance_id) {
|
||||
uint16 id = GetInstanceID(zone, charid, version);
|
||||
if (id != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
char ln[128];
|
||||
memset(ln, 0, 128);
|
||||
GetGroupLeadershipInfo(group_id, ln);
|
||||
GetGroupLeadershipInfo(gid, ln);
|
||||
uint32 l_charid = GetCharacterID((const char*)ln);
|
||||
uint16 l_id = GetInstanceID(zone, l_charid, version);
|
||||
|
||||
auto group_leader_id = GetCharacterID((const char*)ln);
|
||||
auto group_leader_instance_id = GetInstanceID(zone_id, group_leader_id, version);
|
||||
|
||||
if (!group_leader_instance_id) {
|
||||
if (l_id == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
AddClientToInstance(group_leader_instance_id, character_id);
|
||||
AddClientToInstance(l_id, charid);
|
||||
}
|
||||
|
||||
void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id)
|
||||
void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid)
|
||||
{
|
||||
uint16 instance_id = GetInstanceID(zone_id, character_id, version);
|
||||
if (instance_id) {
|
||||
uint16 id = GetInstanceID(zone, charid, version);
|
||||
if (id != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id));
|
||||
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
|
||||
uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid));
|
||||
uint16 l_id = GetInstanceID(zone, l_charid, version);
|
||||
|
||||
if (!raid_leader_instance_id) {
|
||||
if (l_id == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
AddClientToInstance(raid_leader_instance_id, character_id);
|
||||
AddClientToInstance(l_id, charid);
|
||||
}
|
||||
|
||||
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids)
|
||||
{
|
||||
auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id));
|
||||
if (l.empty()) {
|
||||
return;
|
||||
}
|
||||
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list) {
|
||||
|
||||
for (const auto& e : l) {
|
||||
character_ids.push_back(e.charid);
|
||||
}
|
||||
std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
return;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
charid_list.push_back(atoi(row[0]));
|
||||
}
|
||||
|
||||
void Database::PurgeExpiredInstances()
|
||||
{
|
||||
|
||||
/**
|
||||
* Delay purging by a day so that we can continue using adjacent free instance id's
|
||||
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but
|
||||
* has not been fully de-allocated
|
||||
*/
|
||||
auto l = InstanceListRepository::GetWhere(
|
||||
*this,
|
||||
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0"
|
||||
);
|
||||
if (l.empty()) {
|
||||
std::string query =
|
||||
SQL(
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
instance_list
|
||||
where
|
||||
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
|
||||
and never_expires = 0
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> instance_ids;
|
||||
for (const auto& e : l) {
|
||||
instance_ids.emplace_back(std::to_string(e.id));
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
instance_ids.emplace_back(row[0]);
|
||||
}
|
||||
|
||||
const auto imploded_instance_ids = Strings::Implode(",", instance_ids);
|
||||
std::string imploded_instance_ids = Strings::Implode(",", instance_ids);
|
||||
|
||||
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
|
||||
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
|
||||
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
|
||||
QueryDatabase(fmt::format("DELETE FROM instance_list WHERE id IN ({})", imploded_instance_ids));
|
||||
QueryDatabase(fmt::format("DELETE FROM instance_list_player WHERE id IN ({})", imploded_instance_ids));
|
||||
QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
}
|
||||
|
||||
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||
{
|
||||
auto i = InstanceListRepository::FindOne(*this, instance_id);
|
||||
if (!i.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
i.start_time = std::time(nullptr);
|
||||
i.duration = new_duration;
|
||||
|
||||
InstanceListRepository::UpdateOne(*this, i);
|
||||
}
|
||||
|
||||
void Database::CleanupInstanceCorpses() {
|
||||
auto l = InstanceListRepository::GetWhere(
|
||||
*this,
|
||||
"never_expires = 0"
|
||||
);
|
||||
|
||||
if (l.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> instance_ids;
|
||||
for (const auto& e : l) {
|
||||
instance_ids.emplace_back(std::to_string(e.id));
|
||||
}
|
||||
|
||||
const auto imploded_instance_ids = Strings::Implode(",", instance_ids);
|
||||
|
||||
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
|
||||
std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), "
|
||||
"duration=%u WHERE id=%u", new_duration, instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
}
|
||||
|
||||
+11
-36
@@ -66,12 +66,11 @@ namespace DatabaseSchema {
|
||||
{"character_potionbelt", "id"},
|
||||
{"character_skills", "id"},
|
||||
{"character_spells", "id"},
|
||||
{"character_stats_record", "character_id"},
|
||||
{"character_task_timers", "character_id"},
|
||||
{"character_tasks", "charid"},
|
||||
{"character_tribute", "character_id"},
|
||||
{"character_tribute", "id"},
|
||||
{"completed_tasks", "charid"},
|
||||
{"data_buckets", "character_id"},
|
||||
{"data_buckets", "id"},
|
||||
{"faction_values", "char_id"},
|
||||
{"friends", "charid"},
|
||||
{"guild_members", "char_id"},
|
||||
@@ -135,7 +134,6 @@ namespace DatabaseSchema {
|
||||
"character_potionbelt",
|
||||
"character_skills",
|
||||
"character_spells",
|
||||
"character_stats_record",
|
||||
"character_task_timers",
|
||||
"character_tasks",
|
||||
"character_tribute",
|
||||
@@ -146,10 +144,8 @@ namespace DatabaseSchema {
|
||||
"friends",
|
||||
"guild_bank",
|
||||
"guild_members",
|
||||
"guild_permissions",
|
||||
"guild_ranks",
|
||||
"guild_relations",
|
||||
"guild_tributes",
|
||||
"guilds",
|
||||
"instance_list_player",
|
||||
"inventory",
|
||||
@@ -260,9 +256,7 @@ namespace DatabaseSchema {
|
||||
{
|
||||
return {
|
||||
"chatchannels",
|
||||
"chatchannel_reserved_names",
|
||||
"command_settings",
|
||||
"command_subsettings",
|
||||
"content_flags",
|
||||
"db_str",
|
||||
"eqtime",
|
||||
@@ -327,17 +321,18 @@ namespace DatabaseSchema {
|
||||
"discord_webhooks",
|
||||
"dynamic_zone_members",
|
||||
"dynamic_zones",
|
||||
"eventlog",
|
||||
"expedition_lockouts",
|
||||
"expeditions",
|
||||
"gm_ips",
|
||||
"group_id",
|
||||
"group_leaders",
|
||||
"hackers",
|
||||
"instance_list",
|
||||
"ip_exemptions",
|
||||
"item_tick",
|
||||
"lfguild",
|
||||
"merc_buffs",
|
||||
"merchantlist_temp",
|
||||
"mercs",
|
||||
"object_contents",
|
||||
"raid_details",
|
||||
"raid_leaders",
|
||||
@@ -346,9 +341,6 @@ namespace DatabaseSchema {
|
||||
"respawn_times",
|
||||
"saylink",
|
||||
"server_scheduled_events",
|
||||
"spawn2_disabled",
|
||||
"player_event_log_settings",
|
||||
"player_event_logs",
|
||||
"shared_task_activity_state",
|
||||
"shared_task_dynamic_zones",
|
||||
"shared_task_members",
|
||||
@@ -398,6 +390,9 @@ namespace DatabaseSchema {
|
||||
"bot_command_settings",
|
||||
"bot_create_combinations",
|
||||
"bot_data",
|
||||
"bot_group_members",
|
||||
"bot_groups",
|
||||
"bot_guild_members",
|
||||
"bot_heal_rotation_members",
|
||||
"bot_heal_rotation_targets",
|
||||
"bot_heal_rotations",
|
||||
@@ -408,31 +403,11 @@ namespace DatabaseSchema {
|
||||
"bot_pet_inventories",
|
||||
"bot_pets",
|
||||
"bot_spell_casting_chances",
|
||||
"bot_spell_settings",
|
||||
"bot_spells_entries",
|
||||
"bot_stances",
|
||||
"bot_timers"
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> GetMercTables()
|
||||
{
|
||||
return {
|
||||
"merc_armorinfo",
|
||||
"merc_inventory",
|
||||
"merc_merchant_entries",
|
||||
"merc_merchant_template_entries",
|
||||
"merc_merchant_templates",
|
||||
"merc_name_types",
|
||||
"merc_npc_types",
|
||||
"merc_spell_list_entries",
|
||||
"merc_spell_lists",
|
||||
"merc_stance_entries",
|
||||
"merc_stats",
|
||||
"merc_subtypes",
|
||||
"merc_templates",
|
||||
"merc_types",
|
||||
"merc_weaponinfo"
|
||||
"bot_timers",
|
||||
"vw_bot_character_mobs",
|
||||
"vw_bot_groups"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+53
-190
@@ -8,11 +8,11 @@
|
||||
|
||||
#include "dbcore.h"
|
||||
|
||||
#include <errmsg.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <mysqld_error.h>
|
||||
#include <string.h>
|
||||
#include "strings.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
@@ -34,16 +34,14 @@
|
||||
|
||||
DBcore::DBcore()
|
||||
{
|
||||
mysql = mysql_init(nullptr);
|
||||
mysqlOwner = true;
|
||||
pHost = nullptr;
|
||||
pUser = nullptr;
|
||||
pPassword = nullptr;
|
||||
pDatabase = nullptr;
|
||||
pCompress = false;
|
||||
pSSL = false;
|
||||
pStatus = Closed;
|
||||
m_mutex = new Mutex;
|
||||
mysql_init(&mysql);
|
||||
pHost = nullptr;
|
||||
pUser = nullptr;
|
||||
pPassword = nullptr;
|
||||
pDatabase = nullptr;
|
||||
pCompress = false;
|
||||
pSSL = false;
|
||||
pStatus = Closed;
|
||||
}
|
||||
|
||||
DBcore::~DBcore()
|
||||
@@ -53,10 +51,16 @@ DBcore::~DBcore()
|
||||
* are re-using the default database connection pointer when we dont have an
|
||||
* external configuration setup ex: (content_database)
|
||||
*/
|
||||
if (mysqlOwner) {
|
||||
mysql_close(mysql);
|
||||
std::string mysql_connection_host;
|
||||
if (mysql.host) {
|
||||
mysql_connection_host = mysql.host;
|
||||
}
|
||||
|
||||
if (GetOriginHost() != mysql_connection_host) {
|
||||
return;
|
||||
}
|
||||
|
||||
mysql_close(&mysql);
|
||||
safe_delete_array(pHost);
|
||||
safe_delete_array(pUser);
|
||||
safe_delete_array(pPassword);
|
||||
@@ -66,21 +70,20 @@ DBcore::~DBcore()
|
||||
// Sends the MySQL server a keepalive
|
||||
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
|
||||
return;
|
||||
}
|
||||
mysql_ping(mysql);
|
||||
m_mutex->unlock();
|
||||
mysql_ping(&mysql);
|
||||
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 r;
|
||||
return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
@@ -92,16 +95,18 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
BenchTimer timer;
|
||||
timer.reset();
|
||||
|
||||
LockMutex lock(m_mutex);
|
||||
LockMutex lock(&MDatabase);
|
||||
|
||||
// Reconnect if we are not connected before hand.
|
||||
if (pStatus != Connected) {
|
||||
Open();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// request query. != 0 indicates some kind of error.
|
||||
if (mysql_real_query(mysql, query, querylen) != 0) {
|
||||
unsigned int errorNumber = mysql_errno(mysql);
|
||||
if (mysql_real_query(&mysql, query, querylen) != 0) {
|
||||
unsigned int errorNumber = mysql_errno(&mysql);
|
||||
|
||||
if (errorNumber == CR_SERVER_GONE_ERROR) {
|
||||
pStatus = Error;
|
||||
@@ -125,26 +130,26 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
|
||||
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];
|
||||
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
|
||||
*/
|
||||
if (mysql_errno(mysql) > 0 && query[0] != '\0') {
|
||||
LogMySQLError("MySQL Error ({}) [{}] Query [{}]", mysql_errno(mysql), mysql_error(mysql), query);
|
||||
if (mysql_errno(&mysql) > 0 && strlen(query) > 0) {
|
||||
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.
|
||||
MYSQL_RES *res = mysql_store_result(mysql);
|
||||
MYSQL_RES *res = mysql_store_result(&mysql);
|
||||
uint32 rowCount = 0;
|
||||
|
||||
if (res != nullptr) {
|
||||
@@ -153,16 +158,16 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
|
||||
MySQLRequestResult requestResult(
|
||||
res,
|
||||
(uint32) mysql_affected_rows(mysql),
|
||||
(uint32) mysql_affected_rows(&mysql),
|
||||
rowCount,
|
||||
(uint32) mysql_field_count(mysql),
|
||||
(uint32) mysql_insert_id(mysql)
|
||||
(uint32) mysql_field_count(&mysql),
|
||||
(uint32) mysql_insert_id(&mysql)
|
||||
);
|
||||
|
||||
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
||||
if ((strncasecmp(query, "select", 6) == 0)) {
|
||||
LogMySQLQuery(
|
||||
"{0} -- ({1} row{2} returned) ({3}s)",
|
||||
"{0}; -- ({1} row{2} returned) ({3}s)",
|
||||
query,
|
||||
requestResult.RowCount(),
|
||||
requestResult.RowCount() == 1 ? "" : "s",
|
||||
@@ -171,7 +176,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
}
|
||||
else {
|
||||
LogMySQLQuery(
|
||||
"{0} -- ({1} row{2} affected) ({3}s)",
|
||||
"{0}; -- ({1} row{2} affected) ({3}s)",
|
||||
query,
|
||||
requestResult.RowsAffected(),
|
||||
requestResult.RowsAffected() == 1 ? "" : "s",
|
||||
@@ -202,7 +207,7 @@ uint32 DBcore::DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen)
|
||||
{
|
||||
// No good reason to lock the DB, we only need it in the first place to check char encoding.
|
||||
// LockMutex lock(&MDatabase);
|
||||
return mysql_real_escape_string(mysql, tobuf, frombuf, fromlen);
|
||||
return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen);
|
||||
}
|
||||
|
||||
bool DBcore::Open(
|
||||
@@ -217,7 +222,7 @@ bool DBcore::Open(
|
||||
bool iSSL
|
||||
)
|
||||
{
|
||||
LockMutex lock(m_mutex);
|
||||
LockMutex lock(&MDatabase);
|
||||
safe_delete_array(pHost);
|
||||
safe_delete_array(pUser);
|
||||
safe_delete_array(pPassword);
|
||||
@@ -237,13 +242,13 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
|
||||
if (errbuf) {
|
||||
errbuf[0] = 0;
|
||||
}
|
||||
LockMutex lock(m_mutex);
|
||||
LockMutex lock(&MDatabase);
|
||||
if (GetStatus() == Connected) {
|
||||
return true;
|
||||
}
|
||||
if (GetStatus() == Error) {
|
||||
mysql_close(mysql);
|
||||
mysql_init(mysql); // Initialize structure again
|
||||
mysql_close(&mysql);
|
||||
mysql_init(&mysql); // Initialize structure again
|
||||
}
|
||||
if (!pHost) {
|
||||
return false;
|
||||
@@ -260,7 +265,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
|
||||
if (pSSL) {
|
||||
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;
|
||||
|
||||
std::string connected_origin_host = pHost;
|
||||
@@ -270,16 +275,21 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
|
||||
}
|
||||
else {
|
||||
if (errnum) {
|
||||
*errnum = mysql_errno(mysql);
|
||||
*errnum = mysql_errno(&mysql);
|
||||
}
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DBcore::SetMysql(MYSQL *mysql)
|
||||
{
|
||||
DBcore::mysql = *mysql;
|
||||
}
|
||||
|
||||
const std::string &DBcore::GetOriginHost() const
|
||||
{
|
||||
return origin_host;
|
||||
@@ -289,150 +299,3 @@ void DBcore::SetOriginHost(const std::string &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
-33
@@ -12,10 +12,6 @@
|
||||
|
||||
#include <mysql.h>
|
||||
#include <string.h>
|
||||
#include <mutex>
|
||||
|
||||
#define CR_SERVER_GONE_ERROR 2006
|
||||
#define CR_SERVER_LOST 2013
|
||||
|
||||
class DBcore {
|
||||
public:
|
||||
@@ -27,26 +23,19 @@ public:
|
||||
~DBcore();
|
||||
eStatus GetStatus() { return pStatus; }
|
||||
MySQLRequestResult QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce = true);
|
||||
MySQLRequestResult QueryDatabase(const std::string& query, bool retryOnFailureOnce = true);
|
||||
MySQLRequestResult QueryDatabaseMulti(const std::string &query);
|
||||
MySQLRequestResult QueryDatabase(std::string query, bool retryOnFailureOnce = true);
|
||||
void TransactionBegin();
|
||||
void TransactionCommit();
|
||||
void TransactionRollback();
|
||||
std::string Escape(const std::string& s);
|
||||
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
|
||||
void ping();
|
||||
MYSQL *getMySQL() { return &mysql; }
|
||||
void SetMysql(MYSQL *mysql);
|
||||
|
||||
const std::string &GetOriginHost() const;
|
||||
void SetOriginHost(const std::string &origin_host);
|
||||
|
||||
bool DoesTableExist(const std::string& table_name);
|
||||
|
||||
void SetMySQL(const DBcore &o)
|
||||
{
|
||||
mysql = o.mysql;
|
||||
mysqlOwner = false;
|
||||
}
|
||||
void SetMutex(Mutex *mutex);
|
||||
bool DoesTableExist(std::string table_name);
|
||||
|
||||
protected:
|
||||
bool Open(
|
||||
@@ -64,13 +53,10 @@ protected:
|
||||
private:
|
||||
bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr);
|
||||
|
||||
MYSQL* mysql;
|
||||
bool mysqlOwner;
|
||||
Mutex *m_mutex;
|
||||
MYSQL mysql;
|
||||
Mutex MDatabase;
|
||||
eStatus pStatus;
|
||||
|
||||
std::mutex m_query_lock{};
|
||||
|
||||
std::string origin_host;
|
||||
|
||||
char *pHost;
|
||||
@@ -81,20 +67,8 @@ private:
|
||||
uint32 pPort;
|
||||
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
|
||||
|
||||
|
||||
+122
-72
@@ -11,7 +11,7 @@
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
@@ -19,81 +19,131 @@
|
||||
|
||||
#include "deity.h"
|
||||
|
||||
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
|
||||
|
||||
EQ::deity::DeityTypeBit EQ::deity::ConvertDeityTypeToDeityTypeBit(DeityType deity_type)
|
||||
{
|
||||
switch (deity_type) {
|
||||
case DeityBertoxxulous:
|
||||
return bit_DeityBertoxxulous;
|
||||
case DeityBrellSirilis:
|
||||
return bit_DeityBrellSirilis;
|
||||
case DeityCazicThule:
|
||||
return bit_DeityCazicThule;
|
||||
case DeityErollisiMarr:
|
||||
return bit_DeityErollisiMarr;
|
||||
case DeityBristlebane:
|
||||
return bit_DeityBristlebane;
|
||||
case DeityInnoruuk:
|
||||
return bit_DeityInnoruuk;
|
||||
case DeityKarana:
|
||||
return bit_DeityKarana;
|
||||
case DeityMithanielMarr:
|
||||
return bit_DeityMithanielMarr;
|
||||
case DeityPrexus:
|
||||
return bit_DeityPrexus;
|
||||
case DeityQuellious:
|
||||
return bit_DeityQuellious;
|
||||
case DeityRallosZek:
|
||||
return bit_DeityRallosZek;
|
||||
case DeityRodcetNife:
|
||||
return bit_DeityRodcetNife;
|
||||
case DeitySolusekRo:
|
||||
return bit_DeitySolusekRo;
|
||||
case DeityTheTribunal:
|
||||
return bit_DeityTheTribunal;
|
||||
case DeityTunare:
|
||||
return bit_DeityTunare;
|
||||
case DeityVeeshan:
|
||||
return bit_DeityVeeshan;
|
||||
case DeityAgnostic_LB:
|
||||
case DeityAgnostic:
|
||||
return bit_DeityAgnostic;
|
||||
default:
|
||||
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" }
|
||||
case DeityBertoxxulous:
|
||||
return bit_DeityBertoxxulous;
|
||||
case DeityBrellSirilis:
|
||||
return bit_DeityBrellSirilis;
|
||||
case DeityCazicThule:
|
||||
return bit_DeityCazicThule;
|
||||
case DeityErollisiMarr:
|
||||
return bit_DeityErollisiMarr;
|
||||
case DeityBristlebane:
|
||||
return bit_DeityBristlebane;
|
||||
case DeityInnoruuk:
|
||||
return bit_DeityInnoruuk;
|
||||
case DeityKarana:
|
||||
return bit_DeityKarana;
|
||||
case DeityMithanielMarr:
|
||||
return bit_DeityMithanielMarr;
|
||||
case DeityPrexus:
|
||||
return bit_DeityPrexus;
|
||||
case DeityQuellious:
|
||||
return bit_DeityQuellious;
|
||||
case DeityRallosZek:
|
||||
return bit_DeityRallosZek;
|
||||
case DeityRodcetNife:
|
||||
return bit_DeityRodcetNife;
|
||||
case DeitySolusekRo:
|
||||
return bit_DeitySolusekRo;
|
||||
case DeityTheTribunal:
|
||||
return bit_DeityTheTribunal;
|
||||
case DeityTunare:
|
||||
return bit_DeityTunare;
|
||||
case DeityVeeshan:
|
||||
return bit_DeityVeeshan;
|
||||
case DeityAgnostic_LB:
|
||||
case DeityAgnostic:
|
||||
return bit_DeityAgnostic;
|
||||
default:
|
||||
return bit_DeityAll;
|
||||
};
|
||||
|
||||
return deity_map;
|
||||
}
|
||||
|
||||
std::string EQ::deity::GetDeityName(DeityType deity_type)
|
||||
EQ::deity::DeityType EQ::deity::ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit)
|
||||
{
|
||||
|
||||
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) {
|
||||
return EQ::deity::GetDeityMap().find(deity_type)->second;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
switch (deity_type_bit) {
|
||||
case bit_DeityAgnostic:
|
||||
return DeityAgnostic;
|
||||
case bit_DeityBertoxxulous:
|
||||
return DeityBertoxxulous;
|
||||
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
-24
@@ -21,8 +21,6 @@
|
||||
#define COMMON_DEITY_H
|
||||
|
||||
#include "types.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace EQ
|
||||
@@ -51,31 +49,30 @@ namespace EQ
|
||||
};
|
||||
|
||||
enum DeityTypeBit : uint32 {
|
||||
bit_DeityAgnostic = 0x00000001,
|
||||
bit_DeityBertoxxulous = 0x00000002,
|
||||
bit_DeityBrellSirilis = 0x00000004,
|
||||
bit_DeityCazicThule = 0x00000008,
|
||||
bit_DeityErollisiMarr = 0x00000010,
|
||||
bit_DeityBristlebane = 0x00000020,
|
||||
bit_DeityInnoruuk = 0x00000040,
|
||||
bit_DeityKarana = 0x00000080,
|
||||
bit_DeityNone = 0x00000000,
|
||||
bit_DeityAgnostic = 0x00000001,
|
||||
bit_DeityBertoxxulous = 0x00000002,
|
||||
bit_DeityBrellSirilis = 0x00000004,
|
||||
bit_DeityCazicThule = 0x00000008,
|
||||
bit_DeityErollisiMarr = 0x00000010,
|
||||
bit_DeityBristlebane = 0x00000020,
|
||||
bit_DeityInnoruuk = 0x00000040,
|
||||
bit_DeityKarana = 0x00000080,
|
||||
bit_DeityMithanielMarr = 0x00000100,
|
||||
bit_DeityPrexus = 0x00000200,
|
||||
bit_DeityQuellious = 0x00000400,
|
||||
bit_DeityRallosZek = 0x00000800,
|
||||
bit_DeityRodcetNife = 0x00001000,
|
||||
bit_DeitySolusekRo = 0x00002000,
|
||||
bit_DeityTheTribunal = 0x00004000,
|
||||
bit_DeityTunare = 0x00008000,
|
||||
bit_DeityVeeshan = 0x00010000,
|
||||
bit_DeityAll = UINT32_MAX
|
||||
bit_DeityPrexus = 0x00000200,
|
||||
bit_DeityQuellious = 0x00000400,
|
||||
bit_DeityRallosZek = 0x00000800,
|
||||
bit_DeityRodcetNife = 0x00001000,
|
||||
bit_DeitySolusekRo = 0x00002000,
|
||||
bit_DeityTheTribunal = 0x00004000,
|
||||
bit_DeityTunare = 0x00008000,
|
||||
bit_DeityVeeshan = 0x00010000,
|
||||
bit_DeityAll = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
constexpr int format_as(DeityType type) { return static_cast<int>(type); }
|
||||
|
||||
extern DeityTypeBit GetDeityBitmask(DeityType deity_type);
|
||||
extern std::string GetDeityName(DeityType deity_type);
|
||||
extern const std::map<DeityType, std::string>& GetDeityMap();
|
||||
extern DeityTypeBit ConvertDeityTypeToDeityTypeBit(DeityType deity_type);
|
||||
extern DeityType ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit);
|
||||
extern const char* DeityName(DeityType deity_type);
|
||||
|
||||
} /*deity*/
|
||||
|
||||
|
||||
+15
-89
@@ -1,17 +1,22 @@
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <cereal/archives/binary.hpp>
|
||||
#include "discord.h"
|
||||
#include "../http/httplib.h"
|
||||
#include "../json/json.h"
|
||||
#include "../strings.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include "../events/player_event_logs.h"
|
||||
|
||||
constexpr int MAX_RETRIES = 10;
|
||||
|
||||
void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url)
|
||||
{
|
||||
if (!ValidateWebhookUrl(webhook_url)) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -23,10 +28,13 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
|
||||
std::string endpoint = Strings::Replace(webhook_url, base_url, "");
|
||||
|
||||
// client
|
||||
httplib::Client cli(base_url);
|
||||
httplib::Client cli(base_url.c_str());
|
||||
cli.set_connection_timeout(0, 15000000); // 15 sec
|
||||
cli.set_read_timeout(15, 0); // 15 seconds
|
||||
cli.set_write_timeout(15, 0); // 15 seconds
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"}
|
||||
};
|
||||
|
||||
// payload
|
||||
Json::Value p;
|
||||
@@ -38,7 +46,7 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
|
||||
int retries = 0;
|
||||
int retry_timer = 1000;
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -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)
|
||||
{
|
||||
if (category_id == Logs::LogCategory::MySQLQuery) {
|
||||
@@ -146,20 +89,3 @@ std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string
|
||||
|
||||
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 "../types.h"
|
||||
#include "../http/httplib.h"
|
||||
#include "../repositories/player_event_logs_repository.h"
|
||||
#include "../events/player_events.h"
|
||||
|
||||
class Discord {
|
||||
public:
|
||||
static void SendWebhookMessage(const std::string& message, const std::string& webhook_url);
|
||||
static std::string FormatDiscordMessage(uint16 category_id, const std::string& message);
|
||||
static void SendPlayerEventMessage(const PlayerEvent::PlayerEventContainer& e, const std::string &webhook_url);
|
||||
static bool ValidateWebhookUrl(const std::string &webhook_url);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "discord_manager.h"
|
||||
#include "../../common/discord/discord.h"
|
||||
#include "../events/player_event_logs.h"
|
||||
#include "../common/discord/discord.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/strings.h"
|
||||
|
||||
void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message)
|
||||
{
|
||||
@@ -37,7 +38,7 @@ void DiscordManager::ProcessMessageQueue()
|
||||
message,
|
||||
webhook.webhook_url
|
||||
);
|
||||
message.clear();
|
||||
message = "";
|
||||
}
|
||||
|
||||
message += m;
|
||||
@@ -51,9 +52,10 @@ void DiscordManager::ProcessMessageQueue()
|
||||
webhook.webhook_url
|
||||
);
|
||||
}
|
||||
message.clear();
|
||||
message = "";
|
||||
}
|
||||
}
|
||||
|
||||
// final flush
|
||||
if (!message.empty()) {
|
||||
Discord::SendWebhookMessage(
|
||||
@@ -65,11 +67,3 @@ void DiscordManager::ProcessMessageQueue()
|
||||
webhook_message_queue.clear();
|
||||
webhook_queue_lock.unlock();
|
||||
}
|
||||
|
||||
void DiscordManager::QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e)
|
||||
{
|
||||
auto w = player_event_logs.GetDiscordWebhookUrlFromEventType(e.player_event_log.event_type_id);
|
||||
if (!w.empty()) {
|
||||
Discord::SendPlayerEventMessage(e, w);
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,12 @@
|
||||
#include <mutex>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "../../common/types.h"
|
||||
#include "../repositories/player_event_logs_repository.h"
|
||||
#include "../events/player_events.h"
|
||||
#include "../common/types.h"
|
||||
|
||||
class DiscordManager {
|
||||
public:
|
||||
void QueueWebhookMessage(uint32 webhook_id, const std::string& message);
|
||||
void ProcessMessageQueue();
|
||||
void QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e);
|
||||
private:
|
||||
std::mutex webhook_queue_lock{};
|
||||
std::map<uint32, std::vector<std::string>> webhook_message_queue{};
|
||||
+64
-197
@@ -22,6 +22,7 @@
|
||||
#include "data_verification.h"
|
||||
#include "eqemu_logsys.h"
|
||||
#include "eqemu_logsys_log_aliases.h"
|
||||
#include "languages.h"
|
||||
#include "rulesys.h"
|
||||
|
||||
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
|
||||
@@ -158,49 +159,49 @@ int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetLanguageMap()
|
||||
const std::map<int, std::string>& EQ::constants::GetLanguageMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> language_map = {
|
||||
{ Language::CommonTongue, "Common Tongue" },
|
||||
{ Language::Barbarian, "Barbarian" },
|
||||
{ Language::Erudian, "Erudian" },
|
||||
{ Language::Elvish, "Elvish" },
|
||||
{ Language::DarkElvish, "Dark Elvish" },
|
||||
{ Language::Dwarvish, "Dwarvish" },
|
||||
{ Language::Troll, "Troll" },
|
||||
{ Language::Ogre, "Ogre" },
|
||||
{ Language::Gnomish, "Gnomish" },
|
||||
{ Language::Halfling, "Halfling" },
|
||||
{ Language::ThievesCant, "Thieves Cant" },
|
||||
{ Language::OldErudian, "Old Erudian" },
|
||||
{ Language::ElderElvish, "Elder Elvish" },
|
||||
{ Language::Froglok, "Froglok" },
|
||||
{ Language::Goblin, "Goblin" },
|
||||
{ Language::Gnoll, "Gnoll" },
|
||||
{ Language::CombineTongue, "Combine Tongue" },
|
||||
{ Language::ElderTeirDal, "Elder Teir'Dal" },
|
||||
{ Language::Lizardman, "Lizardman" },
|
||||
{ Language::Orcish, "Orcish" },
|
||||
{ Language::Faerie, "Faerie" },
|
||||
{ Language::Dragon, "Dragon" },
|
||||
{ Language::ElderDragon, "Elder Dragon" },
|
||||
{ Language::DarkSpeech, "Dark Speech" },
|
||||
{ Language::VahShir, "Vah Shir" },
|
||||
{ Language::Alaran, "Alaran" },
|
||||
{ Language::Hadal, "Hadal" },
|
||||
{ Language::Unknown27, "Unknown" }
|
||||
static const std::map<int, std::string> language_map = {
|
||||
{ LANG_COMMON_TONGUE, "Common Tongue" },
|
||||
{ LANG_BARBARIAN, "Barbarian" },
|
||||
{ LANG_ERUDIAN, "Erudian" },
|
||||
{ LANG_ELVISH, "Elvish" },
|
||||
{ LANG_DARK_ELVISH, "Dark Elvish" },
|
||||
{ LANG_DWARVISH, "Dwarvish" },
|
||||
{ LANG_TROLL, "Troll" },
|
||||
{ LANG_OGRE, "Ogre" },
|
||||
{ LANG_GNOMISH, "Gnomish" },
|
||||
{ LANG_HALFLING, "Halfling" },
|
||||
{ LANG_THIEVES_CANT, "Thieves Cant" },
|
||||
{ LANG_OLD_ERUDIAN, "Old Erudian" },
|
||||
{ LANG_ELDER_ELVISH, "Elder Elvish" },
|
||||
{ LANG_FROGLOK, "Froglok" },
|
||||
{ LANG_GOBLIN, "Goblin" },
|
||||
{ LANG_GNOLL, "Gnoll" },
|
||||
{ LANG_COMBINE_TONGUE, "Combine Tongue" },
|
||||
{ LANG_ELDER_TEIRDAL, "Elder Teirdal" },
|
||||
{ LANG_LIZARDMAN, "Lizardman" },
|
||||
{ LANG_ORCISH, "Orcish" },
|
||||
{ LANG_FAERIE, "Faerie" },
|
||||
{ LANG_DRAGON, "Dragon" },
|
||||
{ LANG_ELDER_DRAGON, "Elder Dragon" },
|
||||
{ LANG_DARK_SPEECH, "Dark Speech" },
|
||||
{ LANG_VAH_SHIR, "Vah Shir" },
|
||||
{ LANG_ALARAN, "Alaran" },
|
||||
{ LANG_HADAL, "Hadal" },
|
||||
{ LANG_UNKNOWN, "Unknown" }
|
||||
};
|
||||
|
||||
return language_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetLanguageName(uint8 language_id)
|
||||
std::string EQ::constants::GetLanguageName(int language_id)
|
||||
{
|
||||
if (!EQ::ValueWithin(language_id, Language::CommonTongue, Language::Unknown27)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
||||
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()
|
||||
@@ -219,11 +220,11 @@ const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
||||
|
||||
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
|
||||
{
|
||||
if (!EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
||||
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()
|
||||
@@ -242,11 +243,11 @@ const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
|
||||
|
||||
std::string EQ::constants::GetFlyModeName(int8 flymode_id)
|
||||
{
|
||||
if (!EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
||||
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()
|
||||
@@ -364,11 +365,11 @@ const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
|
||||
|
||||
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
|
||||
{
|
||||
if (!EQ::ValueWithin(faction_consider_level, ConsiderLevel::Ally, ConsiderLevel::Scowls)) {
|
||||
return std::string();;
|
||||
if (EQ::constants::GetConsiderLevelMap().find(faction_consider_level) != EQ::constants::GetConsiderLevelMap().end()) {
|
||||
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()
|
||||
@@ -385,11 +386,11 @@ const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
|
||||
|
||||
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
|
||||
{
|
||||
if (!EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
|
||||
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()
|
||||
@@ -406,11 +407,11 @@ const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
|
||||
|
||||
std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id)
|
||||
{
|
||||
if (!EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
|
||||
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()
|
||||
@@ -428,11 +429,11 @@ const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
|
||||
|
||||
std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
|
||||
{
|
||||
if (!EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
|
||||
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()
|
||||
@@ -506,11 +507,11 @@ const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
|
||||
|
||||
std::string EQ::constants::GetObjectTypeName(int object_type)
|
||||
{
|
||||
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
||||
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
||||
}
|
||||
|
||||
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
|
||||
@@ -526,11 +527,11 @@ const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
|
||||
|
||||
std::string EQ::constants::GetWeatherTypeName(uint8 weather_type)
|
||||
{
|
||||
if (!EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
|
||||
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
|
||||
}
|
||||
|
||||
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
|
||||
@@ -552,17 +553,16 @@ const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
|
||||
|
||||
std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type)
|
||||
{
|
||||
if (!EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
|
||||
return std::string();
|
||||
if (EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
|
||||
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
|
||||
}
|
||||
|
||||
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> emote_type_map = {
|
||||
{ EmoteTypes::Say, "Say" },
|
||||
{ EmoteTypes::Emote, "Emote" },
|
||||
{ EmoteTypes::Shout, "Shout" },
|
||||
{ EmoteTypes::Proximity, "Proximity" }
|
||||
@@ -573,141 +573,8 @@ const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
|
||||
|
||||
std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
|
||||
{
|
||||
if (!EQ::ValueWithin(emote_type, EmoteTypes::Say, EmoteTypes::Proximity)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
|
||||
}
|
||||
|
||||
const std::map<uint32, std::string>& EQ::constants::GetAppearanceTypeMap()
|
||||
{
|
||||
static const std::map<uint32, std::string> appearance_type_map = {
|
||||
{ AppearanceType::Die, "Die" },
|
||||
{ AppearanceType::WhoLevel, "Who Level" },
|
||||
{ AppearanceType::MaxHealth, "Max Health" },
|
||||
{ AppearanceType::Invisibility, "Invisibility" },
|
||||
{ AppearanceType::PVP, "PVP" },
|
||||
{ AppearanceType::Light, "Light" },
|
||||
{ AppearanceType::Animation, "Animation" },
|
||||
{ AppearanceType::Sneak, "Sneak" },
|
||||
{ AppearanceType::SpawnID, "Spawn ID" },
|
||||
{ AppearanceType::Health, "Health" },
|
||||
{ AppearanceType::Linkdead, "Linkdead" },
|
||||
{ AppearanceType::FlyMode, "Fly Mode" },
|
||||
{ AppearanceType::GM, "GM" },
|
||||
{ AppearanceType::Anonymous, "Anonymous" },
|
||||
{ AppearanceType::GuildID, "Guild ID" },
|
||||
{ AppearanceType::GuildRank, "Guild Rank" },
|
||||
{ AppearanceType::AFK, "AFK" },
|
||||
{ AppearanceType::Pet, "Pet" },
|
||||
{ AppearanceType::Summoned, "Summoned" },
|
||||
{ AppearanceType::Split, "Split" },
|
||||
{ AppearanceType::Size, "Size" },
|
||||
{ AppearanceType::SetType, "Set Type" },
|
||||
{ AppearanceType::NPCName, "NPCName" },
|
||||
{ AppearanceType::AARank, "AARank" },
|
||||
{ AppearanceType::CancelSneakHide, "Cancel Sneak Hide" },
|
||||
{ AppearanceType::AreaHealthRegen, "Area Health Regeneration" },
|
||||
{ AppearanceType::AreaManaRegen, "Area Mana Regeneration" },
|
||||
{ AppearanceType::AreaEnduranceRegen, "Area Endurance Regeneration" },
|
||||
{ AppearanceType::FreezeBeneficialBuffs, "Freeze Beneficial Buffs" },
|
||||
{ AppearanceType::NPCTintIndex, "NPC Tint Index" },
|
||||
{ AppearanceType::GroupAutoConsent, "Group Auto Consent" },
|
||||
{ AppearanceType::RaidAutoConsent, "Raid Auto Consent" },
|
||||
{ AppearanceType::GuildAutoConsent, "Guild Auto Consent" },
|
||||
{ AppearanceType::ShowHelm, "Show Helm" },
|
||||
{ AppearanceType::DamageState, "Damage State" },
|
||||
{ AppearanceType::EQPlayers, "EQ Players" },
|
||||
{ AppearanceType::FindBits, "Find Bits" },
|
||||
{ AppearanceType::TextureType, "Texture Type" },
|
||||
{ AppearanceType::FacePick, "Face Pick" },
|
||||
{ AppearanceType::AntiCheat, "Anti Cheat" },
|
||||
{ AppearanceType::GuildShow, "Guild Show" },
|
||||
{ AppearanceType::OfflineMode, "Offline Mode" }
|
||||
};
|
||||
|
||||
return appearance_type_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetAppearanceTypeName(uint32 appearance_type)
|
||||
{
|
||||
const auto& a = EQ::constants::GetAppearanceTypeMap().find(appearance_type);
|
||||
if (a != EQ::constants::GetAppearanceTypeMap().end()) {
|
||||
return a->second;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint32, std::string>& EQ::constants::GetSpecialAbilityMap()
|
||||
{
|
||||
static const std::map<uint32, std::string> special_ability_map = {
|
||||
{ SPECATK_SUMMON, "Summon" },
|
||||
{ SPECATK_ENRAGE, "Enrage" },
|
||||
{ SPECATK_RAMPAGE, "Rampage" },
|
||||
{ SPECATK_AREA_RAMPAGE, "Area Rampage" },
|
||||
{ SPECATK_FLURRY, "Flurry" },
|
||||
{ SPECATK_TRIPLE, "Triple Attack" },
|
||||
{ SPECATK_QUAD, "Quadruple Attack" },
|
||||
{ SPECATK_INNATE_DW, "Dual Wield" },
|
||||
{ SPECATK_BANE, "Bane Attack" },
|
||||
{ SPECATK_MAGICAL, "Magical Attack" },
|
||||
{ SPECATK_RANGED_ATK, "Ranged Attack" },
|
||||
{ UNSLOWABLE, "Immune to Slow" },
|
||||
{ UNMEZABLE, "Immune to Mesmerize" },
|
||||
{ UNCHARMABLE, "Immune to Charm" },
|
||||
{ UNSTUNABLE, "Immune to Stun" },
|
||||
{ UNSNAREABLE, "Immune to Snare" },
|
||||
{ UNFEARABLE, "Immune to Fear" },
|
||||
{ UNDISPELLABLE, "Immune to Dispell" },
|
||||
{ IMMUNE_MELEE, "Immune to Melee" },
|
||||
{ IMMUNE_MAGIC, "Immune to Magic" },
|
||||
{ IMMUNE_FLEEING, "Immune to Fleeing" },
|
||||
{ IMMUNE_MELEE_EXCEPT_BANE, "Immune to Melee except Bane" },
|
||||
{ IMMUNE_MELEE_NONMAGICAL, "Immune to Non-Magical Melee" },
|
||||
{ IMMUNE_AGGRO, "Immune to Aggro" },
|
||||
{ IMMUNE_AGGRO_ON, "Immune to Being Aggro" },
|
||||
{ IMMUNE_CASTING_FROM_RANGE, "Immune to Ranged Spells" },
|
||||
{ IMMUNE_FEIGN_DEATH, "Immune to Feign Death" },
|
||||
{ IMMUNE_TAUNT, "Immune to Taunt" },
|
||||
{ NPC_TUNNELVISION, "Tunnel Vision" },
|
||||
{ NPC_NO_BUFFHEAL_FRIENDS, "Does Not Heal of Buff Allies" },
|
||||
{ IMMUNE_PACIFY, "Immune to Pacify" },
|
||||
{ LEASH, "Leashed" },
|
||||
{ TETHER, "Tethered" },
|
||||
{ DESTRUCTIBLE_OBJECT, "Destructible Object" },
|
||||
{ NO_HARM_FROM_CLIENT, "Immune to Harm from Client" },
|
||||
{ ALWAYS_FLEE, "Always Flees" },
|
||||
{ FLEE_PERCENT, "Flee Percentage" },
|
||||
{ ALLOW_BENEFICIAL, "Allows Beneficial Spells" },
|
||||
{ DISABLE_MELEE, "Melee is Disabled" },
|
||||
{ NPC_CHASE_DISTANCE, "Chase Distance" },
|
||||
{ ALLOW_TO_TANK, "Allowed to Tank" },
|
||||
{ IGNORE_ROOT_AGGRO_RULES, "Ignores Root Aggro" },
|
||||
{ CASTING_RESIST_DIFF, "Casting Resist Difficulty" },
|
||||
{ COUNTER_AVOID_DAMAGE, "Counter Damage Avoidance" },
|
||||
{ PROX_AGGRO, "Proximity Aggro" },
|
||||
{ IMMUNE_RANGED_ATTACKS, "Immune to Ranged Attacks" },
|
||||
{ IMMUNE_DAMAGE_CLIENT, "Immune to Client Damage" },
|
||||
{ IMMUNE_DAMAGE_NPC, "Immune to NPC Damage" },
|
||||
{ IMMUNE_AGGRO_CLIENT, "Immune to Client Aggro" },
|
||||
{ IMMUNE_AGGRO_NPC, "Immune to NPC Aggro" },
|
||||
{ MODIFY_AVOID_DAMAGE, "Modify Damage Avoidance" },
|
||||
{ IMMUNE_FADING_MEMORIES, "Immune to Memory Fades" },
|
||||
{ IMMUNE_OPEN, "Immune to Open" },
|
||||
{ IMMUNE_ASSASSINATE, "Immune to Assassinate" },
|
||||
{ IMMUNE_HEADSHOT, "Immune to Headshot" },
|
||||
};
|
||||
|
||||
return special_ability_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetSpecialAbilityName(uint32 ability_id)
|
||||
{
|
||||
const auto& a = EQ::constants::GetSpecialAbilityMap().find(ability_id);
|
||||
if (a != EQ::constants::GetSpecialAbilityMap().end()) {
|
||||
return a->second;
|
||||
if (EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
|
||||
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
|
||||
+4
-108
@@ -334,7 +334,7 @@ namespace EQ
|
||||
enum WeatherTypes : uint8 {
|
||||
None,
|
||||
Raining,
|
||||
Snowing
|
||||
Snowing
|
||||
};
|
||||
|
||||
enum EmoteEventTypes : uint8 {
|
||||
@@ -350,7 +350,6 @@ namespace EQ
|
||||
};
|
||||
|
||||
enum EmoteTypes : uint8 {
|
||||
Say,
|
||||
Emote,
|
||||
Shout,
|
||||
Proximity
|
||||
@@ -359,8 +358,8 @@ namespace EQ
|
||||
const char *GetStanceName(StanceType stance_type);
|
||||
int ConvertStanceTypeToIndex(StanceType stance_type);
|
||||
|
||||
extern const std::map<uint8, std::string>& GetLanguageMap();
|
||||
std::string GetLanguageName(uint8 language_id);
|
||||
extern const std::map<int, std::string>& GetLanguageMap();
|
||||
std::string GetLanguageName(int language_id);
|
||||
|
||||
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
|
||||
std::string GetLDoNThemeName(uint32 theme_id);
|
||||
@@ -398,12 +397,6 @@ namespace EQ
|
||||
extern const std::map<uint8, std::string>& GetEmoteTypeMap();
|
||||
std::string GetEmoteTypeName(uint8 emote_type);
|
||||
|
||||
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
|
||||
std::string GetAppearanceTypeName(uint32 animation_type);
|
||||
|
||||
extern const std::map<uint32, std::string>& GetSpecialAbilityMap();
|
||||
std::string GetSpecialAbilityName(uint32 ability_id);
|
||||
|
||||
const int STANCE_TYPE_FIRST = stancePassive;
|
||||
const int STANCE_TYPE_LAST = stanceBurnAE;
|
||||
const int STANCE_TYPE_COUNT = stanceBurnAE;
|
||||
@@ -574,7 +567,7 @@ enum ReloadWorld : uint8 {
|
||||
ForceRepop
|
||||
};
|
||||
|
||||
enum BucketComparison : uint8 {
|
||||
enum MerchantBucketComparison : uint8 {
|
||||
BucketEqualTo = 0,
|
||||
BucketNotEqualTo,
|
||||
BucketGreaterThanOrEqualTo,
|
||||
@@ -587,101 +580,4 @@ enum BucketComparison : uint8 {
|
||||
BucketIsNotBetween
|
||||
};
|
||||
|
||||
enum class EntityFilterType {
|
||||
All,
|
||||
Bots,
|
||||
Clients,
|
||||
NPCs
|
||||
};
|
||||
|
||||
enum class ApplySpellType {
|
||||
Solo,
|
||||
Group,
|
||||
Raid
|
||||
};
|
||||
|
||||
enum {
|
||||
SPECATK_SUMMON = 1,
|
||||
SPECATK_ENRAGE = 2,
|
||||
SPECATK_RAMPAGE = 3,
|
||||
SPECATK_AREA_RAMPAGE = 4,
|
||||
SPECATK_FLURRY = 5,
|
||||
SPECATK_TRIPLE = 6,
|
||||
SPECATK_QUAD = 7,
|
||||
SPECATK_INNATE_DW = 8,
|
||||
SPECATK_BANE = 9,
|
||||
SPECATK_MAGICAL = 10,
|
||||
SPECATK_RANGED_ATK = 11,
|
||||
UNSLOWABLE = 12,
|
||||
UNMEZABLE = 13,
|
||||
UNCHARMABLE = 14,
|
||||
UNSTUNABLE = 15,
|
||||
UNSNAREABLE = 16,
|
||||
UNFEARABLE = 17,
|
||||
UNDISPELLABLE = 18,
|
||||
IMMUNE_MELEE = 19,
|
||||
IMMUNE_MAGIC = 20,
|
||||
IMMUNE_FLEEING = 21,
|
||||
IMMUNE_MELEE_EXCEPT_BANE = 22,
|
||||
IMMUNE_MELEE_NONMAGICAL = 23,
|
||||
IMMUNE_AGGRO = 24,
|
||||
IMMUNE_AGGRO_ON = 25,
|
||||
IMMUNE_CASTING_FROM_RANGE = 26,
|
||||
IMMUNE_FEIGN_DEATH = 27,
|
||||
IMMUNE_TAUNT = 28,
|
||||
NPC_TUNNELVISION = 29,
|
||||
NPC_NO_BUFFHEAL_FRIENDS = 30,
|
||||
IMMUNE_PACIFY = 31,
|
||||
LEASH = 32,
|
||||
TETHER = 33,
|
||||
DESTRUCTIBLE_OBJECT = 34,
|
||||
NO_HARM_FROM_CLIENT = 35,
|
||||
ALWAYS_FLEE = 36,
|
||||
FLEE_PERCENT = 37,
|
||||
ALLOW_BENEFICIAL = 38,
|
||||
DISABLE_MELEE = 39,
|
||||
NPC_CHASE_DISTANCE = 40,
|
||||
ALLOW_TO_TANK = 41,
|
||||
IGNORE_ROOT_AGGRO_RULES = 42,
|
||||
CASTING_RESIST_DIFF = 43,
|
||||
COUNTER_AVOID_DAMAGE = 44, // Modify by percent NPC's opponents chance to riposte, block, parry or dodge individually, or for all skills
|
||||
PROX_AGGRO = 45,
|
||||
IMMUNE_RANGED_ATTACKS = 46,
|
||||
IMMUNE_DAMAGE_CLIENT = 47,
|
||||
IMMUNE_DAMAGE_NPC = 48,
|
||||
IMMUNE_AGGRO_CLIENT = 49,
|
||||
IMMUNE_AGGRO_NPC = 50,
|
||||
MODIFY_AVOID_DAMAGE = 51, // Modify by percent the NPCs chance to riposte, block, parry or dodge individually, or for all skills
|
||||
IMMUNE_FADING_MEMORIES = 52,
|
||||
IMMUNE_OPEN = 53,
|
||||
IMMUNE_ASSASSINATE = 54,
|
||||
IMMUNE_HEADSHOT = 55,
|
||||
MAX_SPECIAL_ATTACK = 56
|
||||
};
|
||||
|
||||
|
||||
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*/
|
||||
|
||||
@@ -45,7 +45,6 @@ typedef enum { //EQEmu internal opcodes list
|
||||
_maxEmuOpcode
|
||||
} EmuOpcode;
|
||||
|
||||
constexpr int format_as(EmuOpcode opcode) { return static_cast<int>(opcode); }
|
||||
extern const char *OpcodeNames[_maxEmuOpcode+1];
|
||||
|
||||
#endif
|
||||
|
||||
+2
-26
@@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest),
|
||||
N(OP_AltCurrencyPurchase),
|
||||
N(OP_AltCurrencyReclaim),
|
||||
N(OP_AltCurrencySell),
|
||||
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069
|
||||
N(OP_AltCurrencySellSelection),
|
||||
N(OP_Animation),
|
||||
N(OP_AnnoyingZoneUnknown),
|
||||
N(OP_ApplyPoison),
|
||||
@@ -62,7 +62,6 @@ N(OP_BeginCast),
|
||||
N(OP_Bind_Wound),
|
||||
N(OP_BlockedBuffs),
|
||||
N(OP_BoardBoat),
|
||||
N(OP_BookButton),
|
||||
N(OP_Buff),
|
||||
N(OP_BuffCreate),
|
||||
N(OP_BuffRemoveRequest),
|
||||
@@ -228,7 +227,6 @@ N(OP_GuildBank),
|
||||
N(OP_GuildBankItemList),
|
||||
N(OP_GuildCreate),
|
||||
N(OP_GuildDelete),
|
||||
N(OP_GuildDeleteGuild),
|
||||
N(OP_GuildDemote),
|
||||
N(OP_GuildInvite),
|
||||
N(OP_GuildInviteAccept),
|
||||
@@ -240,33 +238,15 @@ N(OP_GuildManageStatus),
|
||||
N(OP_GuildMemberLevelUpdate),
|
||||
N(OP_GuildMemberList),
|
||||
N(OP_GuildMemberUpdate),
|
||||
N(OP_GuildMemberLevel),
|
||||
N(OP_GuildMemberRankAltBanker),
|
||||
N(OP_GuildMemberPublicNote),
|
||||
N(OP_GuildMemberAdd),
|
||||
N(OP_GuildMemberRename),
|
||||
N(OP_GuildMemberDelete),
|
||||
N(OP_GuildMemberDetails),
|
||||
N(OP_GuildRenameGuild),
|
||||
N(OP_GuildMOTD),
|
||||
N(OP_GuildPeace),
|
||||
N(OP_GuildPromote),
|
||||
N(OP_GuildPublicNote),
|
||||
N(OP_GuildRemove),
|
||||
N(OP_GuildSelectTribute),
|
||||
N(OP_GuildModifyBenefits),
|
||||
N(OP_GuildTributeToggleReq),
|
||||
N(OP_GuildTributeToggleReply),
|
||||
N(OP_GuildOptInOut),
|
||||
N(OP_GuildSaveActiveTributes),
|
||||
N(OP_GuildSendActiveTributes),
|
||||
N(OP_GuildTributeFavorAndTimer),
|
||||
N(OP_GuildsList),
|
||||
N(OP_GuildStatus),
|
||||
N(OP_GuildTributeInfo),
|
||||
N(OP_GuildUpdate),
|
||||
N(OP_GuildTributeDonateItem),
|
||||
N(OP_GuildTributeDonatePlat),
|
||||
N(OP_GuildUpdateURLAndChannel),
|
||||
N(OP_GuildWar),
|
||||
N(OP_Heartbeat),
|
||||
N(OP_Hide),
|
||||
@@ -336,7 +316,6 @@ N(OP_LootRequest),
|
||||
N(OP_ManaChange),
|
||||
N(OP_ManaUpdate),
|
||||
N(OP_MarkNPC),
|
||||
N(OP_MarkRaidNPC),
|
||||
N(OP_Marquee),
|
||||
N(OP_MemorizeSpell),
|
||||
N(OP_Mend),
|
||||
@@ -419,8 +398,6 @@ N(OP_PVPLeaderBoardRequest),
|
||||
N(OP_PVPStats),
|
||||
N(OP_QueryResponseThing),
|
||||
N(OP_QueryUCSServerStatus),
|
||||
N(OP_RaidDelegateAbility),
|
||||
N(OP_RaidClearNPCMarks),
|
||||
N(OP_RaidInvite),
|
||||
N(OP_RaidJoin),
|
||||
N(OP_RaidUpdate),
|
||||
@@ -444,7 +421,6 @@ N(OP_ReqClientSpawn),
|
||||
N(OP_ReqNewZone),
|
||||
N(OP_RequestClientZoneChange),
|
||||
N(OP_RequestDuel),
|
||||
N(OP_RequestGuildTributes),
|
||||
N(OP_RequestKnowledgeBase),
|
||||
N(OP_RequestTitles),
|
||||
N(OP_RespawnWindow),
|
||||
|
||||
+60
-171
@@ -23,61 +23,61 @@
|
||||
#include "skills.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace AppearanceType {
|
||||
constexpr uint32 Die = 0; // Causes the client to keel over and zone to bind point (default action)
|
||||
constexpr uint32 WhoLevel = 1; // Level that shows up on /who
|
||||
constexpr uint32 MaxHealth = 2;
|
||||
constexpr uint32 Invisibility = 3; // 0 = Visible, 1 = Invisible
|
||||
constexpr uint32 PVP = 4; // 0 = Non-PVP, 1 = PVP
|
||||
constexpr uint32 Light = 5; // Light type emitted by player (lightstone, shiny shield)
|
||||
constexpr uint32 Animation = 14; // 100 = Standing, 102 = Freeze, 105 = Looting, 110 = Sitting, 111 = Crouching, 115 = Lying
|
||||
constexpr uint32 Sneak = 15; // 0 = Normal, 1 = Sneaking
|
||||
constexpr uint32 SpawnID = 16; // Server -> Client, sets player spawn ID
|
||||
constexpr uint32 Health = 17; // Client->Server, my HP has changed (like regen tic)
|
||||
constexpr uint32 Linkdead = 18; // 0 = Normal, 1 = Linkdead
|
||||
constexpr uint32 FlyMode = 19; // 0 = Off, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating while Running
|
||||
constexpr uint32 GM = 20; // 0 = Non-GM, 1 = GM
|
||||
constexpr uint32 Anonymous = 21; // 0 = Non-Anonymous, 1 = Anonymous, 2 = Roleplaying
|
||||
constexpr uint32 GuildID = 22;
|
||||
constexpr uint32 GuildRank = 23;
|
||||
constexpr uint32 AFK = 24; // 0 = Non-AFK, 1 = AFK
|
||||
constexpr uint32 Pet = 25; // Parameter is Entity ID of owner, or 0 for when charm breaks
|
||||
constexpr uint32 Summoned = 27;
|
||||
constexpr uint32 Split = 28; // 0 = No Split, 1 = Auto Split
|
||||
constexpr uint32 Size = 29; // Spawn's Size
|
||||
constexpr uint32 SetType = 30; // 0 = PC, 1 = NPC, 2 = Corpse
|
||||
constexpr uint32 NPCName = 31; // Change PC name color to NPC name color
|
||||
constexpr uint32 AARank = 32; // AA Rank Title ID, title in /who?
|
||||
constexpr uint32 CancelSneakHide = 33; // Turns off Hide and Sneak
|
||||
constexpr uint32 AreaHealthRegen = 35; // Guild Hall Regeneration Pool sets to value * 0.001
|
||||
constexpr uint32 AreaManaRegen = 36; // Guild Hall Regeneration Pool sets to value * 0.001
|
||||
constexpr uint32 AreaEnduranceRegen = 37; // Guild Hall Regeneration Pool sets to value * 0.001
|
||||
constexpr uint32 FreezeBeneficialBuffs = 38; // Freezes beneficial buff timers for PCs
|
||||
constexpr uint32 NPCTintIndex = 39;
|
||||
constexpr uint32 GroupAutoConsent = 40; // Auto Consent Group
|
||||
constexpr uint32 RaidAutoConsent = 41; // Auto Consent Raid
|
||||
constexpr uint32 GuildAutoConsent = 42; // Auto Consent Guild
|
||||
constexpr uint32 ShowHelm = 43; // 0 = Hide, 1 = Show
|
||||
constexpr uint32 DamageState = 44; // The damage state of a destructible object (0 through 10) plays sound IDs, most only have 2 or 4 states though
|
||||
constexpr uint32 EQPlayers = 45; // EQ Players Update
|
||||
constexpr uint32 FindBits = 46; // Set Find Bits?
|
||||
constexpr uint32 TextureType = 48; // Texture Type?
|
||||
constexpr uint32 FacePick = 49; // Turns off face pick window?
|
||||
constexpr uint32 AntiCheat = 51; // Sent by the client randomly telling the server how long since last action has occurred
|
||||
constexpr uint32 GuildShow = 52;
|
||||
constexpr uint32 OfflineMode = 53; // Offline Mode
|
||||
}
|
||||
|
||||
namespace Animation {
|
||||
constexpr uint32 Standing = 100;
|
||||
constexpr uint32 Freeze = 102;
|
||||
constexpr uint32 Looting = 105;
|
||||
constexpr uint32 Sitting = 110;
|
||||
constexpr uint32 Crouching = 111;
|
||||
constexpr uint32 Lying = 115;
|
||||
}
|
||||
//SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2)
|
||||
#define AT_Die 0 // this causes the client to keel over and zone to bind point (default action)
|
||||
#define AT_WhoLevel 1 // the level that shows up on /who
|
||||
#define AT_HPMax 2 // idk
|
||||
#define AT_Invis 3 // 0 = visible, 1 = invisible
|
||||
#define AT_PVP 4 // 0 = blue, 1 = pvp (red)
|
||||
#define AT_Light 5 // light type emitted by player (lightstone, shiny shield)
|
||||
#define AT_Anim 14 // 100=standing, 110=sitting, 111=ducking, 115=feigned, 105=looting
|
||||
#define AT_Sneak 15 // 0 = normal, 1 = sneaking
|
||||
#define AT_SpawnID 16 // server to client, sets player spawn id
|
||||
#define AT_HP 17 // Client->Server, my HP has changed (like regen tic)
|
||||
#define AT_Linkdead 18 // 0 = normal, 1 = linkdead
|
||||
#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate max 5, see GravityBehavior enum
|
||||
#define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM
|
||||
#define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay
|
||||
#define AT_GuildID 22
|
||||
#define AT_GuildRank 23 // 0=member, 1=officer, 2=leader
|
||||
#define AT_AFK 24 // 0 = normal, 1 = afk
|
||||
#define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks
|
||||
#define AT_Summoned 27 // Unsure
|
||||
#define AT_Split 28 // 0 = normal, 1 = autosplit on (not showing in SoF+) (client-to-server only)
|
||||
#define AT_Size 29 // spawn's size (present: SoF, absent: RoF2)
|
||||
#define AT_SetType 30 // 0 = PC, 1 = NPC, 2 <= = corpse
|
||||
#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name, Trader on RoF2?
|
||||
#define AT_AARank 32 // AA Rank Title ID thingy, does is this the title in /who?
|
||||
#define AT_CancelSneakHide 33 // Turns off Hide and Sneak
|
||||
//#define AT_34 34 // unknown (present: SoF, absent: RoF2)
|
||||
#define AT_AreaHPRegen 35 // guild hall regen pool sets to value * 0.001
|
||||
#define AT_AreaManaRegen 36 // guild hall regen pool sets to value * 0.001
|
||||
#define AT_AreaEndRegen 37 // guild hall regen pool sets to value * 0.001
|
||||
#define AT_FreezeBuffs 38 // Freezes beneficial buff timers
|
||||
#define AT_NpcTintIndex 39 // not 100% sure
|
||||
#define AT_GroupConsent 40 // auto consent group
|
||||
#define AT_RaidConsent 41 // auto consent raid
|
||||
#define AT_GuildConsent 42 // auto consent guild
|
||||
#define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic
|
||||
#define AT_DamageState 44 // The damage state of a destructible object (0 through 10) plays soundids most only have 2 or 4 states though
|
||||
#define AT_EQPlayers 45 // /eqplayersupdate
|
||||
#define AT_FindBits 46 // set FindBits, whatever those are!
|
||||
#define AT_TextureType 48 // TextureType
|
||||
#define AT_FacePick 49 // Turns off face pick window? maybe ...
|
||||
#define AT_AntiCheat 51 // sent by the client randomly telling the server how long since last action has occured
|
||||
#define AT_GuildShow 52 // this is what MQ2 call sit, not sure
|
||||
#define AT_Offline 53 // Offline mode
|
||||
|
||||
constexpr int16 RECAST_TYPE_UNLINKED_ITEM = -1;
|
||||
//#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2)
|
||||
|
||||
// animations for AT_Anim
|
||||
#define ANIM_FREEZE 102
|
||||
#define ANIM_STAND 0x64
|
||||
#define ANIM_SIT 0x6e
|
||||
#define ANIM_CROUCH 0x6f
|
||||
#define ANIM_DEATH 0x73
|
||||
#define ANIM_LOOT 0x69
|
||||
|
||||
typedef enum {
|
||||
eaStanding = 0,
|
||||
@@ -684,53 +684,14 @@ namespace Zones {
|
||||
constexpr uint16 APPRENTICE = 999; // Designer Apprentice
|
||||
}
|
||||
|
||||
namespace Language {
|
||||
constexpr uint8 CommonTongue = 0;
|
||||
constexpr uint8 Barbarian = 1;
|
||||
constexpr uint8 Erudian = 2;
|
||||
constexpr uint8 Elvish = 3;
|
||||
constexpr uint8 DarkElvish = 4;
|
||||
constexpr uint8 Dwarvish = 5;
|
||||
constexpr uint8 Troll = 6;
|
||||
constexpr uint8 Ogre = 7;
|
||||
constexpr uint8 Gnomish = 8;
|
||||
constexpr uint8 Halfling = 9;
|
||||
constexpr uint8 ThievesCant = 10;
|
||||
constexpr uint8 OldErudian = 11;
|
||||
constexpr uint8 ElderElvish = 12;
|
||||
constexpr uint8 Froglok = 13;
|
||||
constexpr uint8 Goblin = 14;
|
||||
constexpr uint8 Gnoll = 15;
|
||||
constexpr uint8 CombineTongue = 16;
|
||||
constexpr uint8 ElderTeirDal = 17;
|
||||
constexpr uint8 Lizardman = 18;
|
||||
constexpr uint8 Orcish = 19;
|
||||
constexpr uint8 Faerie = 20;
|
||||
constexpr uint8 Dragon = 21;
|
||||
constexpr uint8 ElderDragon = 22;
|
||||
constexpr uint8 DarkSpeech = 23;
|
||||
constexpr uint8 VahShir = 24;
|
||||
constexpr uint8 Alaran = 25;
|
||||
constexpr uint8 Hadal = 26;
|
||||
constexpr uint8 Unknown27 = 27;
|
||||
//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
|
||||
|
||||
constexpr uint8 MaxValue = 100;
|
||||
}
|
||||
namespace PetInfoType {
|
||||
constexpr int Current = 0;
|
||||
constexpr int Suspended = 1;
|
||||
}
|
||||
|
||||
namespace BuffEffectType {
|
||||
constexpr uint8 None = 0;
|
||||
constexpr uint8 Buff = 2;
|
||||
constexpr uint8 InverseBuff = 4;
|
||||
}
|
||||
|
||||
namespace AlternateCurrencyMode {
|
||||
constexpr uint32 Update = 7;
|
||||
constexpr uint32 Populate = 8;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
FilterNone = 0,
|
||||
@@ -1055,76 +1016,4 @@ enum FVNoDropFlagRule
|
||||
AdminOnly = 2
|
||||
};
|
||||
|
||||
enum Anonymity : uint8
|
||||
{
|
||||
NotAnonymous,
|
||||
Anonymous,
|
||||
Roleplaying
|
||||
};
|
||||
|
||||
enum ZoningMessage : int8 {
|
||||
ZoneNoMessage = 0,
|
||||
ZoneSuccess = 1,
|
||||
ZoneNotReady = -1,
|
||||
ZoneValidPC = -2,
|
||||
ZoneStoryZone = -3,
|
||||
ZoneNoExpansion = -6,
|
||||
ZoneNoExperience = -7
|
||||
};
|
||||
|
||||
enum class RecipeCountType : uint8
|
||||
{
|
||||
Component,
|
||||
Container,
|
||||
Fail,
|
||||
Salvage,
|
||||
Success
|
||||
};
|
||||
|
||||
#define ALT_CURRENCY_ID_RADIANT 4
|
||||
#define ALT_CURRENCY_ID_EBON 5
|
||||
|
||||
enum ResurrectionActions
|
||||
{
|
||||
Decline,
|
||||
Accept
|
||||
};
|
||||
|
||||
enum ScribeSpellActions
|
||||
{
|
||||
Scribe,
|
||||
Memorize,
|
||||
Unmemorize
|
||||
};
|
||||
|
||||
enum SpellTimeRestrictions
|
||||
{
|
||||
NoRestriction,
|
||||
Day,
|
||||
Night
|
||||
};
|
||||
|
||||
enum MoneyTypes
|
||||
{
|
||||
Copper,
|
||||
Silver,
|
||||
Gold,
|
||||
Platinum
|
||||
};
|
||||
|
||||
enum MoneySubtypes
|
||||
{
|
||||
Personal,
|
||||
Bank,
|
||||
Cursor,
|
||||
SharedBank // Platinum Only
|
||||
};
|
||||
|
||||
namespace RaidLootType {
|
||||
constexpr uint32 LeaderOnly = 1;
|
||||
constexpr uint32 LeaderAndGroupLeadersOnly = 2;
|
||||
constexpr uint32 LeaderSelected = 3;
|
||||
constexpr uint32 EntireRaid = 4;
|
||||
}
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ namespace EQ
|
||||
|
||||
LookupEntry(const LookupEntry *lookup_entry) { }
|
||||
LookupEntry(
|
||||
const InventoryTypeSize_Struct& InventoryTypeSize,
|
||||
InventoryTypeSize_Struct InventoryTypeSize,
|
||||
uint64 EquipmentBitmask,
|
||||
uint64 GeneralBitmask,
|
||||
uint64 CursorBitmask,
|
||||
|
||||
+138
-1
@@ -236,6 +236,26 @@ uint32 EQApplicationPacket::serialize(uint16 opcode, unsigned char *dest) const
|
||||
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 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 newlen=0;
|
||||
@@ -315,6 +403,55 @@ uint32 flag_offset=1,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 {
|
||||
return(new EQApplicationPacket(*this));
|
||||
}
|
||||
@@ -378,4 +515,4 @@ std::string DumpPacketToString(const EQApplicationPacket* app){
|
||||
std::ostringstream out;
|
||||
out << DumpPacketHexToString(app->pBuffer, app->size);
|
||||
return out.str();
|
||||
}
|
||||
}
|
||||
@@ -80,8 +80,11 @@ public:
|
||||
|
||||
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 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); }
|
||||
|
||||
|
||||
+106
-364
@@ -29,7 +29,7 @@
|
||||
#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 MAX_MERC = 100;
|
||||
static const uint32 MAX_MERC_GRADES = 10;
|
||||
@@ -124,12 +124,6 @@ struct LDoNTrapTemplate
|
||||
uint8 locked;
|
||||
};
|
||||
|
||||
enum CrystalReclaimTypes
|
||||
{
|
||||
Ebon = 5,
|
||||
Radiant = 4,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -314,7 +308,6 @@ union
|
||||
uint32 DestructibleUnk9;
|
||||
bool targetable_with_hotkey;
|
||||
bool show_name;
|
||||
bool guild_show;
|
||||
};
|
||||
|
||||
struct PlayerState_Struct {
|
||||
@@ -393,7 +386,7 @@ struct NewZone_Struct {
|
||||
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
|
||||
/*0728*/ uint32 lava_damage; // Seen 50
|
||||
/*0732*/ uint32 min_lava_damage; // Seen 10
|
||||
/*0736*/ float safe_heading;
|
||||
/*0736*/
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -632,12 +625,6 @@ struct ConsentResponse_Struct {
|
||||
char zonename[32];
|
||||
};
|
||||
|
||||
struct NameApproval_Struct {
|
||||
char name[64];
|
||||
uint32 race_id;
|
||||
uint32 class_id;
|
||||
};
|
||||
|
||||
/*
|
||||
** Name Generator Struct
|
||||
** Length: 72 bytes
|
||||
@@ -1678,68 +1665,6 @@ struct GuildUpdate_Struct {
|
||||
GuildsListEntry_Struct entry;
|
||||
};
|
||||
|
||||
struct GuildMemberAdd_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ uint32 unknown04;
|
||||
/*008*/ uint32 unknown08;
|
||||
/*012*/ uint32 unknown12;
|
||||
/*016*/ uint32 level;
|
||||
/*020*/ uint32 class_;
|
||||
/*024*/ uint32 rank_;
|
||||
/*028*/ uint32 guild_show;
|
||||
/*032*/ uint32 zone_id;
|
||||
/*036*/ uint32 last_on;
|
||||
/*040*/ char player_name[64];
|
||||
};
|
||||
|
||||
struct GuildMemberLevel_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ char player_name[64];
|
||||
/*068*/ uint32 level;
|
||||
};
|
||||
|
||||
struct GuildMemberRank_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ uint32 rank_;
|
||||
/*008*/ char player_name[64];
|
||||
/*072*/ uint32 alt_banker; //Banker/Alt bit 00 - none 10 - Alt 11 - Alt and Banker 01 - Banker. Banker not functional for RoF2+
|
||||
/*076*/ uint32 offline;
|
||||
};
|
||||
|
||||
struct GuildMemberPublicNote_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ char player_name[64];
|
||||
/*068*/ char public_note[256]; //RoF2 256
|
||||
};
|
||||
|
||||
struct GuildDelete_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
};
|
||||
|
||||
struct GuildRenameGuild_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ char new_guild_name[64];
|
||||
};
|
||||
|
||||
struct GuildRenameMember_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ char player_name[64];
|
||||
/*068*/ char new_player_name[64];
|
||||
};
|
||||
|
||||
struct GuildMemberDetails_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ char player_name[64];
|
||||
/*068*/ uint32 zone_id;
|
||||
/*072*/ uint32 last_on;
|
||||
/*076*/ uint32 offline_mode; //1 Offline
|
||||
};
|
||||
|
||||
struct GuildMemberDelete_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ char player_name[64];
|
||||
};
|
||||
|
||||
/*
|
||||
** Money Loot
|
||||
** Length: 22 Bytes
|
||||
@@ -1788,10 +1713,10 @@ struct GuildJoin_Struct{
|
||||
/*092*/
|
||||
};
|
||||
struct GuildInviteAccept_Struct {
|
||||
char inviter[64];
|
||||
char new_member[64];
|
||||
char inviter[64];
|
||||
char newmember[64];
|
||||
uint32 response;
|
||||
uint32 guild_id;
|
||||
uint32 guildeqid;
|
||||
};
|
||||
struct GuildManageRemove_Struct {
|
||||
uint32 guildeqid;
|
||||
@@ -1823,14 +1748,6 @@ struct PopupResponse_Struct {
|
||||
/*0004*/ uint32 popupid;
|
||||
};
|
||||
|
||||
enum GuildInformationActions
|
||||
{
|
||||
GuildUpdateURL = 0,
|
||||
GuildUpdateChannel = 1,
|
||||
GuildUpdateRanks = 4,
|
||||
GuildUpdatePermissions = 5
|
||||
};
|
||||
|
||||
struct GuildManageBanker_Struct {
|
||||
uint32 unknown0;
|
||||
char myname[64];
|
||||
@@ -1844,9 +1761,9 @@ struct GuildSetRank_Struct
|
||||
{
|
||||
/*00*/ uint32 Unknown00;
|
||||
/*04*/ uint32 Unknown04;
|
||||
/*08*/ uint32 rank;
|
||||
/*12*/ char member_name[64];
|
||||
/*76*/ uint32 banker;
|
||||
/*08*/ uint32 Rank;
|
||||
/*12*/ char MemberName[64];
|
||||
/*76*/ uint32 Banker;
|
||||
/*80*/
|
||||
};
|
||||
|
||||
@@ -1876,17 +1793,6 @@ struct GMSummon_Struct {
|
||||
/*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
|
||||
/* 0*/ char charname[64];
|
||||
|
||||
@@ -2642,10 +2548,7 @@ struct GMEmoteZone_Struct {
|
||||
struct BookText_Struct {
|
||||
uint8 window; // where to display the text (0xFF means new window)
|
||||
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
||||
int16 invslot; // Only used in SoF and later clients.
|
||||
int32 target_id;
|
||||
int8 can_cast;
|
||||
int8 can_scribe;
|
||||
uint32 invslot; // Only used in SoF and later clients.
|
||||
char booktext[1]; // Variable Length
|
||||
};
|
||||
// This is the request to read a book.
|
||||
@@ -2654,18 +2557,11 @@ struct BookText_Struct {
|
||||
struct BookRequest_Struct {
|
||||
uint8 window; // where to display the text (0xFF means new window)
|
||||
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
|
||||
int16 invslot; // Only used in Sof and later clients;
|
||||
int32 target_id;
|
||||
uint32 invslot; // Only used in Sof and later clients;
|
||||
int16 subslot; // The subslot inside of a bag if it is inside one.
|
||||
char txtfile[20];
|
||||
};
|
||||
|
||||
// used by Scribe and CastSpell book buttons
|
||||
struct BookButton_Struct
|
||||
{
|
||||
int16 invslot; // server slot
|
||||
int32 target_id;
|
||||
};
|
||||
|
||||
/*
|
||||
** Object/Ground Spawn struct
|
||||
** Used for Forges, Ovens, ground spawns, items dropped to ground, etc
|
||||
@@ -2677,11 +2573,11 @@ struct BookButton_Struct
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ float size; //
|
||||
/*10*/ uint16 solid_type; //
|
||||
/*10*/ uint16 solidtype; //
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
/*18*/ uint16 zone_instance; //
|
||||
/*20*/ uint32 incline; //
|
||||
/*20*/ uint32 unknown020; //
|
||||
/*24*/ uint32 unknown024; //
|
||||
/*28*/ float tilt_x;
|
||||
/*32*/ float tilt_y;
|
||||
@@ -3404,7 +3300,6 @@ struct Internal_GuildMemberEntry_Struct {
|
||||
// char public_note[1]; //variable length.
|
||||
uint16 zoneinstance; //network byte order
|
||||
uint16 zone_id; //network byte order
|
||||
uint32 online;
|
||||
};
|
||||
|
||||
struct Internal_GuildMembers_Struct { //just for display purposes, this is not actually used in the message encoding.
|
||||
@@ -3431,42 +3326,7 @@ struct GuildUpdate_PublicNote{
|
||||
uint32 unknown0;
|
||||
char name[64];
|
||||
char target[64];
|
||||
char note[256];
|
||||
};
|
||||
|
||||
struct GuildUpdateURLAndChannelStruct {
|
||||
char text[512];
|
||||
};
|
||||
|
||||
struct GuildUpdatePermissionsStruct {
|
||||
uint32 rank; // the rank that is being changed
|
||||
uint32 function_id; // the id of the guild function
|
||||
uint32 value; // 1 is on, 0 is off
|
||||
|
||||
};
|
||||
|
||||
struct GuildUpdateRankNamesStruct {
|
||||
uint32 rank; // the rank that is being updated
|
||||
char rank_name[76]; // the rank name
|
||||
};
|
||||
|
||||
struct GuildUpdateUCPStruct {
|
||||
uint32 action; // 0 and 1 use url and channel payload. 5 uses permissions payload
|
||||
char unknown[76];
|
||||
union {
|
||||
GuildUpdateURLAndChannelStruct url_channel;
|
||||
GuildUpdatePermissionsStruct permissions;
|
||||
GuildUpdateRankNamesStruct rank_name;
|
||||
}payload;
|
||||
};
|
||||
|
||||
struct GuildPermission_Struct
|
||||
{
|
||||
uint32 Action; // 5 = Update function permission
|
||||
char Unknown0004[76]; // not used
|
||||
uint32 rank; // the rank that is being changed
|
||||
uint32 function_id; // the id of the guild function
|
||||
uint32 value; // 1 is on, 0 is off
|
||||
char note[1]; //variable length.
|
||||
};
|
||||
|
||||
struct GuildUpdateURLAndChannel_Struct
|
||||
@@ -3485,7 +3345,7 @@ struct GuildUpdateURLAndChannel_Struct
|
||||
//The client sends this struct on changing a guild rank. The server sends each rank in 32 or less packets upon zonein if you are in a guild.
|
||||
struct GuildUpdateRanks_Struct
|
||||
{
|
||||
/*0000*/ uint32 Action; // 0 = Update URL, 1 = Update Channel, 4 = Ranks 5 = Permissions
|
||||
/*0000*/ uint32 Action; // 0 = Update URL, 1 = Update Channel, 5 = RoF Ranks
|
||||
/*0004*/ uint32 Unknown0004; //Seen 00 00 00 00
|
||||
/*0008*/ uint32 Unknown0008; //Seen 96 29 00 00
|
||||
/*0008*/ char Unknown0012[64]; //Seen "CharacterName"
|
||||
@@ -3507,7 +3367,6 @@ struct GuildStatus_Struct
|
||||
struct GuildDemoteStruct{
|
||||
char name[64];
|
||||
char target[64];
|
||||
uint32 rank;
|
||||
};
|
||||
|
||||
struct GuildRemoveStruct{
|
||||
@@ -3517,9 +3376,9 @@ struct GuildRemoveStruct{
|
||||
uint32 leaderstatus; //?
|
||||
};
|
||||
|
||||
struct GuildMakeLeader_Struct{
|
||||
char requestor[64];
|
||||
char new_leader[64];
|
||||
struct GuildMakeLeader{
|
||||
char name[64];
|
||||
char target[64];
|
||||
};
|
||||
|
||||
struct BugReport_Struct {
|
||||
@@ -3559,23 +3418,20 @@ struct Make_Pet_Struct { //Simple struct for getting pet info
|
||||
uint32 min_dmg;
|
||||
uint32 max_dmg;
|
||||
};
|
||||
|
||||
struct GroundSpawn {
|
||||
float max_x = 0.0f;
|
||||
float max_y = 0.0f;
|
||||
float min_x = 0.0f;
|
||||
float min_y = 0.0f;
|
||||
float max_z = 0.0f;
|
||||
float heading = 0.0f;
|
||||
std::string name = std::string();
|
||||
uint32 item_id = 0;
|
||||
uint32 max_allowed = 1;
|
||||
uint32 respawn_timer = 1;
|
||||
bool fix_z = true;
|
||||
struct Ground_Spawn{
|
||||
float max_x;
|
||||
float max_y;
|
||||
float min_x;
|
||||
float min_y;
|
||||
float max_z;
|
||||
float heading;
|
||||
char name[20];
|
||||
uint32 item;
|
||||
uint32 max_allowed;
|
||||
uint32 respawntimer;
|
||||
};
|
||||
|
||||
struct GroundSpawns {
|
||||
struct GroundSpawn spawn[50]; //Assigned max number to allow
|
||||
struct Ground_Spawns {
|
||||
struct Ground_Spawn spawn[50]; //Assigned max number to allow
|
||||
};
|
||||
|
||||
//struct PetitionBug_Struct{
|
||||
@@ -3613,193 +3469,66 @@ struct ZoneInSendName_Struct2 {
|
||||
static const uint32 MAX_TRIBUTE_TIERS = 10;
|
||||
|
||||
struct StartTribute_Struct {
|
||||
uint32 client_id;
|
||||
uint32 tribute_master_id;
|
||||
uint32 response;
|
||||
uint32 client_id;
|
||||
uint32 tribute_master_id;
|
||||
uint32 response;
|
||||
};
|
||||
|
||||
struct TributeLevel_Struct {
|
||||
uint32 level; //backwards byte order!
|
||||
uint32 tribute_item_id; //backwards byte order!
|
||||
uint32 cost; //backwards byte order!
|
||||
uint32 level; //backwards byte order!
|
||||
uint32 tribute_item_id; //backwards byte order!
|
||||
uint32 cost; //backwards byte order!
|
||||
};
|
||||
|
||||
struct TributeAbility_Struct {
|
||||
uint32 tribute_id; //backwards byte order!
|
||||
uint32 tier_count; //backwards byte order!
|
||||
uint32 tribute_id; //backwards byte order!
|
||||
uint32 tier_count; //backwards byte order!
|
||||
TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS];
|
||||
char name[0];
|
||||
};
|
||||
|
||||
struct SelectTributeReq_Struct {
|
||||
uint32 client_id; //? maybe action ID?
|
||||
uint32 tribute_id;
|
||||
uint32 unknown8; //seen E3 00 00 00
|
||||
};
|
||||
|
||||
struct GuildTributeAbilityDetail_Struct {
|
||||
uint32 tribute_id; //backwards byte order!
|
||||
uint32 tier_count; //backwards byte order!
|
||||
TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS];
|
||||
uint32 unknown132;
|
||||
char name[0];
|
||||
char name[0];
|
||||
};
|
||||
|
||||
struct GuildTributeAbility_Struct {
|
||||
uint32 guild_id;
|
||||
GuildTributeAbilityDetail_Struct ability;
|
||||
uint32 guild_id;
|
||||
TributeAbility_Struct ability;
|
||||
};
|
||||
|
||||
struct GuildTributeSelectReq_Struct {
|
||||
uint32 tribute_id;
|
||||
uint32 tier;
|
||||
uint32 tribute_id2;
|
||||
uint32 unknown12; //seen A7 01 00 00
|
||||
};
|
||||
|
||||
struct GuildTributeSelectReply_Struct {
|
||||
uint32 tribute_id;
|
||||
uint32 tier;
|
||||
uint32 tribute_id2;
|
||||
char description;
|
||||
};
|
||||
|
||||
struct GuildTributeModifyBenefits_Struct {
|
||||
/*000*/uint32 command;
|
||||
/*004*/uint32 data;
|
||||
/*008*/char unknown8[12];
|
||||
/*020*/uint32 tribute_master_id;
|
||||
/*024*/uint32 tribute_id_1;
|
||||
/*028*/uint32 tribute_id_2;
|
||||
/*032*/uint32 tribute_id_1_tier;
|
||||
/*036*/uint32 tribute_id_2_tier;
|
||||
/*040*/char unknown[40];
|
||||
};
|
||||
|
||||
struct GuildTributeOptInOutReq_Struct {
|
||||
/*000*/uint32 guild_id;
|
||||
/*004*/uint32 tribute_toggle;
|
||||
/*008*/char player[64];
|
||||
/*072*/uint32 command;
|
||||
/*076*/uint32 tribute_master_id;
|
||||
};
|
||||
|
||||
struct GuildTributeOptInOutReply_Struct {
|
||||
/*000*/uint32 guild_id;
|
||||
/*004*/char player_name[64];
|
||||
/*068*/uint32 tribute_toggle;// 0 off 1 on
|
||||
/*072*/uint32 tribute_trophy_toggle;// 0 off 1 on not yet implemented
|
||||
/*076*/uint32 no_donations;
|
||||
/*080*/uint32 time;
|
||||
/*084*/uint32 command;
|
||||
};
|
||||
|
||||
struct GuildTributeSaveActive_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ char unknown04[16];
|
||||
/*020*/ uint32 master_tribute_id;
|
||||
/*024*/ uint32 tribute_id_1;
|
||||
/*028*/ uint32 tribute_id_2;
|
||||
/*032*/ uint32 tribute_1_tier;
|
||||
/*036*/ uint32 tribute_2_tier;
|
||||
/*040*/ char unknown40[8];
|
||||
};
|
||||
|
||||
struct GuildTributeFavorTimer_Struct {
|
||||
/*000*/ uint32 guild_id;
|
||||
/*004*/ uint32 guild_favor;
|
||||
/*008*/ uint32 tribute_timer;
|
||||
/*012*/ uint32 trophy_timer;
|
||||
};
|
||||
|
||||
struct GuildTributeSendActive_Struct {
|
||||
/*000*/ uint32 not_used;
|
||||
/*004*/ uint32 guild_favor;
|
||||
/*008*/ uint32 tribute_timer;
|
||||
/*012*/ uint32 tribute_enabled;
|
||||
/*016*/ char unknown16[8];
|
||||
/*024*/ uint32 tribute_id_1;
|
||||
/*028*/ uint32 tribute_id_2;
|
||||
/*032*/ uint32 tribute_id_1_tier;
|
||||
/*036*/ uint32 tribute_id_2_tier;
|
||||
};
|
||||
|
||||
struct GuildTributeToggleReq_Struct {
|
||||
/*000*/ uint32 command;
|
||||
/*004*/ uint32 unknown4;
|
||||
/*008*/ uint32 unknown8;
|
||||
};
|
||||
|
||||
struct GuildTributeDonateItemRequest_Struct {
|
||||
/*000*/ uint32 type;
|
||||
/*004*/ uint16 slot;
|
||||
/*006*/ uint16 sub_index;
|
||||
/*008*/ uint16 aug_index;
|
||||
/*010*/ uint16 unknown10;
|
||||
/*012*/ uint32 quantity;
|
||||
/*016*/ uint32 tribute_master_id;
|
||||
/*020*/ uint32 unknown20;
|
||||
/*024*/ uint32 guild_id;
|
||||
/*028*/ uint32 unknown28;
|
||||
/*032*/ uint32 unknown32;
|
||||
};
|
||||
|
||||
struct GuildTributeDonateItemReply_Struct {
|
||||
/*000*/ uint32 type;
|
||||
/*004*/ uint16 slot;
|
||||
/*006*/ uint16 sub_index;
|
||||
/*008*/ uint16 aug_index;
|
||||
/*010*/ uint16 unknown10;
|
||||
/*012*/ uint32 quantity;
|
||||
/*016*/ uint32 unknown20;
|
||||
/*020*/ uint32 favor;
|
||||
};
|
||||
|
||||
struct GuildTributeDonatePlatRequest_Struct {
|
||||
/*000*/ uint32 quantity;
|
||||
/*004*/ uint32 tribute_master_id;
|
||||
/*008*/ uint32 unknown08;
|
||||
/*012*/ uint32 guild_id;
|
||||
/*016*/ uint32 unknown16;
|
||||
};
|
||||
|
||||
struct GuildTributeDonatePlatReply_Struct {
|
||||
/*000*/ uint32 quantity;
|
||||
/*004*/ uint32 unknown4;
|
||||
/*008*/ uint32 favor;
|
||||
struct SelectTributeReq_Struct {
|
||||
uint32 client_id; //? maybe action ID?
|
||||
uint32 tribute_id;
|
||||
uint32 unknown8; //seen E3 00 00 00
|
||||
};
|
||||
|
||||
struct SelectTributeReply_Struct {
|
||||
uint32 client_id; //echoed from request.
|
||||
uint32 tribute_id;
|
||||
char description[0];
|
||||
uint32 client_id; //echoed from request.
|
||||
uint32 tribute_id;
|
||||
char desc[0];
|
||||
};
|
||||
|
||||
struct TributeInfo_Struct {
|
||||
uint32 active; //0 == inactive, 1 == active
|
||||
uint32 tributes[EQ::invtype::TRIBUTE_SIZE]; //-1 == NONE
|
||||
uint32 tiers[EQ::invtype::TRIBUTE_SIZE]; //all 00's
|
||||
uint32 tribute_master_id;
|
||||
uint32 active; //0 == inactive, 1 == active
|
||||
uint32 tributes[EQ::invtype::TRIBUTE_SIZE]; //-1 == NONE
|
||||
uint32 tiers[EQ::invtype::TRIBUTE_SIZE]; //all 00's
|
||||
uint32 tribute_master_id;
|
||||
};
|
||||
|
||||
struct TributeItem_Struct {
|
||||
uint32 slot;
|
||||
uint32 quantity;
|
||||
uint32 tribute_master_id;
|
||||
int32 tribute_points;
|
||||
uint32 slot;
|
||||
uint32 quantity;
|
||||
uint32 tribute_master_id;
|
||||
int32 tribute_points;
|
||||
};
|
||||
|
||||
struct TributePoint_Struct {
|
||||
int32 tribute_points;
|
||||
uint32 unknown04;
|
||||
int32 career_tribute_points;
|
||||
uint32 unknown12;
|
||||
int32 tribute_points;
|
||||
uint32 unknown04;
|
||||
int32 career_tribute_points;
|
||||
uint32 unknown12;
|
||||
};
|
||||
|
||||
struct TributeMoney_Struct {
|
||||
uint32 platinum;
|
||||
uint32 tribute_master_id;
|
||||
int32 tribute_points;
|
||||
uint32 platinum;
|
||||
uint32 tribute_master_id;
|
||||
int32 tribute_points;
|
||||
};
|
||||
|
||||
|
||||
@@ -3903,19 +3632,17 @@ struct LevelAppearance_Struct { //Sends a little graphic on level up
|
||||
};
|
||||
|
||||
struct MerchantList {
|
||||
uint32 id;
|
||||
uint32 slot;
|
||||
uint32 item;
|
||||
int16 faction_required;
|
||||
int8 level_required;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
uint16 alt_currency_cost;
|
||||
uint32 classes_required;
|
||||
uint8 probability;
|
||||
uint32 id;
|
||||
uint32 slot;
|
||||
uint32 item;
|
||||
int16 faction_required;
|
||||
int8 level_required;
|
||||
uint16 alt_currency_cost;
|
||||
uint32 classes_required;
|
||||
uint8 probability;
|
||||
std::string bucket_name;
|
||||
std::string bucket_value;
|
||||
uint8 bucket_comparison;
|
||||
uint8 bucket_comparison;
|
||||
};
|
||||
|
||||
struct TempMerchantList {
|
||||
@@ -4365,9 +4092,7 @@ struct UpdateLeadershipAA_Struct {
|
||||
|
||||
enum
|
||||
{
|
||||
GroupLeadershipAbility_MarkNPC = 0,
|
||||
RaidLeadershipAbility_MarkNPC = 16,
|
||||
RaidLeadershipAbility_MainAssist = 19
|
||||
GroupLeadershipAbility_MarkNPC = 0
|
||||
};
|
||||
|
||||
struct DoGroupLeadershipAbility_Struct
|
||||
@@ -4411,9 +4136,8 @@ struct InspectBuffs_Struct {
|
||||
struct RaidGeneral_Struct {
|
||||
/*00*/ uint32 action; //=10
|
||||
/*04*/ char player_name[64]; //should both be the player's name
|
||||
/*68*/ uint32 unknown1;
|
||||
/*72*/ char leader_name[64];
|
||||
/*136*/ uint32 parameter;
|
||||
/*64*/ char leader_name[64];
|
||||
/*132*/ uint32 parameter;
|
||||
};
|
||||
|
||||
struct RaidAddMember_Struct {
|
||||
@@ -4424,14 +4148,9 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidNote_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char note[64];
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general;
|
||||
/*140*/ char motd[1024];
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*136*/ char motd[0]; // max size is 1024, but reply is variable
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
@@ -4826,7 +4545,7 @@ struct ItemVerifyReply_Struct {
|
||||
struct ItemRecastDelay_Struct {
|
||||
/*000*/ uint32 recast_delay; // in seconds
|
||||
/*004*/ uint32 recast_type;
|
||||
/*008*/ bool ignore_casting_requirement; //Ignores recast times allows items to be reset?
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
@@ -5378,6 +5097,8 @@ struct GroupMakeLeader_Struct
|
||||
//ex for a blank crowns window you would send:
|
||||
//999999|1|999999|0
|
||||
//any items come after in much the same way adventure merchant items do except there is no theme included
|
||||
#define ALT_CURRENCY_OP_POPULATE 8
|
||||
#define ALT_CURRENCY_OP_UPDATE 7
|
||||
|
||||
//Server -> Client
|
||||
//Populates the initial Alternate Currency Window
|
||||
@@ -5442,10 +5163,10 @@ struct AltCurrencySelectItemReply_Struct {
|
||||
/*000*/ uint32 unknown000;
|
||||
/*004*/ uint8 unknown004; //0xff
|
||||
/*005*/ uint8 unknown005; //0xff
|
||||
/*006*/ uint16 unknown006; //0xffff
|
||||
/*008*/ uint16 unknown008; //0xffff
|
||||
/*010*/ char item_name[64];
|
||||
/*074*/ uint16 unknown074;
|
||||
/*006*/ uint8 unknown006; //0xff
|
||||
/*007*/ uint8 unknown007; //0xff
|
||||
/*008*/ char item_name[64];
|
||||
/*072*/ uint32 unknown074;
|
||||
/*076*/ uint32 cost;
|
||||
/*080*/ uint32 unknown080;
|
||||
/*084*/ uint32 unknown084;
|
||||
@@ -5788,6 +5509,24 @@ struct MercenaryMerchantResponse_Struct {
|
||||
/*0004*/
|
||||
};
|
||||
|
||||
struct ServerLootItem_Struct {
|
||||
uint32 item_id; // uint32 item_id;
|
||||
int16 equip_slot; // int16 equip_slot;
|
||||
uint16 charges; // uint8 charges;
|
||||
uint16 lootslot; // uint16 lootslot;
|
||||
uint32 aug_1; // uint32 aug_1;
|
||||
uint32 aug_2; // uint32 aug_2;
|
||||
uint32 aug_3; // uint32 aug_3;
|
||||
uint32 aug_4; // uint32 aug_4;
|
||||
uint32 aug_5; // uint32 aug_5;
|
||||
uint32 aug_6; // uint32 aug_5;
|
||||
uint8 attuned;
|
||||
uint16 trivial_min_level;
|
||||
uint16 trivial_max_level;
|
||||
uint16 npc_min_level;
|
||||
uint16 npc_max_level;
|
||||
};
|
||||
|
||||
//Found in client near a ref to the string:
|
||||
//"Got a broadcast message for ... %s ...\n"
|
||||
struct ClientMarqueeMessage_Struct {
|
||||
@@ -5806,6 +5545,9 @@ struct ClientMarqueeMessage_Struct {
|
||||
|
||||
};
|
||||
|
||||
typedef std::list<ServerLootItem_Struct*> ItemList;
|
||||
|
||||
|
||||
struct fling_struct {
|
||||
/* 00 */ uint32 collision; // 0 collision is off, anything else it's on
|
||||
/* 04 */ int32 travel_time; // ms -- UF we need to calc this, RoF+ -1 auto calcs
|
||||
|
||||
@@ -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;
|
||||
p->signature = sig;
|
||||
p->name = name;
|
||||
@@ -145,7 +145,7 @@ void EQStreamIdentifier::Process() {
|
||||
}
|
||||
|
||||
void EQStreamIdentifier::AddStream(std::shared_ptr<EQStreamInterface> eqs) {
|
||||
m_streams.emplace_back(Record(eqs));
|
||||
m_streams.push_back(Record(eqs));
|
||||
eqs = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
~EQStreamIdentifier();
|
||||
|
||||
//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
|
||||
void Process();
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
EQDB EQDB::s_EQDB;
|
||||
|
||||
EQDB::EQDB() {
|
||||
}
|
||||
|
||||
unsigned int EQDB::field_count() {
|
||||
return mysql_field_count(mysql_ref);
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
|
||||
//this is the main object exported to perl.
|
||||
class EQDB {
|
||||
EQDB() = default;
|
||||
EQDB();
|
||||
public:
|
||||
static EQDB *Singleton() { return(&s_EQDB); }
|
||||
|
||||
|
||||
+36
-133
@@ -19,13 +19,9 @@
|
||||
#include "../common/global_define.h"
|
||||
#include "eqemu_config.h"
|
||||
#include "misc_functions.h"
|
||||
#include "strings.h"
|
||||
#include "eqemu_logsys.h"
|
||||
#include "json/json.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
|
||||
EQEmuConfig *EQEmuConfig::_config = nullptr;
|
||||
@@ -37,13 +33,13 @@ void EQEmuConfig::parse_config()
|
||||
LongName = _root["server"]["world"].get("longname", "").asString();
|
||||
WorldAddress = _root["server"]["world"].get("address", "").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();
|
||||
LoginCount = 0;
|
||||
|
||||
if (_root["server"]["world"]["loginserver"].isObject()) {
|
||||
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;
|
||||
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
|
||||
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
||||
@@ -66,7 +62,7 @@ void EQEmuConfig::parse_config()
|
||||
|
||||
auto loginconfig = new LoginConfig;
|
||||
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->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
|
||||
|
||||
@@ -88,22 +84,17 @@ 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
|
||||
Locked = false;
|
||||
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();
|
||||
WorldTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["tcp"].get("port", "9000").asString());
|
||||
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
|
||||
WorldUDPPort = atoi(_root["server"]["world"]["udp"].get("port", "9000").asString().c_str());
|
||||
|
||||
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
||||
TelnetTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["telnet"].get("port", "9001").asString());
|
||||
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
|
||||
TelnetEnabled = false;
|
||||
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; }
|
||||
|
||||
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;
|
||||
|
||||
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
|
||||
@@ -114,12 +105,13 @@ void EQEmuConfig::parse_config()
|
||||
DisableConfigChecks = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CheckUcsConfigConversion();
|
||||
|
||||
m_ucs_host = _root["server"]["ucs"].get("host", "eqchat.eqemulator.net").asString();
|
||||
m_ucs_port = Strings::ToUnsignedInt(_root["server"]["ucs"].get("port", "7778").asString());
|
||||
/**
|
||||
* UCS
|
||||
*/
|
||||
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
||||
ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
|
||||
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
||||
MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
|
||||
|
||||
/**
|
||||
* Database
|
||||
@@ -127,7 +119,7 @@ void EQEmuConfig::parse_config()
|
||||
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
|
||||
DatabasePassword = _root["server"]["database"].get("password", "eq").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();
|
||||
|
||||
/**
|
||||
@@ -136,14 +128,14 @@ void EQEmuConfig::parse_config()
|
||||
ContentDbUsername = _root["server"]["content_database"].get("username", "").asString();
|
||||
ContentDbPassword = _root["server"]["content_database"].get("password", "").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();
|
||||
|
||||
/**
|
||||
* QS
|
||||
*/
|
||||
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();
|
||||
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
|
||||
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
||||
@@ -151,9 +143,9 @@ void EQEmuConfig::parse_config()
|
||||
/**
|
||||
* Zones
|
||||
*/
|
||||
DefaultStatus = Strings::ToUnsignedInt(_root["server"]["zones"].get("defaultstatus", 0).asString());
|
||||
ZonePortLow = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("low", "7000").asString());
|
||||
ZonePortHigh = Strings::ToUnsignedInt(_root["server"]["zones"]["ports"].get("high", "7999").asString());
|
||||
DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
|
||||
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
|
||||
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
|
||||
|
||||
/**
|
||||
* Files
|
||||
@@ -183,10 +175,10 @@ void EQEmuConfig::parse_config()
|
||||
/**
|
||||
* Launcher
|
||||
*/
|
||||
RestartWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("restart", "10000").asString());
|
||||
TerminateWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString());
|
||||
InitialBootWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("initial", "20000").asString());
|
||||
ZoneBootInterval = Strings::ToInt(_root["server"]["launcher"]["timers"].get("interval", "2000").asString());
|
||||
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
|
||||
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
|
||||
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
|
||||
ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str());
|
||||
#ifdef WIN32
|
||||
ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString();
|
||||
#else
|
||||
@@ -226,6 +218,9 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
||||
if (var_name == "WorldTCPPort") {
|
||||
return (itoa(WorldTCPPort));
|
||||
}
|
||||
if (var_name == "WorldUDPPort") {
|
||||
return (itoa(WorldUDPPort));
|
||||
}
|
||||
if (var_name == "WorldIP") {
|
||||
return (WorldIP);
|
||||
}
|
||||
@@ -248,16 +243,16 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
||||
return (WorldHTTPEnabled ? "true" : "false");
|
||||
}
|
||||
if (var_name == "ChatHost") {
|
||||
return (m_ucs_host);
|
||||
return (ChatHost);
|
||||
}
|
||||
if (var_name == "ChatPort") {
|
||||
return (itoa(m_ucs_port));
|
||||
return (itoa(ChatPort));
|
||||
}
|
||||
if (var_name == "MailHost") {
|
||||
return (m_ucs_host);
|
||||
return (MailHost);
|
||||
}
|
||||
if (var_name == "MailPort") {
|
||||
return (itoa(m_ucs_port));
|
||||
return (itoa(MailPort));
|
||||
}
|
||||
if (var_name == "DatabaseHost") {
|
||||
return (DatabaseHost);
|
||||
@@ -357,6 +352,7 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "LoginLegacy = " << LoginLegacy << std::endl;
|
||||
std::cout << "Locked = " << Locked << std::endl;
|
||||
std::cout << "WorldTCPPort = " << WorldTCPPort << std::endl;
|
||||
std::cout << "WorldUDPPort = " << WorldUDPPort << std::endl;
|
||||
std::cout << "WorldIP = " << WorldIP << std::endl;
|
||||
std::cout << "TelnetTCPPort = " << TelnetTCPPort << std::endl;
|
||||
std::cout << "TelnetIP = " << TelnetIP << std::endl;
|
||||
@@ -364,8 +360,10 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "WorldHTTPPort = " << WorldHTTPPort << std::endl;
|
||||
std::cout << "WorldHTTPMimeFile = " << WorldHTTPMimeFile << std::endl;
|
||||
std::cout << "WorldHTTPEnabled = " << WorldHTTPEnabled << std::endl;
|
||||
std::cout << "UCSHost = " << m_ucs_host << std::endl;
|
||||
std::cout << "UCSPort = " << m_ucs_port << std::endl;
|
||||
std::cout << "ChatHost = " << ChatHost << std::endl;
|
||||
std::cout << "ChatPort = " << ChatPort << std::endl;
|
||||
std::cout << "MailHost = " << MailHost << std::endl;
|
||||
std::cout << "MailPort = " << MailPort << std::endl;
|
||||
std::cout << "DatabaseHost = " << DatabaseHost << std::endl;
|
||||
std::cout << "DatabaseUsername = " << DatabaseUsername << std::endl;
|
||||
std::cout << "DatabasePassword = " << DatabasePassword << std::endl;
|
||||
@@ -392,98 +390,3 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl;
|
||||
// std::cout << "DynamicCount = " << DynamicCount << std::endl;
|
||||
}
|
||||
|
||||
const std::string &EQEmuConfig::GetUCSHost() const
|
||||
{
|
||||
return m_ucs_host;
|
||||
}
|
||||
|
||||
uint16 EQEmuConfig::GetUCSPort() const
|
||||
{
|
||||
return m_ucs_port;
|
||||
}
|
||||
|
||||
void EQEmuConfig::CheckUcsConfigConversion()
|
||||
{
|
||||
std::string chat_host = _root["server"]["chatserver"].get("host", "").asString();
|
||||
uint32 chat_port = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "0").asString());
|
||||
std::string mail_host = _root["server"]["mailserver"].get("host", "").asString();
|
||||
uint32 mail_port = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "0").asString());
|
||||
std::string ucs_host = _root["server"]["ucs"].get("host", "").asString();
|
||||
|
||||
// automatic ucs legacy configuration migration
|
||||
// if old configuration values are set, let's backup the existing configuration
|
||||
// and migrate to to use the new fields and write the new config
|
||||
if ((!chat_host.empty() || !mail_host.empty()) && ucs_host.empty()) {
|
||||
LogInfo("Migrating old [eqemu_config] UCS configuration to new configuration");
|
||||
|
||||
std::string config_file_path = std::filesystem::path{
|
||||
path.GetServerPath() + "/eqemu_config.json"
|
||||
}.string();
|
||||
|
||||
std::string config_file_bak_path = std::filesystem::path{
|
||||
path.GetServerPath() + "/eqemu_config.ucs-migrate-json.bak"
|
||||
}.string();
|
||||
|
||||
// copy eqemu_config.json to eqemu_config.json.bak
|
||||
std::ifstream src(config_file_path, std::ios::binary);
|
||||
std::ofstream dst(config_file_bak_path, std::ios::binary);
|
||||
dst << src.rdbuf();
|
||||
src.close();
|
||||
|
||||
LogInfo("Old configuration backed up to [{}]", config_file_bak_path);
|
||||
|
||||
// read eqemu_config.json, transplant new fields and write to eqemu_config.json
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
std::ifstream file(config_file_path);
|
||||
if (!reader.parse(file, root)) {
|
||||
LogError("Failed to parse configuration file");
|
||||
return;
|
||||
}
|
||||
file.close();
|
||||
|
||||
// get old fields
|
||||
std::string host = !chat_host.empty() ? chat_host : mail_host;
|
||||
if (host.empty()) {
|
||||
host = "eqchat.eqemulator.net";
|
||||
}
|
||||
std::string port = chat_port > 0 ? std::to_string(chat_port) : std::to_string(mail_port);
|
||||
if (port.empty()) {
|
||||
port = "7778";
|
||||
}
|
||||
|
||||
// set new fields
|
||||
root["server"]["ucs"]["host"] = host;
|
||||
root["server"]["ucs"]["port"] = port;
|
||||
|
||||
// unset old fields
|
||||
root["server"].removeMember("chatserver");
|
||||
root["server"].removeMember("mailserver");
|
||||
|
||||
// get Json::Value raw string
|
||||
std::string config = root.toStyledString();
|
||||
|
||||
// format using more modern json library
|
||||
nlohmann::json data = nlohmann::json::parse(config);
|
||||
|
||||
// write to file
|
||||
std::ofstream o(config_file_path);
|
||||
o << std::setw(1) << data << std::endl;
|
||||
o.close();
|
||||
|
||||
// write new config
|
||||
LogInfo("New configuration written to [{}]", config_file_path);
|
||||
LogInfo("Migration complete, please review the new configuration file");
|
||||
|
||||
// reload config internally
|
||||
try {
|
||||
std::ifstream fconfig(config_file_path, std::ifstream::binary);
|
||||
fconfig >> _config->_root;
|
||||
_config->parse_config();
|
||||
}
|
||||
catch (std::exception &) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-9
@@ -51,6 +51,7 @@ class EQEmuConfig
|
||||
LinkedList<LoginConfig*> loginlist;
|
||||
bool Locked;
|
||||
uint16 WorldTCPPort;
|
||||
uint16 WorldUDPPort;
|
||||
std::string WorldIP;
|
||||
uint16 TelnetTCPPort;
|
||||
std::string TelnetIP;
|
||||
@@ -62,6 +63,14 @@ class EQEmuConfig
|
||||
std::string SharedKey;
|
||||
bool DisableConfigChecks;
|
||||
|
||||
// From <chatserver/>
|
||||
std::string ChatHost;
|
||||
uint16 ChatPort;
|
||||
|
||||
// From <mailserver/>
|
||||
std::string MailHost;
|
||||
uint16 MailPort;
|
||||
|
||||
// From <database/>
|
||||
std::string DatabaseHost;
|
||||
std::string DatabaseUsername;
|
||||
@@ -112,20 +121,12 @@ class EQEmuConfig
|
||||
uint16 ZonePortHigh;
|
||||
uint8 DefaultStatus;
|
||||
|
||||
bool auto_database_updates;
|
||||
|
||||
const std::string &GetUCSHost() const;
|
||||
uint16 GetUCSPort() const;
|
||||
|
||||
// uint16 DynamicCount;
|
||||
|
||||
// map<string,uint16> StaticZones;
|
||||
|
||||
protected:
|
||||
|
||||
std::string m_ucs_host;
|
||||
uint16 m_ucs_port;
|
||||
|
||||
static EQEmuConfig *_config;
|
||||
Json::Value _root;
|
||||
static std::string ConfigFile;
|
||||
@@ -147,6 +148,12 @@ class EQEmuConfig
|
||||
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
|
||||
static bool LoadConfig(const std::string& path = "")
|
||||
{
|
||||
@@ -184,7 +191,6 @@ class EQEmuConfig
|
||||
}
|
||||
|
||||
void Dump() const;
|
||||
void CheckUcsConfigConversion();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+194
-253
@@ -22,19 +22,21 @@
|
||||
#include "rulesys.h"
|
||||
#include "platform.h"
|
||||
#include "strings.h"
|
||||
#include "misc.h"
|
||||
#include "discord/discord.h"
|
||||
#include "repositories/discord_webhooks_repository.h"
|
||||
#include "repositories/logsys_categories_repository.h"
|
||||
#include "termcolor/rang.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <algorithm>
|
||||
|
||||
std::ofstream process_log;
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <direct.h>
|
||||
#include <conio.h>
|
||||
@@ -50,12 +52,46 @@ std::ofstream process_log;
|
||||
|
||||
#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::EQEmuLogSys()
|
||||
{
|
||||
m_on_log_gmsay_hook = [](uint16 log_type, const char *func, const std::string &) {};
|
||||
m_on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
|
||||
m_on_log_console_hook = [](uint16 log_type, const std::string &) {};
|
||||
}
|
||||
|
||||
@@ -84,8 +120,14 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
/**
|
||||
* Set Defaults
|
||||
*/
|
||||
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
|
||||
@@ -98,17 +140,17 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::ChecksumVerification].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::CombatRecord].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::EqTime].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::EqTime].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
|
||||
/**
|
||||
* RFC 5424
|
||||
*/
|
||||
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::Info].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Emergency].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Alert].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Critical].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::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
|
||||
@@ -152,6 +194,24 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
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 debug_level
|
||||
* @param log_category
|
||||
@@ -182,6 +242,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
|
||||
* @return
|
||||
@@ -189,10 +307,11 @@ void EQEmuLogSys::ProcessLogWrite(
|
||||
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
||||
{
|
||||
switch (log_category) {
|
||||
case Logs::Crash:
|
||||
case Logs::Error:
|
||||
case Logs::Status:
|
||||
case Logs::Normal:
|
||||
return Chat::Yellow;
|
||||
case Logs::MySQLError:
|
||||
case Logs::QuestErrors:
|
||||
case Logs::Error:
|
||||
return Chat::Red;
|
||||
case Logs::MySQLQuery:
|
||||
case Logs::Debug:
|
||||
@@ -202,206 +321,35 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
||||
case Logs::Commands:
|
||||
case Logs::Mercenaries:
|
||||
return Chat::Magenta;
|
||||
case Logs::Crash:
|
||||
return Chat::Red;
|
||||
default:
|
||||
return Chat::Yellow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param debug_level
|
||||
* @param log_category
|
||||
* @param message
|
||||
*/
|
||||
void EQEmuLogSys::ProcessConsoleMessage(
|
||||
uint16 log_category,
|
||||
const std::string &message,
|
||||
const char *file,
|
||||
const char *func,
|
||||
int line
|
||||
)
|
||||
void EQEmuLogSys::ProcessConsoleMessage(uint16 log_category, const std::string &message)
|
||||
{
|
||||
bool is_error = (
|
||||
log_category == Logs::LogCategory::Error ||
|
||||
log_category == Logs::LogCategory::MySQLError ||
|
||||
log_category == Logs::LogCategory::Crash ||
|
||||
log_category == Logs::LogCategory::QuestErrors
|
||||
);
|
||||
bool is_warning = (
|
||||
log_category == Logs::LogCategory::Warning
|
||||
);
|
||||
|
||||
(!is_error ? std::cout : std::cerr)
|
||||
<< ""
|
||||
<< 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;
|
||||
#ifdef _WINDOWS
|
||||
HANDLE console_handle;
|
||||
console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_FONT_INFOEX info = { 0 };
|
||||
info.cbSize = sizeof(info);
|
||||
info.dwFontSize.Y = 12; // leave X as zero
|
||||
info.FontWeight = FW_NORMAL;
|
||||
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
|
||||
|
||||
m_on_log_console_hook(log_category, message);
|
||||
}
|
||||
@@ -415,6 +363,33 @@ constexpr const char *str_end(const char *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
|
||||
*
|
||||
@@ -442,14 +417,12 @@ void EQEmuLogSys::Out(
|
||||
|
||||
std::string prefix;
|
||||
if (RuleB(Logging, PrintFileFunctionAndLine)) {
|
||||
prefix = fmt::format("[{0}::{1}:{2}] ", std::filesystem::path(file).filename().string(), func, line);
|
||||
prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
|
||||
}
|
||||
|
||||
// remove this when we remove all legacy logs
|
||||
bool ignore_log_legacy_format = (
|
||||
log_category == Logs::Netcode ||
|
||||
log_category == Logs::MySQLQuery ||
|
||||
log_category == Logs::MySQLError ||
|
||||
log_category == Logs::PacketServerClient ||
|
||||
log_category == Logs::PacketClientServer ||
|
||||
log_category == Logs::PacketServerToServer
|
||||
@@ -467,14 +440,11 @@ void EQEmuLogSys::Out(
|
||||
if (l.log_to_console_enabled) {
|
||||
EQEmuLogSys::ProcessConsoleMessage(
|
||||
log_category,
|
||||
output_message,
|
||||
file,
|
||||
func,
|
||||
line
|
||||
fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message)
|
||||
);
|
||||
}
|
||||
if (l.log_to_gmsay_enabled) {
|
||||
m_on_log_gmsay_hook(log_category, func, output_message);
|
||||
m_on_log_gmsay_hook(log_category, output_message);
|
||||
}
|
||||
if (l.log_to_file_enabled) {
|
||||
EQEmuLogSys::ProcessLogWrite(
|
||||
@@ -584,14 +554,10 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
|
||||
*/
|
||||
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++) {
|
||||
log_settings[log_index].log_to_console = 0;
|
||||
log_settings[log_index].is_category_enabled = 0;
|
||||
}
|
||||
|
||||
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -599,7 +565,10 @@ void EQEmuLogSys::SilenceConsoleLogging()
|
||||
*/
|
||||
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()
|
||||
@@ -651,24 +620,21 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
|
||||
}
|
||||
|
||||
// Auto inject categories that don't exist in the database...
|
||||
|
||||
std::vector<LogsysCategoriesRepository::LogsysCategories> db_categories_to_add{};
|
||||
|
||||
for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) {
|
||||
|
||||
bool is_missing_in_database = std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end();
|
||||
bool is_deprecated_category = Strings::Contains(fmt::format("{}", Logs::LogCategoryName[i]), "Deprecated");
|
||||
if (!is_missing_in_database && is_deprecated_category) {
|
||||
LogInfo(
|
||||
"Logging category [{}] ({}) is now deprecated, deleting from database",
|
||||
Logs::LogCategoryName[i],
|
||||
i
|
||||
);
|
||||
LogInfo("Logging category [{}] ({}) is now deprecated, deleting from database", Logs::LogCategoryName[i], i);
|
||||
LogsysCategoriesRepository::DeleteOne(*m_database, i);
|
||||
}
|
||||
|
||||
if (is_missing_in_database && !is_deprecated_category) {
|
||||
LogInfo("Automatically adding new log category [{}] ({})", Logs::LogCategoryName[i], i);
|
||||
LogInfo(
|
||||
"Automatically adding new log category [{}] ({})",
|
||||
Logs::LogCategoryName[i],
|
||||
i
|
||||
);
|
||||
|
||||
auto new_category = LogsysCategoriesRepository::NewEntity();
|
||||
new_category.log_category_id = i;
|
||||
@@ -677,14 +643,9 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
|
||||
new_category.log_to_gmsay = log_settings[i].log_to_gmsay;
|
||||
new_category.log_to_file = log_settings[i].log_to_file;
|
||||
new_category.log_to_discord = log_settings[i].log_to_discord;
|
||||
db_categories_to_add.emplace_back(new_category);
|
||||
}
|
||||
}
|
||||
|
||||
if (!db_categories_to_add.empty()) {
|
||||
LogsysCategoriesRepository::ReplaceMany(*m_database, db_categories_to_add);
|
||||
LoadLogDatabaseSettings();
|
||||
return this;
|
||||
LogsysCategoriesRepository::InsertOne(*m_database, new_category);
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] log categories", categories.size());
|
||||
@@ -697,13 +658,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
|
||||
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);
|
||||
log_settings[Logs::Info].log_to_file = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -800,23 +754,10 @@ const std::string &EQEmuLogSys::GetLogPath() const
|
||||
return m_log_path;
|
||||
}
|
||||
|
||||
EQEmuLogSys *EQEmuLogSys::SetLogPath(const std::string &log_path)
|
||||
EQEmuLogSys * EQEmuLogSys::SetLogPath(const std::string &log_path)
|
||||
{
|
||||
EQEmuLogSys::m_log_path = log_path;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void EQEmuLogSys::DisableMySQLErrorLogs()
|
||||
{
|
||||
log_settings[Logs::MySQLError].log_to_file = 0;
|
||||
log_settings[Logs::MySQLError].log_to_console = 0;
|
||||
log_settings[Logs::MySQLError].log_to_gmsay = 0;
|
||||
}
|
||||
|
||||
void EQEmuLogSys::EnableMySQLErrorLogs()
|
||||
{
|
||||
log_settings[Logs::MySQLError].log_to_file = 1;
|
||||
log_settings[Logs::MySQLError].log_to_console = 1;
|
||||
log_settings[Logs::MySQLError].log_to_gmsay = 1;
|
||||
}
|
||||
|
||||
+62
-83
@@ -39,7 +39,8 @@
|
||||
namespace Logs {
|
||||
enum DebugLevel {
|
||||
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,
|
||||
Aggro,
|
||||
Attack,
|
||||
DeprecatedCS, // deprecated
|
||||
DeprecatedCS,
|
||||
Combat,
|
||||
Commands,
|
||||
Crash,
|
||||
@@ -64,36 +65,36 @@ namespace Logs {
|
||||
Inventory,
|
||||
Launcher,
|
||||
Netcode,
|
||||
Normal, // deprecated
|
||||
Normal,
|
||||
Object,
|
||||
Pathing,
|
||||
QSServer, // deprecated
|
||||
QSServer,
|
||||
Quests,
|
||||
Rules,
|
||||
Skills,
|
||||
Spawns,
|
||||
Spells,
|
||||
Status, // deprecated
|
||||
Status,
|
||||
TCPConnection,
|
||||
Tasks,
|
||||
Tradeskills,
|
||||
Trading,
|
||||
Tribute,
|
||||
UCSServer, // deprecated
|
||||
WebInterfaceServer, // deprecated
|
||||
WorldServer, // deprecated
|
||||
ZoneServer, // deprecated
|
||||
UCSServer,
|
||||
WebInterfaceServer,
|
||||
WorldServer,
|
||||
ZoneServer,
|
||||
MySQLError,
|
||||
MySQLQuery,
|
||||
Mercenaries,
|
||||
QuestDebug,
|
||||
DeprecatedSC, // deprecated
|
||||
DeprecatedCSU, // deprecated
|
||||
DeprecatedSCD, // deprecated
|
||||
DeprecatedCSD, // deprecated
|
||||
Loginserver, // deprecated
|
||||
DeprecatedSC,
|
||||
DeprecatedCSU,
|
||||
DeprecatedSCD,
|
||||
DeprecatedCSD,
|
||||
Loginserver,
|
||||
ClientLogin,
|
||||
HeadlessClient, // deprecated
|
||||
HeadlessClient,
|
||||
HPUpdate,
|
||||
FixZ,
|
||||
Food,
|
||||
@@ -103,10 +104,10 @@ namespace Logs {
|
||||
MobAppearance,
|
||||
Info,
|
||||
Warning,
|
||||
Critical, // deprecated
|
||||
Emergency, // deprecated
|
||||
Alert, // deprecated
|
||||
Notice, // deprecated
|
||||
Critical,
|
||||
Emergency,
|
||||
Alert,
|
||||
Notice,
|
||||
AIScanClose,
|
||||
AIYellForHelp,
|
||||
AICastBeneficialClose,
|
||||
@@ -134,13 +135,6 @@ namespace Logs {
|
||||
PacketServerClient,
|
||||
PacketClientServer,
|
||||
PacketServerToServer,
|
||||
Bugs,
|
||||
QuestErrors,
|
||||
PlayerEvents,
|
||||
DataBuckets,
|
||||
Zoning,
|
||||
EqTime,
|
||||
Corpses,
|
||||
MaxCategoryID /* Don't Remove this */
|
||||
};
|
||||
|
||||
@@ -164,52 +158,52 @@ namespace Logs {
|
||||
"Inventory",
|
||||
"Launcher",
|
||||
"Netcode",
|
||||
"Normal (Deprecated)",
|
||||
"Normal",
|
||||
"Object",
|
||||
"Pathing",
|
||||
"QS Server (Deprecated)",
|
||||
"QS Server",
|
||||
"Quests",
|
||||
"Rules",
|
||||
"Skills",
|
||||
"Spawns",
|
||||
"Spells",
|
||||
"Status (Deprecated)",
|
||||
"Status",
|
||||
"TCP Connection",
|
||||
"Tasks",
|
||||
"Tradeskills",
|
||||
"Trading",
|
||||
"Tribute",
|
||||
"UCS Server (Deprecated)",
|
||||
"Web Interface (Deprecated)",
|
||||
"World Server (Deprecated)",
|
||||
"Zone Server (Deprecated)",
|
||||
"QueryErr",
|
||||
"Query",
|
||||
"UCS Server",
|
||||
"WebInterface Server",
|
||||
"World Server",
|
||||
"Zone Server",
|
||||
"MySQL Error",
|
||||
"MySQL Query",
|
||||
"Mercenaries",
|
||||
"Quest Debug",
|
||||
"Legacy Packet Logging (Deprecated)",
|
||||
"Legacy Packet Logging (Deprecated)",
|
||||
"Legacy Packet Logging (Deprecated)",
|
||||
"Legacy Packet Logging (Deprecated)",
|
||||
"Login Server (Deprecated)",
|
||||
"Deprecated",
|
||||
"Deprecated",
|
||||
"Deprecated",
|
||||
"Deprecated",
|
||||
"Login Server",
|
||||
"Client Login",
|
||||
"Headless Client (Deprecated)",
|
||||
"Headless Client",
|
||||
"HP Update",
|
||||
"FixZ",
|
||||
"Food",
|
||||
"Traps",
|
||||
"NPC Roam Box",
|
||||
"NPC Scaling",
|
||||
"MobAppearance",
|
||||
"Mob Appearance",
|
||||
"Info",
|
||||
"Warning",
|
||||
"Critical (Deprecated)",
|
||||
"Emergency (Deprecated)",
|
||||
"Alert (Deprecated)",
|
||||
"Notice (Deprecated)",
|
||||
"AI Scan",
|
||||
"AI Yell",
|
||||
"AI CastBeneficial",
|
||||
"Critical",
|
||||
"Emergency",
|
||||
"Alert",
|
||||
"Notice",
|
||||
"AI Scan Close",
|
||||
"AI Yell For Help",
|
||||
"AI Cast Beneficial Close",
|
||||
"AOE Cast",
|
||||
"Entity Management",
|
||||
"Flee",
|
||||
@@ -226,21 +220,14 @@ namespace Logs {
|
||||
"DialogueWindow",
|
||||
"HTTP",
|
||||
"Saylink",
|
||||
"ChecksumVer",
|
||||
"ChecksumVerification",
|
||||
"CombatRecord",
|
||||
"Hate",
|
||||
"Discord",
|
||||
"Faction",
|
||||
"Packet S->C",
|
||||
"Packet C->S",
|
||||
"Packet S->S",
|
||||
"Bugs",
|
||||
"QuestErrors",
|
||||
"PlayerEvents",
|
||||
"DataBuckets",
|
||||
"Zoning",
|
||||
"EqTime",
|
||||
"Corpses",
|
||||
"Packet-S->C",
|
||||
"Packet-C->S",
|
||||
"Packet-S->S"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -332,9 +319,6 @@ public:
|
||||
*/
|
||||
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;
|
||||
@@ -357,7 +341,7 @@ public:
|
||||
// gmsay
|
||||
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;
|
||||
return this;
|
||||
@@ -385,30 +369,25 @@ public:
|
||||
[[nodiscard]] const std::string &GetLogPath() const;
|
||||
EQEmuLogSys * SetLogPath(const std::string &log_path);
|
||||
|
||||
void DisableMySQLErrorLogs();
|
||||
void EnableMySQLErrorLogs();
|
||||
|
||||
private:
|
||||
|
||||
// reference to database
|
||||
Database *m_database;
|
||||
std::function<void(uint16 log_category, const char *func, const std::string &)> m_on_log_gmsay_hook;
|
||||
std::function<void(uint16 log_category, int webhook_id, const std::string &)> m_on_log_discord_hook;
|
||||
std::function<void(uint16 log_category, const std::string &)> m_on_log_console_hook;
|
||||
DiscordWebhooks m_discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{};
|
||||
bool m_file_logs_enabled = false;
|
||||
int m_log_platform = 0;
|
||||
std::string m_platform_file_name;
|
||||
std::string m_log_path;
|
||||
Database *m_database;
|
||||
std::function<void(uint16 log_category, const std::string &)> m_on_log_gmsay_hook;
|
||||
std::function<void(uint16 log_category, int webhook_id, const std::string &)> m_on_log_discord_hook;
|
||||
std::function<void(uint16 log_category, const std::string &)> m_on_log_console_hook;
|
||||
DiscordWebhooks m_discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{};
|
||||
bool m_file_logs_enabled = false;
|
||||
int m_log_platform = 0;
|
||||
std::string m_platform_file_name;
|
||||
std::string m_log_path;
|
||||
|
||||
void ProcessConsoleMessage(
|
||||
uint16 log_category,
|
||||
const std::string &message,
|
||||
const char *file,
|
||||
const char *func,
|
||||
int line
|
||||
);
|
||||
std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
|
||||
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
|
||||
|
||||
void ProcessConsoleMessage(uint16 log_category, const std::string &message);
|
||||
void ProcessLogWrite(uint16 log_category, const std::string &message);
|
||||
bool IsRfc5424LogCategory(uint16 log_category);
|
||||
void InjectTablesIfNotExist();
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
|
||||
#define EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
|
||||
|
||||
#ifdef BUILD_LOGGING
|
||||
|
||||
#define LogAA(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::AA))\
|
||||
OutF(LogSys, Logs::General, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
@@ -36,6 +38,11 @@
|
||||
OutF(LogSys, Logs::General, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogAIModerate(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::AI))\
|
||||
OutF(LogSys, Logs::Moderate, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogAIDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::AI))\
|
||||
OutF(LogSys, Logs::Detail, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
@@ -201,6 +208,16 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogQSServer(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::QSServer))\
|
||||
OutF(LogSys, Logs::General, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogQSServerDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::QSServer))\
|
||||
OutF(LogSys, Logs::Detail, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogQuests(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::Quests))\
|
||||
OutF(LogSys, Logs::General, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
@@ -311,6 +328,46 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogUCSServer(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::UCSServer))\
|
||||
OutF(LogSys, Logs::General, Logs::UCSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogUCSServerDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::UCSServer))\
|
||||
OutF(LogSys, Logs::Detail, Logs::UCSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogWebInterfaceServer(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::WebInterfaceServer))\
|
||||
OutF(LogSys, Logs::General, Logs::WebInterfaceServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogWebInterfaceServerDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::WebInterfaceServer))\
|
||||
OutF(LogSys, Logs::Detail, Logs::WebInterfaceServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogWorldServer(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::WorldServer))\
|
||||
OutF(LogSys, Logs::General, Logs::WorldServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogWorldServerDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::WorldServer))\
|
||||
OutF(LogSys, Logs::Detail, Logs::WorldServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogZoneServer(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::ZoneServer))\
|
||||
OutF(LogSys, Logs::General, Logs::ZoneServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogZoneServerDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::ZoneServer))\
|
||||
OutF(LogSys, Logs::Detail, Logs::ZoneServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogMySQLError(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::MySQLError))\
|
||||
OutF(LogSys, Logs::General, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
@@ -382,6 +439,16 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogHeadlessClient(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::HeadlessClient))\
|
||||
OutF(LogSys, Logs::General, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogHeadlessClientDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::HeadlessClient))\
|
||||
OutF(LogSys, Logs::Detail, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogHPUpdate(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::HPUpdate))\
|
||||
OutF(LogSys, Logs::General, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
@@ -764,74 +831,9 @@
|
||||
|
||||
// manually created
|
||||
|
||||
#define LogBugs(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::Bugs))\
|
||||
OutF(LogSys, Logs::General, Logs::Bugs, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBugsDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Bugs))\
|
||||
OutF(LogSys, Logs::Detail, Logs::Bugs, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogQuestErrors(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::QuestErrors))\
|
||||
OutF(LogSys, Logs::General, Logs::QuestErrors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogQuestErrorsDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::QuestErrors))\
|
||||
OutF(LogSys, Logs::Detail, Logs::QuestErrors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogPlayerEvents(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::PlayerEvents))\
|
||||
OutF(LogSys, Logs::General, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogPlayerEventsDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::PlayerEvents))\
|
||||
OutF(LogSys, Logs::Detail, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogDataBuckets(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::DataBuckets))\
|
||||
OutF(LogSys, Logs::General, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogDataBucketsDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::DataBuckets))\
|
||||
OutF(LogSys, Logs::Detail, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogZoning(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::Zoning))\
|
||||
OutF(LogSys, Logs::General, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogZoningDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Zoning))\
|
||||
OutF(LogSys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogEqTime(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::EqTime))\
|
||||
OutF(LogSys, Logs::General, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogEqTimeDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::EqTime))\
|
||||
OutF(LogSys, Logs::Detail, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogCorpses(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::Corpses))\
|
||||
OutF(LogSys, Logs::General, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogCorpsesDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Corpses))\
|
||||
OutF(LogSys, Logs::Detail, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
#define LogExpeditionsModerate(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Moderate, Logs::Expeditions))\
|
||||
OutF(LogSys, Logs::Moderate, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define Log(debug_level, log_category, message, ...) do {\
|
||||
@@ -844,5 +846,451 @@
|
||||
OutF(LogSys, debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define LogEmergency(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAlert(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCritical(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogError(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogWarning(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNotice(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogInfo(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogDebug(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Category
|
||||
*/
|
||||
|
||||
#define LogAA(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAADetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAI(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAggro(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAggroDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAttack(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAttackDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogPacketClientServer(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogPacketClientServerDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCombat(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCombatDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCommands(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCommandsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCrash(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCrashDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogDoors(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogDoorsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogGroup(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogGroupDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogGuilds(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogGuildsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogInventory(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogInventoryDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogLauncher(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogLauncherDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNetcode(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNetcodeDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNormal(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNormalDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogObject(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogObjectDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogPathing(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogPathingDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogQSServer(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogQSServerDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogQuests(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogQuestsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogRules(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogRulesDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSkills(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSkillsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSpawns(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSpawnsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSpells(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSpellsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTCPConnection(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTCPConnectionDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTasks(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTasksDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTradeskills(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTradeskillsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTrading(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTradingDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTribute(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTributeDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMySQLError(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMySQLErrorDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMySQLQuery(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMySQLQueryDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMercenaries(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMercenariesDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogQuestDebug(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogQuestDebugDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogLoginserver(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogLoginserverDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogClientLogin(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogClientLoginDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHeadlessClient(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHeadlessClientDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHPUpdate(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHPUpdateDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFixZ(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFixZDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFood(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFoodDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTraps(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogTrapsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNPCRoamBox(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNPCRoamBoxDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNPCScaling(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogNPCScalingDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMobAppearance(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMobAppearanceDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogStatus(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogStatusDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIScanClose(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIScanCloseDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIYellForHelp(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIYellForHelpDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAICastBeneficialClose(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAICastBeneficialCloseDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAoeCast(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAoeCastDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogEntityManagement(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogEntityManagementDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFlee(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFleeDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAura(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAuraDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHotReload(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHotReloadDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMerchants(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogMerchantsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogZonePoints(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogZonePointsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogExpeditions(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogExpeditionsModerate(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogExpeditionsDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogDynamicZones(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogDynamicZonesDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCheatList(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCheatDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogClientList(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogClientListDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogDiaWind(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogDiaWindDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHTTP(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHTTPDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSaylink(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSaylinkDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogScheduler(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogSchedulerDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCheat(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCheatDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogLoot(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogLootDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFood(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFoodDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogChecksumVerification(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogChecksumVerificationDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCombatRecord(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogCombatRecordDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHate(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHateDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFaction(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFactionDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define Log(debug_level, log_category, message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogF(debug_level, log_category, message, ...) do {\
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif //EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
|
||||
|
||||
+12
-52
@@ -46,16 +46,20 @@ EQTime::EQTime()
|
||||
timezone = 0;
|
||||
memset(&eqTime, 0, sizeof(eqTime));
|
||||
//Defaults for time
|
||||
TimeOfDay_Struct t{};
|
||||
t.day = 1;
|
||||
t.hour = 9;
|
||||
t.minute = 0;
|
||||
t.month = 1;
|
||||
t.year = 3100;
|
||||
TimeOfDay_Struct start;
|
||||
start.day = 1;
|
||||
start.hour = 9;
|
||||
start.minute = 0;
|
||||
start.month = 1;
|
||||
start.year = 3100;
|
||||
//Set default time zone
|
||||
timezone = 0;
|
||||
//Start EQTimer
|
||||
SetCurrentEQTimeOfDay(t, time(nullptr));
|
||||
SetCurrentEQTimeOfDay(start, time(0));
|
||||
}
|
||||
|
||||
EQTime::~EQTime()
|
||||
{
|
||||
}
|
||||
|
||||
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
|
||||
@@ -199,48 +203,4 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
|
||||
t->month, t->day, t->year, t->hour, t->minute);
|
||||
buf[127] = '\0';
|
||||
str = buf;
|
||||
}
|
||||
|
||||
bool EQTime::IsDayTime() {
|
||||
TimeOfDay_Struct tod{}; //Day time is 5am to 6:59pm (14 hours in-game)
|
||||
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
|
||||
|
||||
if (tod.hour >= 5 || tod.hour < 19) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQTime::IsNightTime() {
|
||||
TimeOfDay_Struct tod{}; //Night time is 7pm to 4:59am (10 hours in-game)
|
||||
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
|
||||
|
||||
if (tod.hour >= 19 || tod.hour < 5) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQTime::IsInbetweenTime(uint8 min_time, uint8 max_time) {
|
||||
TimeOfDay_Struct tod{};
|
||||
GetCurrentEQTimeOfDay(&tod);
|
||||
|
||||
if (min_time == 0 || max_time == 0 || min_time > 24 || max_time > 24) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (max_time < min_time) {
|
||||
if ((tod.hour >= min_time && tod.hour > max_time) || (tod.hour < min_time && tod.hour <= max_time)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tod.hour >= min_time && tod.hour <= max_time) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -18,7 +18,7 @@ public:
|
||||
//Constructor/destructor
|
||||
EQTime(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
EQTime();
|
||||
~EQTime() = default;
|
||||
~EQTime();
|
||||
|
||||
//Get functions
|
||||
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||
@@ -28,9 +28,6 @@ public:
|
||||
uint32 getEQTimeZone() { return timezone; }
|
||||
uint32 getEQTimeZoneHr() { return timezone/60; }
|
||||
uint32 getEQTimeZoneMin() { return timezone%60; }
|
||||
bool IsDayTime();
|
||||
bool IsNightTime();
|
||||
bool IsInbetweenTime(uint8 min_time, uint8 max_time);
|
||||
|
||||
//Set functions
|
||||
int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA */
|
||||
|
||||
/* Error messages for mysql clients */
|
||||
/* error messages for the demon is in share/language/errmsg.sys */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void init_client_errs(void);
|
||||
extern const char *client_errors[]; /* Error messages */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CR_MIN_ERROR 2000 /* For easier client code */
|
||||
#define CR_MAX_ERROR 2999
|
||||
#if defined(OS2) && defined( MYSQL_SERVER)
|
||||
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#else
|
||||
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#endif
|
||||
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
|
||||
|
||||
#define CR_UNKNOWN_ERROR 2000
|
||||
#define CR_SOCKET_CREATE_ERROR 2001
|
||||
#define CR_CONNECTION_ERROR 2002
|
||||
#define CR_CONN_HOST_ERROR 2003
|
||||
#define CR_IPSOCK_ERROR 2004
|
||||
#define CR_UNKNOWN_HOST 2005
|
||||
#define CR_SERVER_GONE_ERROR 2006
|
||||
#define CR_VERSION_ERROR 2007
|
||||
#define CR_OUT_OF_MEMORY 2008
|
||||
#define CR_WRONG_HOST_INFO 2009
|
||||
#define CR_LOCALHOST_CONNECTION 2010
|
||||
#define CR_TCP_CONNECTION 2011
|
||||
#define CR_SERVER_HANDSHAKE_ERR 2012
|
||||
#define CR_SERVER_LOST 2013
|
||||
#define CR_COMMANDS_OUT_OF_SYNC 2014
|
||||
#define CR_NAMEDPIPE_CONNECTION 2015
|
||||
#define CR_NAMEDPIPEWAIT_ERROR 2016
|
||||
#define CR_NAMEDPIPEOPEN_ERROR 2017
|
||||
#define CR_NAMEDPIPESETSTATE_ERROR 2018
|
||||
#define CR_CANT_READ_CHARSET 2019
|
||||
#define CR_NET_PACKET_TOO_LARGE 2020
|
||||
@@ -38,7 +38,7 @@ namespace EQ
|
||||
_running = true;
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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,706 +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);
|
||||
}
|
||||
|
||||
std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> settings_to_insert{};
|
||||
|
||||
// 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;
|
||||
settings_to_insert.emplace_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings_to_insert.empty()) {
|
||||
PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
LogPlayerEvents("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;
|
||||
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_PLAT].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
|
||||
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
|
||||
// TODO: add more values
|
||||
switch (r1) {
|
||||
case DARK_ELF:
|
||||
if (r2 == Race::NeriakCitizen) {
|
||||
if (r2 == 77) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case BARBARIAN:
|
||||
if (r2 == Race::HalasCitizen) {
|
||||
if (r2 == 90) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+27
-8
@@ -24,15 +24,17 @@
|
||||
#include <string>
|
||||
|
||||
enum FACTION_VALUE {
|
||||
FACTION_ALLY = 1,
|
||||
FACTION_WARMLY = 2,
|
||||
FACTION_KINDLY = 3,
|
||||
FACTION_AMIABLY = 4,
|
||||
FACTION_INDIFFERENTLY = 5,
|
||||
FACTION_ALLY = 1,
|
||||
FACTION_WARMLY = 2,
|
||||
FACTION_KINDLY = 3,
|
||||
FACTION_AMIABLY = 4,
|
||||
|
||||
FACTION_INDIFFERENTLY = 5,
|
||||
|
||||
FACTION_APPREHENSIVELY = 6,
|
||||
FACTION_DUBIOUSLY = 7,
|
||||
FACTION_THREATENINGLY = 8,
|
||||
FACTION_SCOWLS = 9
|
||||
FACTION_DUBIOUSLY = 7,
|
||||
FACTION_THREATENINGLY = 8,
|
||||
FACTION_SCOWLS = 9
|
||||
};
|
||||
|
||||
struct NPCFactionList {
|
||||
@@ -73,6 +75,23 @@ struct NPCFaction
|
||||
uint8 temp;
|
||||
};
|
||||
|
||||
// Faction Associations give a much more live like faction system
|
||||
// Basically the primary faction and magnitude of a faction hit will generate the rest of them
|
||||
|
||||
// Largest faction I could find quickly was Lord Inquisitor Seru with 9 total hits (8 associations) so 8 + 2 for max for now
|
||||
#define MAX_FACTION_ASSOC 10
|
||||
|
||||
// this is the ID of a faction association and it's multiplier
|
||||
struct FactionAssociationHit {
|
||||
int id;
|
||||
float multiplier;
|
||||
};
|
||||
|
||||
struct FactionAssociations {
|
||||
// maybe there should be more data here, fine for now
|
||||
FactionAssociationHit hits[MAX_FACTION_ASSOC];
|
||||
};
|
||||
|
||||
const char *FactionValueToString(FACTION_VALUE faction_value);
|
||||
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
|
||||
#endif
|
||||
|
||||
+44
-4
@@ -35,6 +35,11 @@ Core Zone features
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//Uncomment this to cause a zone to basically idle
|
||||
//when there are no players in it, mobs stop wandering, etc..
|
||||
#define IDLE_WHEN_EMPTY
|
||||
|
||||
#ifdef EMBPERL
|
||||
//Enable the new XS based perl parser
|
||||
#define EMBPERL_XS
|
||||
@@ -127,7 +132,7 @@ enum { //reuse times
|
||||
InstillDoubtReuseTime = 9,
|
||||
FishingReuseTime = 11,
|
||||
ForagingReuseTime = 50,
|
||||
MendReuseTime = 360,
|
||||
MendReuseTime = 290,
|
||||
BashReuseTime = 5,
|
||||
BackstabReuseTime = 9,
|
||||
KickReuseTime = 5,
|
||||
@@ -213,14 +218,14 @@ enum { //some random constants
|
||||
#define HARD_LEVEL_CAP 127
|
||||
|
||||
//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
|
||||
#define NPC_RAMPAGE_RANGE2 5625.0f
|
||||
|
||||
//the formula for experience for killing a mob.
|
||||
//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
|
||||
|
||||
@@ -233,6 +238,41 @@ enum { //some random constants
|
||||
// Timer to update aggrometer
|
||||
#define AGGRO_METER_UPDATE_MS 1000
|
||||
|
||||
//Some hard coded statuses from commands and other places:
|
||||
enum {
|
||||
minStatusToBeGM = 40,
|
||||
minStatusToUseGMCommands = 80,
|
||||
minStatusToKick = 150,
|
||||
minStatusToAvoidFalling = 100,
|
||||
minStatusToHaveInvalidSpells = 80,
|
||||
minStatusToHaveInvalidSkills = 80,
|
||||
minStatusToIgnoreZoneFlags = 80,
|
||||
minStatusToSeeOthersZoneFlags = 80,
|
||||
minStatusToEditOtherGuilds = 80,
|
||||
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
||||
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
||||
commandZoneToSpecials = 80, //zone to cshome, out of load zones
|
||||
commandToggleAI = 250, //can turn NPC AI on and off
|
||||
commandCastSpecials = 100, //can cast special spells
|
||||
commandInstacast = 100, //insta-cast all #casted spells
|
||||
commandLevelAboveCap = 100, //can #level players above level cap
|
||||
commandLevelNPCAboveCap = 100, //can #level NPCs above level cap
|
||||
commandSetSkillsOther = 100, //ability to setskills on others
|
||||
commandRaceOthers = 100, //ability to #race on others
|
||||
commandGenderOthers = 100, //ability to #gender on others
|
||||
commandTextureOthers = 100, //ability to #texture on others
|
||||
commandDoAnimOthers = 100, //can #doanim on others
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
|
||||
#define SAYLINK_ITEM_ID 0xFFFFF
|
||||
|
||||
@@ -255,7 +295,7 @@ Developer configuration
|
||||
|
||||
#define COMMON_PROFILE
|
||||
|
||||
#define PROFILE_DUMP_TIME 180
|
||||
#define PROFILE_DUMP_TIME 3*60
|
||||
#endif //EQPROFILE
|
||||
|
||||
|
||||
|
||||
+10
-40
@@ -37,32 +37,25 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
bool File::Exists(const std::string &name)
|
||||
{
|
||||
struct stat sb{};
|
||||
if (stat(name.c_str(), &sb) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
fs::create_directory(directory_name);
|
||||
fs::permissions(directory_name, fs::perms::owner_all);
|
||||
}
|
||||
|
||||
std::string File::FindEqemuConfigPath()
|
||||
@@ -87,26 +80,3 @@ 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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,16 +25,10 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
struct FileContentsResult {
|
||||
std::string contents;
|
||||
std::string error;
|
||||
};
|
||||
|
||||
class File {
|
||||
public:
|
||||
static bool Exists(const std::string &name);
|
||||
static void Makedir(const std::string& directory_name);
|
||||
static FileContentsResult GetContents(const std::string &file_name);
|
||||
static std::string FindEqemuConfigPath();
|
||||
static std::string GetCwd();
|
||||
};
|
||||
|
||||
+826
-1016
File diff suppressed because it is too large
Load Diff
+82
-136
@@ -5,42 +5,6 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "timer.h"
|
||||
#include "../common/repositories/guild_members_repository.h"
|
||||
#include "../common/repositories/guilds_repository.h"
|
||||
|
||||
struct DefaultPermissionStruct {
|
||||
GuildAction id;
|
||||
uint32 value;
|
||||
};
|
||||
|
||||
struct DefaultRankNamesStruct {
|
||||
uint32 id;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct GuildTributeStruct {
|
||||
Timer timer;
|
||||
uint32 id_1;
|
||||
uint32 id_2;
|
||||
uint32 id_1_tier;
|
||||
uint32 id_2_tier;
|
||||
uint32 favor;
|
||||
uint32 time_remaining;
|
||||
uint32 enabled;
|
||||
bool send_timer;
|
||||
};
|
||||
|
||||
class TributeData {
|
||||
public:
|
||||
//this level data stored in regular byte order and must be flipped before sending
|
||||
TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS];
|
||||
uint8 tier_count;
|
||||
uint32 unknown;
|
||||
std::string name;
|
||||
std::string description;
|
||||
bool is_guild; //is a guild tribute item
|
||||
};
|
||||
|
||||
class Database;
|
||||
|
||||
@@ -48,23 +12,22 @@ class CharGuildInfo
|
||||
{
|
||||
public:
|
||||
//fields from `characer_`
|
||||
uint32 char_id;
|
||||
uint32 char_id;
|
||||
std::string char_name;
|
||||
uint8 class_;
|
||||
uint16 level;
|
||||
uint32 time_last_on;
|
||||
uint32 zone_id;
|
||||
uint8 class_;
|
||||
uint16 level;
|
||||
uint32 time_last_on;
|
||||
uint32 zone_id;
|
||||
|
||||
//fields from `guild_members`
|
||||
uint32 guild_id;
|
||||
uint8 rank;
|
||||
bool tribute_enable;
|
||||
uint32 total_tribute;
|
||||
uint32 last_tribute; //timestamp
|
||||
bool banker;
|
||||
bool alt;
|
||||
uint32 guild_id;
|
||||
uint8 rank;
|
||||
bool tribute_enable;
|
||||
uint32 total_tribute;
|
||||
uint32 last_tribute; //timestamp
|
||||
bool banker;
|
||||
bool alt;
|
||||
std::string public_note;
|
||||
bool online;
|
||||
};
|
||||
|
||||
//this object holds guild functionality shared between world and zone.
|
||||
@@ -75,31 +38,21 @@ class BaseGuildManager
|
||||
virtual ~BaseGuildManager();
|
||||
|
||||
//this must be called before doing anything else with this object
|
||||
BaseGuildManager * SetDatabase(Database *db)
|
||||
void SetDatabase(Database *db)
|
||||
{
|
||||
m_db = db;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
BaseGuildManager * SetContentDatabase(Database *db)
|
||||
{
|
||||
m_content_db = db;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
bool LoadGuilds();
|
||||
virtual bool RefreshGuild(uint32 guild_id);
|
||||
bool RefreshGuild(uint32 guild_id);
|
||||
|
||||
//guild edit actions.
|
||||
uint32 CreateGuild(std::string name, uint32 leader_char_id);
|
||||
bool StoreGuildDB(uint32 guild_id);
|
||||
uint32 CreateGuild(const char* name, uint32 leader_char_id);
|
||||
bool DeleteGuild(uint32 guild_id);
|
||||
bool RenameGuild(uint32 guild_id, std::string name);
|
||||
bool SetGuildMOTD(uint32 guild_id, std::string motd, std::string setter);
|
||||
bool SetGuildURL(uint32 guild_id, std::string URL);
|
||||
bool SetGuildChannel(uint32 guild_id, std::string Channel);
|
||||
bool RenameGuild(uint32 guild_id, const char* name);
|
||||
bool SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter);
|
||||
bool SetGuildURL(uint32 GuildID, const char* URL);
|
||||
bool SetGuildChannel(uint32 GuildID, const char* Channel);
|
||||
|
||||
//character edit actions
|
||||
bool SetGuildLeader(uint32 guild_id, uint32 leader_char_id);
|
||||
@@ -109,16 +62,9 @@ class BaseGuildManager
|
||||
bool ForceRankUpdate(uint32 charid);
|
||||
bool GetAltFlag(uint32 CharID);
|
||||
bool SetAltFlag(uint32 charid, bool is_alt);
|
||||
bool GetBankerFlag(uint32 CharID, bool compat_mode = false);
|
||||
bool GetGuildBankerStatus(uint32 guild_id, uint32 guild_rank);
|
||||
bool GetBankerFlag(uint32 CharID);
|
||||
bool SetTributeFlag(uint32 charid, bool enabled);
|
||||
bool SetPublicNote(uint32 charid, std::string public_note);
|
||||
uint32 UpdateDbGuildFavor(uint32 guild_id, uint32 enabled);
|
||||
bool UpdateDbGuildTributeEnabled(uint32 guild_id, uint32 enabled);
|
||||
bool UpdateDbMemberTributeEnabled(uint32 guild_id, uint32 char_id, uint32 enabled);
|
||||
bool UpdateDbTributeTimeRemaining(uint32 guild_id, uint32 enabled);
|
||||
uint32 UpdateDbMemberFavor(uint32 guild_id, uint32 char_id, uint32 favor);
|
||||
bool UpdateDbMemberOnline(uint32 char_id, bool status);
|
||||
bool SetPublicNote(uint32 charid, const char *note);
|
||||
|
||||
//queries
|
||||
bool GetCharInfo(const char *char_name, CharGuildInfo &into);
|
||||
@@ -128,24 +74,29 @@ class BaseGuildManager
|
||||
bool GetGuildMOTD(uint32 guild_id, char *motd_buffer, char *setter_buffer) const;
|
||||
bool GetGuildURL(uint32 GuildID, char *URLBuffer) const;
|
||||
bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const;
|
||||
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
|
||||
bool GetGuildNameByID(uint32 guild_id, std::string& into) const;
|
||||
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
|
||||
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
|
||||
bool CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const;
|
||||
bool UpdateDbBankerFlag(uint32 charid, bool is_banker);
|
||||
uint8* MakeGuildList(const char* head_name, uint32& length) const; //make a guild list packet, returns ownership of the buffer.
|
||||
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
|
||||
uint32 GetGuildIDByName(const char *GuildName);
|
||||
uint32 GetGuildIDByCharacterID(uint32 character_id);
|
||||
uint32 FindGuildByLeader(uint32 leader) const;
|
||||
uint32 NumberInGuild(uint32 guild_id);
|
||||
uint32 DoesAccountContainAGuildLeader(uint32 AccountID);
|
||||
const char* GetRankName(uint32 guild_id, uint8 rank) const;
|
||||
const char* GetGuildName(uint32 guild_id) const;
|
||||
std::string GetGuildNameByID(uint32 guild_id) const;
|
||||
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
|
||||
std::vector<GuildMembersRepository::GuildMembers> GetGuildMembers(uint32 guild_id);
|
||||
const char *GetRankName(uint32 guild_id, uint8 rank) const;
|
||||
const char *GetGuildName(uint32 guild_id) const;
|
||||
std::string GetGuildNameByID(uint32 guild_id) const;
|
||||
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
|
||||
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
|
||||
bool GetGuildNameByID(uint32 guild_id, std::string &into) const;
|
||||
uint32 GetGuildIDByName(const char *GuildName);
|
||||
uint32 GetGuildIDByCharacterID(uint32 character_id);
|
||||
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
|
||||
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
|
||||
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
|
||||
bool CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const;
|
||||
// uint32 Getguild_id(uint32 eqid);
|
||||
uint32 FindGuildByLeader(uint32 leader) const;
|
||||
// void GetGuildMembers(uint32 guild_id,GuildMember_Struct* gms);
|
||||
uint32 NumberInGuild(uint32 guild_id);
|
||||
// bool GetGuildRanks(uint32 guildeqid, GuildRanks_Struct* gr);
|
||||
// bool EditGuild(uint32 guild_id, uint8 ranknum, GuildRankLevel_Struct* grl);
|
||||
|
||||
uint8 *MakeGuildList(const char *head_name, uint32 &length) const; //make a guild list packet, returns ownership of the buffer.
|
||||
|
||||
static const char *const GuildActionNames[_MaxGuildAction];
|
||||
uint32 DoesAccountContainAGuildLeader(uint32 AccountID);
|
||||
|
||||
protected:
|
||||
//the methods which must be defined by base classes.
|
||||
@@ -154,63 +105,58 @@ class BaseGuildManager
|
||||
virtual void SendRankUpdate(uint32 CharID) = 0;
|
||||
virtual void SendGuildDelete(uint32 guild_id) = 0;
|
||||
|
||||
uint32 UpdateDbCreateGuild(std::string name, uint32 leader_char_id);
|
||||
bool UpdateDbDeleteGuild(uint32 guild_id, bool local_delete = true, bool db_delete = true);
|
||||
bool UpdateDbRenameGuild(uint32 guild_id, std::string name);
|
||||
bool UpdateDbGuildLeader(uint32 guild_id, uint32 leader_char_id);
|
||||
bool UpdateDbGuildMOTD(uint32 guild_id, std::string motd, std::string setter);
|
||||
bool UpdateDbGuildURL(uint32 GuildID, std::string URL);
|
||||
bool UpdateDbGuildChannel(uint32 GuildID, std::string Channel);
|
||||
bool UpdateDbGuild(uint32 charid, uint32 guild_id, uint8 rank);
|
||||
bool UpdateDbGuildRank(uint32 charid, uint8 rank);
|
||||
bool UpdateDbAltFlag(uint32 charid, bool is_alt);
|
||||
bool UpdateDbTributeFlag(uint32 charid, bool enabled);
|
||||
bool UpdateDbPublicNote(uint32 charid, std::string public_note);
|
||||
uint32 DBCreateGuild(const char* name, uint32 leader_char_id);
|
||||
bool DBDeleteGuild(uint32 guild_id);
|
||||
bool DBRenameGuild(uint32 guild_id, const char* name);
|
||||
bool DBSetGuildLeader(uint32 guild_id, uint32 leader_char_id);
|
||||
bool DBSetGuildMOTD(uint32 guild_id, const char* motd, const char *setter);
|
||||
bool DBSetGuildURL(uint32 GuildID, const char* URL);
|
||||
bool DBSetGuildChannel(uint32 GuildID, const char* Channel);
|
||||
bool DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank);
|
||||
bool DBSetGuildRank(uint32 charid, uint8 rank);
|
||||
bool DBSetBankerFlag(uint32 charid, bool is_banker);
|
||||
bool DBSetAltFlag(uint32 charid, bool is_alt);
|
||||
bool DBSetTributeFlag(uint32 charid, bool enabled);
|
||||
bool DBSetPublicNote(uint32 charid, const char *note);
|
||||
bool QueryWithLogging(std::string query, const char *errmsg);
|
||||
// void DBSetPublicNote(uint32 guild_id,char* charname, char* note);
|
||||
|
||||
bool LocalDeleteGuild(uint32 guild_id);
|
||||
|
||||
struct RankInfo
|
||||
class RankInfo
|
||||
{
|
||||
RankInfo();
|
||||
std::string rank_name;
|
||||
public:
|
||||
RankInfo();
|
||||
std::string name;
|
||||
bool permissions[_MaxGuildAction];
|
||||
};
|
||||
struct Functions
|
||||
class GuildInfo
|
||||
{
|
||||
uint32 id;
|
||||
uint32 perm_id;
|
||||
uint32 guild_id;
|
||||
uint32 perm_value;
|
||||
};
|
||||
public:
|
||||
class GuildInfo {
|
||||
public:
|
||||
GuildInfo();
|
||||
std::string name;
|
||||
std::string motd;
|
||||
std::string motd_setter;
|
||||
std::string url;
|
||||
std::string channel;
|
||||
uint32 leader;
|
||||
uint8 minstatus;
|
||||
std::string rank_names[GUILD_MAX_RANK + 1];
|
||||
Functions functions[GUILD_MAX_FUNCTIONS + 1];
|
||||
GuildTributeStruct tribute;
|
||||
};
|
||||
virtual BaseGuildManager::GuildInfo* GetGuildByGuildID(uint32 guild_id);
|
||||
uint32 GetGuildTributeTimeRemaining(uint32 guild_id);
|
||||
public:
|
||||
GuildInfo();
|
||||
std::string name;
|
||||
std::string motd;
|
||||
std::string motd_setter;
|
||||
std::string url;
|
||||
std::string channel;
|
||||
|
||||
uint32 leader_char_id;
|
||||
uint8 minstatus;
|
||||
//tribute is not in here on purpose, since it is only valid in world!
|
||||
RankInfo ranks[GUILD_MAX_RANK + 1];
|
||||
};
|
||||
|
||||
protected:
|
||||
std::map<uint32, GuildInfo *> m_guilds; //we own the pointers in this map
|
||||
void ClearGuilds(); //clears internal structure
|
||||
|
||||
Database *m_db;
|
||||
Database *m_content_db;
|
||||
Database *m_db; //we do not own this
|
||||
|
||||
bool _StoreGuildDB(uint32 guild_id);
|
||||
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
|
||||
GuildInfo *_CreateGuild(uint32 guild_id, const char *guild_name, uint32 account_id, uint8 minstatus, const char *guild_motd, const char *motd_setter, const char *Channel, const char *URL);
|
||||
uint32 _GetFreeGuildID();
|
||||
GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in);
|
||||
};
|
||||
|
||||
|
||||
#endif /*GUILD_BASE_H_*/
|
||||
|
||||
|
||||
|
||||
+16
-56
@@ -16,71 +16,31 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef GUILDS_H
|
||||
#define GUILDS_H
|
||||
#ifndef GUILD_H
|
||||
#define GUILD_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define GUILD_NONE 0xFFFFFFFF // user has no guild
|
||||
|
||||
#define GUILD_MAX_RANK 8 // 0-2 - some places in the code assume a single digit, dont go above 9
|
||||
#define GUILD_MAX_FUNCTIONS 30
|
||||
#define GUILD_TRIBUTES_MODIFY 1
|
||||
#define GUILD_TRIBUTES_SAVE 0
|
||||
#define GUILD_TRIBUTES_OFF 0
|
||||
#define GUILD_TRIBUTES_ON 1
|
||||
#define GUILD_INVITE_DECLINE 9
|
||||
#define GUILD_MAX_RANK 8 // 0-2 - some places in the code assume a single digit, dont go above 9
|
||||
|
||||
//defines for standard ranks
|
||||
#define GUILD_MEMBER_TI 0
|
||||
#define GUILD_OFFICER_TI 1
|
||||
#define GUILD_LEADER_TI 2
|
||||
#define GUILD_RANK_NONE_TI (GUILD_MAX_RANK + 1)
|
||||
|
||||
//defines for standard ranks base on RoF2 definitions
|
||||
#define GUILD_RANK_NONE 0
|
||||
#define GUILD_LEADER 1
|
||||
#define GUILD_SENIOR_OFFICER 2
|
||||
#define GUILD_OFFICER 3
|
||||
#define GUILD_SENIOR_MEMBER 4
|
||||
#define GUILD_MEMBER 5
|
||||
#define GUILD_JUNIOR_MEMBER 6
|
||||
#define GUILD_INITIATE 7
|
||||
#define GUILD_RECRUIT 8
|
||||
#define GUILD_MEMBER 0
|
||||
#define GUILD_OFFICER 1
|
||||
#define GUILD_LEADER 2
|
||||
#define GUILD_RANK_NONE (GUILD_MAX_RANK+1)
|
||||
|
||||
typedef enum {
|
||||
GUILD_ACTION_BANNER_CHANGE = 1,
|
||||
GUILD_ACTION_BANNER_PLANT = 2,
|
||||
GUILD_ACTION_BANNER_REMOVE = 3,
|
||||
GUILD_ACTION_DISPLAY_GUILD_NAME = 4,
|
||||
GUILD_ACTION_RANKS_CHANGE_PERMISSIONS = 5,
|
||||
GUILD_ACTION_RANKS_CHANGE_RANK_NAMES = 6,
|
||||
GUILD_ACTION_MEMBERS_INVITE = 7,
|
||||
GUILD_ACTION_MEMBERS_PROMOTE = 8,
|
||||
GUILD_ACTION_MEMBERS_DEMOTE = 9,
|
||||
GUILD_ACTION_MEMBERS_REMOVE = 10,
|
||||
GUILD_ACTION_EDIT_RECRUITING_SETTINGS = 11,
|
||||
GUILD_ACTION_EDIT_PUBLIC_NOTES = 12,
|
||||
GUILD_ACTION_BANK_DEPOSIT_ITEMS = 13,
|
||||
GUILD_ACTION_BANK_WITHDRAW_ITEMS = 14,
|
||||
GUILD_ACTION_BANK_VIEW_ITEMS = 15,
|
||||
GUILD_ACTION_BANK_PROMOTE_ITEMS = 16,
|
||||
GUILD_ACTION_BANK_CHANGE_ITEM_PERMISSIONS = 17,
|
||||
GUILD_ACTION_CHANGE_THE_MOTD = 18,
|
||||
GUILD_ACTION_GUILD_CHAT_SEE = 19,
|
||||
GUILD_ACTION_GUILD_CHAT_SPEAK_IN = 20,
|
||||
GUILD_ACTION_SEND_THE_WHOLE_GUILD_E_MAIL = 21,
|
||||
GUILD_ACTION_TRIBUTE_CHANGE_FOR_OTHERS = 22,
|
||||
GUILD_ACTION_TRIBUTE_CHANGE_ACTIVE_BENEFIT = 23,
|
||||
GUILD_ACTION_TROPHY_TRIBUTE_CHANGE_FOR_OTHERS = 24,
|
||||
GUILD_ACTION_TROPHY_TRIBUTE_CHANGE_ACTIVE_BENEFIT = 25,
|
||||
GUILD_ACTION_MEMBERS_CHANGE_ALT_FLAG_FOR_OTHER = 26,
|
||||
GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_BUY = 27,
|
||||
GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_SELL = 28,
|
||||
GUILD_ACTION_REAL_ESTATE_MODIFY_TROPHIES = 29,
|
||||
GUILD_ACTION_MEMBERS_DEMOTE_SELF = 30,
|
||||
GUILD_HEAR = 0,
|
||||
GUILD_SPEAK = 1,
|
||||
GUILD_INVITE = 2,
|
||||
GUILD_REMOVE = 3,
|
||||
GUILD_PROMOTE = 4,
|
||||
GUILD_DEMOTE = 5,
|
||||
GUILD_MOTD = 6,
|
||||
GUILD_WARPEACE = 7,
|
||||
_MaxGuildAction
|
||||
} GuildAction;
|
||||
|
||||
constexpr int format_as(GuildAction action) { return static_cast<int>(action); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -272,8 +272,6 @@ inline const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1) {
|
||||
#include <brotli/encode.h>
|
||||
#endif
|
||||
|
||||
#include "../strings.h"
|
||||
|
||||
/*
|
||||
* Declaration
|
||||
*/
|
||||
@@ -3814,12 +3812,12 @@ inline bool brotli_decompressor::decompress(const char *data,
|
||||
if (std::regex_match(b, e, cm, re_another_range)) {
|
||||
ssize_t first = -1;
|
||||
if (!cm.str(1).empty()) {
|
||||
first = static_cast<ssize_t>(Strings::ToBigInt(cm.str(1)));
|
||||
first = static_cast<ssize_t>(std::stoll(cm.str(1)));
|
||||
}
|
||||
|
||||
ssize_t last = -1;
|
||||
if (!cm.str(2).empty()) {
|
||||
last = static_cast<ssize_t>(Strings::ToBigInt(cm.str(2)));
|
||||
last = static_cast<ssize_t>(std::stoll(cm.str(2)));
|
||||
}
|
||||
|
||||
if (first != -1 && last != -1 && first > last) {
|
||||
@@ -6690,7 +6688,7 @@ static WSInit wsinit_;
|
||||
if (params.empty()) { return Get(path, headers); }
|
||||
|
||||
std::string path_with_query = append_query_params(path, params);
|
||||
return Get(path_with_query, headers, progress);
|
||||
return Get(path_with_query.c_str(), headers, progress);
|
||||
}
|
||||
|
||||
inline Result ClientImpl::Get(const std::string &path, const Params ¶ms,
|
||||
@@ -6710,7 +6708,7 @@ static WSInit wsinit_;
|
||||
}
|
||||
|
||||
std::string path_with_query = append_query_params(path, params);
|
||||
return Get(path_with_query, headers, response_handler,
|
||||
return Get(path_with_query.c_str(), headers, response_handler,
|
||||
content_receiver, progress);
|
||||
}
|
||||
|
||||
@@ -6807,7 +6805,7 @@ static WSInit wsinit_;
|
||||
std::string content_type;
|
||||
const auto &body = detail::serialize_multipart_formdata(
|
||||
items, detail::make_multipart_data_boundary(), content_type);
|
||||
return Post(path, headers, body, content_type);
|
||||
return Post(path, headers, body, content_type.c_str());
|
||||
}
|
||||
|
||||
inline Result ClientImpl::Post(const std::string &path, const Headers &headers,
|
||||
@@ -6820,7 +6818,7 @@ static WSInit wsinit_;
|
||||
std::string content_type;
|
||||
const auto &body =
|
||||
detail::serialize_multipart_formdata(items, boundary, content_type);
|
||||
return Post(path, headers, body, content_type);
|
||||
return Post(path, headers, body, content_type.c_str());
|
||||
}
|
||||
|
||||
inline Result ClientImpl::Put(const std::string &path) {
|
||||
|
||||
@@ -173,8 +173,7 @@ EQ::ItemInstance* EQ::InventoryProfile::GetItem(int16 slot_id) const
|
||||
result = _GetItem(m_inv, slot_id);
|
||||
}
|
||||
else if ((slot_id >= invslot::EQUIPMENT_BEGIN && slot_id <= invslot::EQUIPMENT_END) ||
|
||||
(slot_id >= invslot::TRIBUTE_BEGIN && slot_id <= invslot::TRIBUTE_END) ||
|
||||
(slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END)) {
|
||||
(slot_id >= invslot::TRIBUTE_BEGIN && slot_id <= invslot::TRIBUTE_END)) {
|
||||
// Equippable slots (on body)
|
||||
result = _GetItem(m_worn, slot_id);
|
||||
}
|
||||
@@ -354,7 +353,7 @@ bool EQ::InventoryProfile::SwapItem(
|
||||
fail_state = swapRaceClass;
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
@@ -380,7 +379,7 @@ bool EQ::InventoryProfile::SwapItem(
|
||||
fail_state = swapRaceClass;
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
@@ -413,12 +412,11 @@ bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
|
||||
// If there are no charges left on the item,
|
||||
if (item_to_delete->GetCharges() <= 0) {
|
||||
// If the item is stackable (e.g arrows), or
|
||||
// the item is not a charged item, or is expendable, delete it
|
||||
if (
|
||||
item_to_delete->IsStackable() ||
|
||||
item_to_delete->GetItem()->MaxCharges == 0 ||
|
||||
item_to_delete->IsExpendable()
|
||||
) {
|
||||
// the item is not stackable, and is not a charged item, or is expendable, delete it
|
||||
if (item_to_delete->IsStackable() ||
|
||||
(!item_to_delete->IsStackable() &&
|
||||
((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable()))
|
||||
) {
|
||||
// Item can now be destroyed
|
||||
InventoryProfile::MarkDirty(item_to_delete);
|
||||
return true;
|
||||
@@ -466,10 +464,6 @@ EQ::ItemInstance* EQ::InventoryProfile::PopItem(int16 slot_id)
|
||||
p = m_worn[slot_id];
|
||||
m_worn.erase(slot_id);
|
||||
}
|
||||
else if (slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END) {
|
||||
p = m_worn[slot_id];
|
||||
m_worn.erase(slot_id);
|
||||
}
|
||||
else if (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) {
|
||||
p = m_bank[slot_id];
|
||||
m_bank.erase(slot_id);
|
||||
@@ -806,35 +800,34 @@ int16 EQ::InventoryProfile::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
||||
// Returns slot_id when there's one available, else SLOT_INVALID
|
||||
int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
|
||||
{
|
||||
const int16 last_bag_slot = (RuleI(World, ExpansionSettings) == -1 || RuleI(World, ExpansionSettings) & EQ::expansions::bitHoT) ? EQ::invslot::slotGeneral10 : EQ::invslot::slotGeneral8;
|
||||
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { // Check basic inventory
|
||||
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
|
||||
// Check basic inventory
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
|
||||
if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!GetItem(i)) {
|
||||
return i; // Found available slot in personal inventory
|
||||
}
|
||||
if (!GetItem(i))
|
||||
// Found available slot in personal inventory
|
||||
return i;
|
||||
}
|
||||
|
||||
if (!for_bag) {
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) {
|
||||
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
|
||||
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
|
||||
if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto *inst = GetItem(i);
|
||||
if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) {
|
||||
if (inst->GetItem()->BagType == item::BagTypeQuiver &&
|
||||
inst->GetItem()->ItemType != item::ItemTypeArrow) {
|
||||
const ItemInstance* inst = GetItem(i);
|
||||
if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size)
|
||||
{
|
||||
if (inst->GetItem()->BagType == item::BagTypeQuiver && inst->GetItem()->ItemType != item::ItemTypeArrow)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN);
|
||||
int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN);
|
||||
|
||||
const uint8 slots = inst->GetItem()->BagSlots;
|
||||
for (uint8 j = invbag::SLOT_BEGIN; j < slots; j++) {
|
||||
uint8 slots = inst->GetItem()->BagSlots;
|
||||
uint8 j;
|
||||
for (j = invbag::SLOT_BEGIN; j<slots; j++) {
|
||||
if (!GetItem(base_slot_id + j)) {
|
||||
// Found available slot within bag
|
||||
return (base_slot_id + j);
|
||||
@@ -1424,10 +1417,6 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
|
||||
m_worn[slot_id] = inst;
|
||||
result = slot_id;
|
||||
}
|
||||
else if (slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END) {
|
||||
m_worn[slot_id] = inst;
|
||||
result = slot_id;
|
||||
}
|
||||
else if (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) {
|
||||
if (slot_id - EQ::invslot::BANK_BEGIN < m_lookup->InventoryTypeSize.Bank) {
|
||||
m_bank[slot_id] = inst;
|
||||
@@ -1454,7 +1443,7 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1729,17 +1718,3 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 lo
|
||||
|
||||
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 "classes.h"
|
||||
#include "races.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//FatherNitwit: location bits for searching specific
|
||||
@@ -132,7 +129,7 @@ namespace EQ
|
||||
|
||||
// Swap items in inventory
|
||||
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, uint8 class_id = Class::None, 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
|
||||
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
|
||||
int CountAugmentEquippedByID(uint32 item_id);
|
||||
|
||||
// Get a list of augments from a specific slot ID
|
||||
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
|
||||
|
||||
// Check whether there is space for the specified number of the specified item.
|
||||
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
|
||||
|
||||
@@ -203,12 +197,12 @@ namespace EQ
|
||||
void dumpBankItems();
|
||||
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, const 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, const std::string &identifier, bool value);
|
||||
std::string GetCustomItemData(int16 slot_id, const std::string& identifier);
|
||||
static const int GetItemStatValue(uint32 item_id, const std::string& identifier);
|
||||
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value);
|
||||
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value);
|
||||
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value);
|
||||
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value);
|
||||
std::string GetCustomItemData(int16 slot_id, std::string identifier);
|
||||
static int GetItemStatValue(uint32 item_id, const char* identifier);
|
||||
protected:
|
||||
///////////////////////////////
|
||||
// Protected Methods
|
||||
|
||||
+1
-1
@@ -198,7 +198,7 @@ std::string IpUtil::DNSLookupSync(const std::string &addr, int port)
|
||||
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 [{}]",
|
||||
"[DNSLookupSync] Deadline exceeded [{}]",
|
||||
1500
|
||||
);
|
||||
running = false;
|
||||
|
||||
+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
|
||||
{
|
||||
if (!(Races & GetPlayerRaceBit(race_id))) {
|
||||
if (!(Races & GetPlayerRaceBit(race_id)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
|
||||
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id))))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQ::ItemData::IsClassEquipable(uint16 class_id) const
|
||||
{
|
||||
|
||||
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQ::ItemData::IsRaceEquipable(uint16 race_id) const
|
||||
{
|
||||
|
||||
if (!(Races & GetPlayerRaceBit(race_id))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -230,10 +208,6 @@ bool EQ::ItemData::IsTypeShield() const
|
||||
return (ItemType == item::ItemTypeShield);
|
||||
}
|
||||
|
||||
bool EQ::ItemData::IsQuestItem() const {
|
||||
return QuestItemFlag;
|
||||
}
|
||||
|
||||
bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item)
|
||||
{
|
||||
if (!l_item || !r_item)
|
||||
|
||||
+160
-169
@@ -131,7 +131,7 @@ namespace EQ
|
||||
Mounts?
|
||||
Ornamentations?
|
||||
GuildBanners?
|
||||
Collectible?
|
||||
Collectible?
|
||||
Placeable?
|
||||
(others?)
|
||||
*/
|
||||
@@ -355,199 +355,190 @@ namespace EQ
|
||||
|
||||
struct ItemData {
|
||||
// Non packet based fields
|
||||
uint8 MinStatus {};
|
||||
char Comment[255] {};
|
||||
uint8 MinStatus;
|
||||
|
||||
// Packet based fields
|
||||
uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book
|
||||
char Name[64] {}; // Name
|
||||
char Lore[80] {}; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
||||
char IDFile[30] {}; // Visible model
|
||||
uint32 ID {}; // Unique ID (also PK for DB)
|
||||
int32 Weight {}; // Item weight * 10
|
||||
uint8 NoRent{} ; // No Rent: 0=norent, 255=not norent
|
||||
uint8 NoDrop {}; // No Drop: 0=nodrop, 255=not nodrop
|
||||
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 Price {}; // Item cost (?)
|
||||
uint32 Icon {}; // Icon Number
|
||||
int32 LoreGroup {}; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
||||
bool LoreFlag {}; // This will be true if LoreGroup is non-zero
|
||||
bool PendingLoreFlag {};
|
||||
bool ArtifactFlag {};
|
||||
bool SummonedFlag {};
|
||||
uint8 FVNoDrop {}; // Firiona Vie nodrop flag
|
||||
uint32 Favor {}; // Individual favor
|
||||
uint32 GuildFavor {}; // Guild favor
|
||||
uint32 PointType {};
|
||||
uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book
|
||||
char Name[64]; // Name
|
||||
char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
||||
char IDFile[30]; // Visible model
|
||||
uint32 ID; // Unique ID (also PK for DB)
|
||||
int32 Weight; // Item weight * 10
|
||||
uint8 NoRent; // No Rent: 0=norent, 255=not norent
|
||||
uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop
|
||||
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 Price; // Item cost (?)
|
||||
uint32 Icon; // Icon Number
|
||||
int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
||||
bool LoreFlag; // This will be true if LoreGroup is non-zero
|
||||
bool PendingLoreFlag;
|
||||
bool ArtifactFlag;
|
||||
bool SummonedFlag;
|
||||
uint8 FVNoDrop; // Firiona Vie nodrop flag
|
||||
uint32 Favor; // Individual favor
|
||||
uint32 GuildFavor; // Guild favor
|
||||
uint32 PointType;
|
||||
|
||||
//uint32 Unk117;
|
||||
//uint32 Unk118;
|
||||
//uint32 Unk121;
|
||||
//uint32 Unk124;
|
||||
|
||||
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 BagSize {}; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
|
||||
uint8 BagWR {}; // 0->100
|
||||
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 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
|
||||
uint8 BagWR; // 0->100
|
||||
|
||||
bool BenefitFlag {};
|
||||
bool Tradeskills {}; // Is this a tradeskill item?
|
||||
int8 CR {}; // Save vs Cold
|
||||
int8 DR {}; // Save vs Disease
|
||||
int8 PR {}; // Save vs Poison
|
||||
int8 MR {}; // Save vs Magic
|
||||
int8 FR {}; // Save vs Fire
|
||||
int8 AStr {}; // Strength
|
||||
int8 ASta {}; // Stamina
|
||||
int8 AAgi {}; // Agility
|
||||
int8 ADex {}; // Dexterity
|
||||
int8 ACha {}; // Charisma
|
||||
int8 AInt {}; // Intelligence
|
||||
int8 AWis {}; // Wisdom
|
||||
int32 HP {}; // HP
|
||||
int32 Mana {}; // Mana
|
||||
int32 AC {}; // AC
|
||||
uint32 Deity {}; // Bitmask of Deities that can equip this item
|
||||
bool BenefitFlag;
|
||||
bool Tradeskills; // Is this a tradeskill item?
|
||||
int8 CR; // Save vs Cold
|
||||
int8 DR; // Save vs Disease
|
||||
int8 PR; // Save vs Poison
|
||||
int8 MR; // Save vs Magic
|
||||
int8 FR; // Save vs Fire
|
||||
int8 AStr; // Strength
|
||||
int8 ASta; // Stamina
|
||||
int8 AAgi; // Agility
|
||||
int8 ADex; // Dexterity
|
||||
int8 ACha; // Charisma
|
||||
int8 AInt; // Intelligence
|
||||
int8 AWis; // Wisdom
|
||||
int32 HP; // HP
|
||||
int32 Mana; // Mana
|
||||
int32 AC; // AC
|
||||
uint32 Deity; // Bitmask of Deities that can equip this item
|
||||
//uint32 Unk033
|
||||
int32 SkillModValue {}; // % Mod to skill specified in SkillModType
|
||||
int32 SkillModMax {}; // Max skill point modification
|
||||
uint32 SkillModType {}; // Type of skill for SkillModValue to apply to
|
||||
uint32 BaneDmgRace {}; // Bane Damage Race
|
||||
int32 BaneDmgAmt {}; // Bane Damage Body Amount
|
||||
uint32 BaneDmgBody {}; // Bane Damage Body
|
||||
bool Magic {}; // True=Magic Item, False=not
|
||||
int32 CastTime_ {};
|
||||
uint8 ReqLevel {}; // Required Level to use item
|
||||
uint32 BardType {}; // Bard Skill Type
|
||||
int32 BardValue {}; // Bard Skill Amount
|
||||
int8 Light {}; // Light
|
||||
uint8 Delay {}; // Delay * 10
|
||||
uint8 RecLevel {}; // Recommended level to use item
|
||||
uint8 RecSkill {}; // Recommended skill to use item (refers to primary skill of item)
|
||||
uint8 ElemDmgType {}; // Elemental Damage Type (1=magic, 2=fire)
|
||||
uint8 ElemDmgAmt {}; // Elemental Damage
|
||||
uint8 Range {}; // Range of item
|
||||
uint32 Damage {}; // Delay between item usage (in 0.1 sec increments)
|
||||
uint32 Color {}; // RR GG BB 00 <-- as it appears in pc
|
||||
uint32 Classes {}; // Bitfield of classes that can equip item (1 << class#)
|
||||
uint32 Races {}; // Bitfield of races that can equip item (1 << race#)
|
||||
//uint32 Unk054 {};
|
||||
int16 MaxCharges {}; // Maximum charges items can hold: -1 if not a chargeable item
|
||||
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)
|
||||
uint8 Material {}; // Item material type
|
||||
uint32 HerosForgeModel {};// Hero's Forge Armor Model Type (2-13?)
|
||||
float SellRate {}; // Sell rate
|
||||
//uint32 Unk059 {};
|
||||
int32 SkillModValue; // % Mod to skill specified in SkillModType
|
||||
int32 SkillModMax; // Max skill point modification
|
||||
uint32 SkillModType; // Type of skill for SkillModValue to apply to
|
||||
uint32 BaneDmgRace; // Bane Damage Race
|
||||
int32 BaneDmgAmt; // Bane Damage Body Amount
|
||||
uint32 BaneDmgBody; // Bane Damage Body
|
||||
bool Magic; // True=Magic Item, False=not
|
||||
int32 CastTime_;
|
||||
uint8 ReqLevel; // Required Level to use item
|
||||
uint32 BardType; // Bard Skill Type
|
||||
int32 BardValue; // Bard Skill Amount
|
||||
int8 Light; // Light
|
||||
uint8 Delay; // Delay * 10
|
||||
uint8 RecLevel; // Recommended level to use item
|
||||
uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item)
|
||||
uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire)
|
||||
uint8 ElemDmgAmt; // Elemental Damage
|
||||
uint8 Range; // Range of item
|
||||
uint32 Damage; // Delay between item usage (in 0.1 sec increments)
|
||||
uint32 Color; // RR GG BB 00 <-- as it appears in pc
|
||||
uint32 Classes; // Bitfield of classes that can equip item (1 << class#)
|
||||
uint32 Races; // Bitfield of races that can equip item (1 << race#)
|
||||
//uint32 Unk054;
|
||||
int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
|
||||
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)
|
||||
uint8 Material; // Item material type
|
||||
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
|
||||
float SellRate; // Sell rate
|
||||
//uint32 Unk059;
|
||||
union {
|
||||
uint32 Fulfilment; // Food fulfilment (How long it lasts)
|
||||
uint32 CastTime; // Cast Time for clicky effects, in milliseconds
|
||||
};
|
||||
uint32 EliteMaterial {};
|
||||
int32 ProcRate {};
|
||||
int8 CombatEffects {}; // PoP: Combat Effects +
|
||||
int8 Shielding {}; // PoP: Shielding %
|
||||
int8 StunResist {}; // PoP: Stun Resist %
|
||||
int8 StrikeThrough {}; // PoP: Strike Through %
|
||||
int32 ExtraDmgSkill {};
|
||||
int32 ExtraDmgAmt {};
|
||||
int8 SpellShield {}; // PoP: Spell Shield %
|
||||
int8 Avoidance {}; // PoP: Avoidance +
|
||||
int8 Accuracy {}; // PoP: Accuracy +
|
||||
uint32 CharmFileID {};
|
||||
int32 FactionMod1 {}; // Faction Mod 1
|
||||
int32 FactionMod2 {}; // Faction Mod 2
|
||||
int32 FactionMod3 {}; // Faction Mod 3
|
||||
int32 FactionMod4 {}; // Faction Mod 4
|
||||
int32 FactionAmt1 {}; // Faction Amt 1
|
||||
int32 FactionAmt2 {}; // Faction Amt 2
|
||||
int32 FactionAmt3 {}; // Faction Amt 3
|
||||
int32 FactionAmt4 {}; // Faction Amt 4
|
||||
char CharmFile[32] {}; // ?
|
||||
uint32 AugType {};
|
||||
uint8 AugSlotType[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Type
|
||||
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
|
||||
uint32 LDoNTheme {};
|
||||
uint32 LDoNPrice {};
|
||||
uint32 LDoNSold {};
|
||||
uint32 BaneDmgRaceAmt {};
|
||||
uint32 AugRestrict {};
|
||||
int32 Endur {};
|
||||
int32 DotShielding {};
|
||||
int32 Attack {};
|
||||
int32 Regen {};
|
||||
int32 ManaRegen {};
|
||||
int32 EnduranceRegen {};
|
||||
int32 Haste {};
|
||||
int32 DamageShield {};
|
||||
uint32 RecastDelay {};
|
||||
int RecastType {};
|
||||
uint32 AugDistiller {};
|
||||
bool Attuneable {};
|
||||
bool NoPet {};
|
||||
bool PotionBelt {};
|
||||
bool Stackable {};
|
||||
bool NoTransfer {};
|
||||
bool QuestItemFlag {};
|
||||
int16 StackSize {};
|
||||
uint8 PotionBeltSlots {};
|
||||
item::ItemEffect_Struct Click {};
|
||||
item::ItemEffect_Struct Proc {};
|
||||
item::ItemEffect_Struct Worn {};
|
||||
item::ItemEffect_Struct Focus {};
|
||||
item::ItemEffect_Struct Scroll {};
|
||||
item::ItemEffect_Struct Bard {};
|
||||
uint32 EliteMaterial;
|
||||
int32 ProcRate;
|
||||
int8 CombatEffects; // PoP: Combat Effects +
|
||||
int8 Shielding; // PoP: Shielding %
|
||||
int8 StunResist; // PoP: Stun Resist %
|
||||
int8 StrikeThrough; // PoP: Strike Through %
|
||||
uint32 ExtraDmgSkill;
|
||||
uint32 ExtraDmgAmt;
|
||||
int8 SpellShield; // PoP: Spell Shield %
|
||||
int8 Avoidance; // PoP: Avoidance +
|
||||
int8 Accuracy; // PoP: Accuracy +
|
||||
uint32 CharmFileID;
|
||||
int32 FactionMod1; // Faction Mod 1
|
||||
int32 FactionMod2; // Faction Mod 2
|
||||
int32 FactionMod3; // Faction Mod 3
|
||||
int32 FactionMod4; // Faction Mod 4
|
||||
int32 FactionAmt1; // Faction Amt 1
|
||||
int32 FactionAmt2; // Faction Amt 2
|
||||
int32 FactionAmt3; // Faction Amt 3
|
||||
int32 FactionAmt4; // Faction Amt 4
|
||||
char CharmFile[32]; // ?
|
||||
uint32 AugType;
|
||||
uint8 AugSlotType[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Type
|
||||
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
|
||||
uint32 LDoNTheme;
|
||||
uint32 LDoNPrice;
|
||||
uint32 LDoNSold;
|
||||
uint32 BaneDmgRaceAmt;
|
||||
uint32 AugRestrict;
|
||||
int32 Endur;
|
||||
int32 DotShielding;
|
||||
int32 Attack;
|
||||
int32 Regen;
|
||||
int32 ManaRegen;
|
||||
int32 EnduranceRegen;
|
||||
int32 Haste;
|
||||
int32 DamageShield;
|
||||
uint32 RecastDelay;
|
||||
int RecastType;
|
||||
uint32 AugDistiller;
|
||||
bool Attuneable;
|
||||
bool NoPet;
|
||||
bool PotionBelt;
|
||||
bool Stackable;
|
||||
bool NoTransfer;
|
||||
bool QuestItemFlag;
|
||||
int16 StackSize;
|
||||
uint8 PotionBeltSlots;
|
||||
item::ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
|
||||
|
||||
uint8 Book {}; // 0=Not book, 1=Book
|
||||
uint32 BookType {};
|
||||
char Filename[33] {}; // Filename for book data
|
||||
uint8 Book; // 0=Not book, 1=Book
|
||||
uint32 BookType;
|
||||
char Filename[33]; // Filename for book data
|
||||
// Begin SoF Fields
|
||||
int32 SVCorruption {};
|
||||
uint32 Purity {};
|
||||
uint8 EvolvingItem {};
|
||||
uint32 EvolvingID {};
|
||||
uint8 EvolvingLevel {};
|
||||
uint8 EvolvingMax {};
|
||||
uint32 BackstabDmg {};
|
||||
uint32 DSMitigation {};
|
||||
int32 HeroicStr {};
|
||||
int32 HeroicInt {};
|
||||
int32 HeroicWis {};
|
||||
int32 HeroicAgi {};
|
||||
int32 HeroicDex {};
|
||||
int32 HeroicSta {};
|
||||
int32 HeroicCha {};
|
||||
int32 HeroicMR {};
|
||||
int32 HeroicFR {};
|
||||
int32 HeroicCR {};
|
||||
int32 HeroicDR {};
|
||||
int32 HeroicPR {};
|
||||
int32 HeroicSVCorrup {};
|
||||
int32 HealAmt {};
|
||||
int32 SpellDmg {};
|
||||
uint32 LDoNSellBackRate {};
|
||||
uint32 ScriptFileID {};
|
||||
uint16 ExpendableArrow {};
|
||||
uint32 Clairvoyance {};
|
||||
char ClickName[65] {};
|
||||
char ProcName[65] {};
|
||||
char WornName[65] {};
|
||||
char FocusName[65] {};
|
||||
char ScrollName[65] {};
|
||||
int32 SVCorruption;
|
||||
uint32 Purity;
|
||||
uint8 EvolvingItem;
|
||||
uint32 EvolvingID;
|
||||
uint8 EvolvingLevel;
|
||||
uint8 EvolvingMax;
|
||||
uint32 BackstabDmg;
|
||||
uint32 DSMitigation;
|
||||
int32 HeroicStr;
|
||||
int32 HeroicInt;
|
||||
int32 HeroicWis;
|
||||
int32 HeroicAgi;
|
||||
int32 HeroicDex;
|
||||
int32 HeroicSta;
|
||||
int32 HeroicCha;
|
||||
int32 HeroicMR;
|
||||
int32 HeroicFR;
|
||||
int32 HeroicCR;
|
||||
int32 HeroicDR;
|
||||
int32 HeroicPR;
|
||||
int32 HeroicSVCorrup;
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
uint32 LDoNSellBackRate;
|
||||
uint32 ScriptFileID;
|
||||
uint16 ExpendableArrow;
|
||||
uint32 Clairvoyance;
|
||||
char ClickName[65];
|
||||
char ProcName[65];
|
||||
char WornName[65];
|
||||
char FocusName[65];
|
||||
char ScrollName[65];
|
||||
//BardName
|
||||
|
||||
bool IsEquipable(uint16 Race, uint16 Class) const;
|
||||
bool IsClassEquipable(uint16 Class) const;
|
||||
bool IsRaceEquipable(uint16 Race) const;
|
||||
bool IsClassCommon() const;
|
||||
bool IsClassBag() const;
|
||||
bool IsClassBook() const;
|
||||
bool IsType1HWeapon() const;
|
||||
bool IsType2HWeapon() const;
|
||||
bool IsTypeShield() const;
|
||||
bool IsQuestItem() const;
|
||||
|
||||
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
|
||||
bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); }
|
||||
|
||||
+186
-266
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
|
||||
#include "inventory_profile.h"
|
||||
#include "../common/data_verification.h"
|
||||
//#include "classes.h"
|
||||
//#include "global_define.h"
|
||||
//#include "item_instance.h"
|
||||
@@ -58,62 +57,108 @@ static inline int32 GetNextItemInstSerialNumber() {
|
||||
// class EQ::ItemInstance
|
||||
//
|
||||
EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
|
||||
|
||||
if (item) {
|
||||
m_use_type = ItemInstNormal;
|
||||
if(item) {
|
||||
m_item = new ItemData(*item);
|
||||
} else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
|
||||
m_charges = charges;
|
||||
|
||||
if (m_item && m_item->IsClassCommon()) {
|
||||
m_price = 0;
|
||||
m_attuned = false;
|
||||
m_merchantslot = 0;
|
||||
if (m_item && m_item->IsClassCommon())
|
||||
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) {
|
||||
|
||||
m_item = db->GetItem(item_id);
|
||||
|
||||
if (m_item) {
|
||||
m_use_type = ItemInstNormal;
|
||||
m_item = db->GetItem(item_id);
|
||||
if(m_item) {
|
||||
m_item = new ItemData(*m_item);
|
||||
}
|
||||
else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
|
||||
m_charges = charges;
|
||||
|
||||
if (m_item && m_item->IsClassCommon()) {
|
||||
m_price = 0;
|
||||
m_merchantslot = 0;
|
||||
m_attuned=false;
|
||||
if (m_item && m_item->IsClassCommon())
|
||||
m_color = m_item->Color;
|
||||
} else {
|
||||
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(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
|
||||
EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
||||
{
|
||||
m_use_type = copy.m_use_type;
|
||||
|
||||
if (copy.m_item) {
|
||||
m_use_type=copy.m_use_type;
|
||||
if(copy.m_item)
|
||||
m_item = new ItemData(*copy.m_item);
|
||||
} else {
|
||||
else
|
||||
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
|
||||
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
|
||||
ItemInstance* inst_old = it->second;
|
||||
@@ -123,42 +168,37 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
||||
inst_new = inst_old->Clone();
|
||||
}
|
||||
|
||||
if (inst_new) {
|
||||
if (inst_new != nullptr) {
|
||||
m_contents[it->first] = inst_new;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>::const_iterator iter;
|
||||
for (iter = copy.m_custom_data.begin(); iter != copy.m_custom_data.end(); ++iter) {
|
||||
m_custom_data[iter->first] = iter->second;
|
||||
}
|
||||
|
||||
m_SerialNumber = copy.m_SerialNumber;
|
||||
m_custom_data = copy.m_custom_data;
|
||||
m_timers = copy.m_timers;
|
||||
m_custom_data = copy.m_custom_data;
|
||||
m_timers = copy.m_timers;
|
||||
|
||||
m_exp = copy.m_exp;
|
||||
m_exp = copy.m_exp;
|
||||
m_evolveLvl = copy.m_evolveLvl;
|
||||
m_activated = copy.m_activated;
|
||||
|
||||
if (copy.m_scaledItem) {
|
||||
if (copy.m_scaledItem)
|
||||
m_scaledItem = new ItemData(*copy.m_scaledItem);
|
||||
} else {
|
||||
else
|
||||
m_scaledItem = nullptr;
|
||||
}
|
||||
|
||||
if (copy.m_evolveInfo) {
|
||||
if(copy.m_evolveInfo)
|
||||
m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo);
|
||||
} else {
|
||||
else
|
||||
m_evolveInfo = nullptr;
|
||||
}
|
||||
|
||||
m_scaling = copy.m_scaling;
|
||||
m_ornamenticon = copy.m_ornamenticon;
|
||||
m_ornamentidfile = copy.m_ornamentidfile;
|
||||
m_scaling = copy.m_scaling;
|
||||
m_ornamenticon = copy.m_ornamenticon;
|
||||
m_ornamentidfile = copy.m_ornamentidfile;
|
||||
m_ornament_hero_model = copy.m_ornament_hero_model;
|
||||
m_recast_timestamp = copy.m_recast_timestamp;
|
||||
m_new_id_file = copy.m_new_id_file;
|
||||
m_recast_timestamp = copy.m_recast_timestamp;
|
||||
m_new_id_file = copy.m_new_id_file;
|
||||
}
|
||||
|
||||
// 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'
|
||||
|
||||
// Check usage type
|
||||
if (m_use_type == ItemInstWorldContainer && item_class == item::ItemClassBag) {
|
||||
if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_item) {
|
||||
if (!m_item)
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_item->ItemClass == item_class);
|
||||
}
|
||||
@@ -205,145 +243,96 @@ bool EQ::ItemInstance::IsClassBook() const
|
||||
// Is item stackable?
|
||||
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
|
||||
{
|
||||
if (!m_item) {
|
||||
if (!m_item)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_item->MaxCharges > 1) {
|
||||
if (m_item->MaxCharges > 1)
|
||||
return true;
|
||||
} else {
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Can item be equipped?
|
||||
bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const
|
||||
{
|
||||
if (!m_item || !m_item->Slots) {
|
||||
if (!m_item || (m_item->Slots == 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_item->IsEquipable(race, class_);
|
||||
}
|
||||
|
||||
// Can item be equipped by Class?
|
||||
bool EQ::ItemInstance::IsClassEquipable(uint16 class_) const
|
||||
{
|
||||
if (!m_item || !m_item->Slots) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_item->IsClassEquipable(class_);
|
||||
}
|
||||
|
||||
// Can item be equipped by Race?
|
||||
bool EQ::ItemInstance::IsRaceEquipable(uint16 race) const
|
||||
{
|
||||
if (!m_item || !m_item->Slots) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_item->IsRaceEquipable(race);
|
||||
}
|
||||
|
||||
// Can equip at this slot?
|
||||
bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
|
||||
{
|
||||
if (!m_item || !m_item->Slots) {
|
||||
if (!m_item)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
|
||||
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END)
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((m_item->Slots & (1 << slot_id)) != 0);
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::IsAugmentable() const
|
||||
{
|
||||
if (!m_item) {
|
||||
if (!m_item)
|
||||
return false;
|
||||
}
|
||||
|
||||
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 false;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = invslot::EQUIPMENT_BEGIN;
|
||||
for (; index <= invslot::EQUIPMENT_END; ++index) {
|
||||
if (m_item->Slots & (1 << index)) {
|
||||
if (aug_wear_slots & (1 << index)) {
|
||||
if (aug_wear_slots & (1 << index))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (index <= EQ::invslot::EQUIPMENT_END);
|
||||
}
|
||||
|
||||
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
|
||||
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augtype) const
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
auto i = invaug::SOCKET_BEGIN;
|
||||
for (; i <= invaug::SOCKET_END; ++i) {
|
||||
if (GetItem(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
augment_type == -1 ||
|
||||
(
|
||||
m_item->AugSlotType[i] &&
|
||||
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
|
||||
)
|
||||
) {
|
||||
int index = invaug::SOCKET_BEGIN;
|
||||
for (; index <= invaug::SOCKET_END; ++index) {
|
||||
if (GetItem(index)) { continue; }
|
||||
if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
|
||||
return (index <= invaug::SOCKET_END) ? index : INVALID_INDEX;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const
|
||||
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return false;
|
||||
|
||||
if (
|
||||
(
|
||||
!GetItem(slot) &&
|
||||
m_item->AugSlotVisible[slot]
|
||||
) &&
|
||||
augment_type == -1 ||
|
||||
(
|
||||
m_item->AugSlotType[slot] &&
|
||||
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
|
||||
)
|
||||
) {
|
||||
if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve item inside container
|
||||
@@ -359,10 +348,9 @@ EQ::ItemInstance* EQ::ItemInstance::GetItem(uint8 index) const
|
||||
|
||||
uint32 EQ::ItemInstance::GetItemID(uint8 slot) const
|
||||
{
|
||||
const auto item = GetItem(slot);
|
||||
if (item) {
|
||||
ItemInstance *item = GetItem(slot);
|
||||
if (item)
|
||||
return item->GetID();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -486,21 +474,14 @@ uint8 EQ::ItemInstance::FirstOpenSlot() const
|
||||
|
||||
uint8 EQ::ItemInstance::GetTotalItemCount() const
|
||||
{
|
||||
if (!m_item) {
|
||||
if (!m_item)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 item_count = 1;
|
||||
|
||||
if (!m_item->IsClassBag()) {
|
||||
return item_count;
|
||||
}
|
||||
if (m_item && !m_item->IsClassBag()) { return item_count; }
|
||||
|
||||
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) {
|
||||
if (GetItem(index)) {
|
||||
++item_count;
|
||||
}
|
||||
}
|
||||
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } }
|
||||
|
||||
return item_count;
|
||||
}
|
||||
@@ -519,108 +500,86 @@ bool EQ::ItemInstance::IsNoneEmptyContainer()
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
return GetItem(augment_index);
|
||||
}
|
||||
if (m_item && m_item->IsClassCommon())
|
||||
return GetItem(slot);
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
if (!m_item || !m_item->IsClassCommon()) { return nullptr; }
|
||||
if (ornamentationAugtype == 0) { return nullptr; }
|
||||
|
||||
const auto augment_item = augment->GetItem();
|
||||
if (!augment_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string& idfile = augment_item->IDFile;
|
||||
|
||||
if (
|
||||
EQ::ValueWithin(
|
||||
augment->GetAugmentType(),
|
||||
OrnamentationAugmentTypes::StandardOrnamentation,
|
||||
OrnamentationAugmentTypes::SpecialOrnamentation
|
||||
) ||
|
||||
(
|
||||
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;
|
||||
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++)
|
||||
{
|
||||
if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype)
|
||||
{
|
||||
const char *item_IDFile = GetAugment(i)->GetItem()->IDFile;
|
||||
if (
|
||||
(strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0
|
||||
|| strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0)
|
||||
&& GetAugment(i)->GetItem()->HerosForgeModel == 0
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return GetAugment(i);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const
|
||||
{
|
||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Item is using a shorthand ID
|
||||
return (m_ornament_hero_model * 100) + material_slot;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::UpdateOrnamentationInfo()
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
bool EQ::ItemInstance::UpdateOrnamentationInfo() {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto augment = GetOrnamentationAugment();
|
||||
bool ornamentSet = false;
|
||||
|
||||
if (augment) {
|
||||
const auto augment_item = GetOrnamentationAugment()->GetItem();
|
||||
|
||||
if (augment_item) {
|
||||
SetOrnamentIcon(augment_item->Icon);
|
||||
SetOrnamentHeroModel(augment_item->HerosForgeModel);
|
||||
|
||||
if (strlen(augment_item->IDFile) > 2) {
|
||||
SetOrnamentationIDFile(Strings::ToUnsignedInt(&augment_item->IDFile[2]));
|
||||
} else {
|
||||
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
if (GetOrnamentationAug(ornamentationAugtype))
|
||||
{
|
||||
const ItemData* ornamentItem;
|
||||
ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
if (ornamentItem != nullptr)
|
||||
{
|
||||
SetOrnamentIcon(ornamentItem->Icon);
|
||||
SetOrnamentHeroModel(ornamentItem->HerosForgeModel);
|
||||
if (strlen(ornamentItem->IDFile) > 2)
|
||||
{
|
||||
SetOrnamentationIDFile(atoi(&ornamentItem->IDFile[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetOrnamentationIDFile(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
ornamentSet = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetOrnamentIcon(0);
|
||||
SetOrnamentHeroModel(0);
|
||||
SetOrnamentationIDFile(0);
|
||||
}
|
||||
|
||||
SetOrnamentIcon(0);
|
||||
SetOrnamentHeroModel(0);
|
||||
SetOrnamentationIDFile(0);
|
||||
|
||||
return false;
|
||||
return ornamentSet;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 GetItemID(augment_index);
|
||||
return GetItemID(slot);
|
||||
}
|
||||
|
||||
// Add an augment to the item
|
||||
@@ -720,14 +678,12 @@ EQ::ItemInstance* EQ::ItemInstance::RemoveAugment(uint8 index)
|
||||
|
||||
bool EQ::ItemInstance::IsAugmented()
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) {
|
||||
if (GetAugmentItemID(slot_id)) {
|
||||
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
|
||||
if (GetAugmentItemID(index))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -836,20 +792,7 @@ std::string EQ::ItemInstance::GetCustomDataString() const {
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void EQ::ItemInstance::SetCustomDataString(const std::string& str)
|
||||
{
|
||||
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::string EQ::ItemInstance::GetCustomData(std::string identifier) {
|
||||
std::map<std::string, std::string>::const_iterator iter = m_custom_data.find(identifier);
|
||||
if (iter != m_custom_data.end()) {
|
||||
return iter->second;
|
||||
@@ -858,33 +801,33 @@ std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) {
|
||||
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);
|
||||
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);
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
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);
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
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);
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
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);
|
||||
if (iter != m_custom_data.end()) {
|
||||
m_custom_data.erase(iter);
|
||||
@@ -936,9 +879,8 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
|
||||
|
||||
void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
||||
// if there's no actual item, don't do anything
|
||||
if (!m_item) {
|
||||
if (!m_item)
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize scaling items
|
||||
if (m_item->CharmFileID != 0) {
|
||||
@@ -947,7 +889,7 @@ void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
||||
}
|
||||
|
||||
// initialize evolving items
|
||||
else if (db && m_item->LoreGroup >= 1000) {
|
||||
else if ((db) && m_item->LoreGroup >= 1000 && m_item->LoreGroup != -1) {
|
||||
// not complete yet
|
||||
}
|
||||
}
|
||||
@@ -1273,7 +1215,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const
|
||||
|
||||
int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
|
||||
{
|
||||
int race = Race::Doug;
|
||||
int race = 0;
|
||||
const auto item = GetItem();
|
||||
if (item) {
|
||||
race = item->BaneDmgRace;
|
||||
@@ -1779,28 +1721,6 @@ int EQ::ItemInstance::GetItemHaste(bool augments) const
|
||||
return total;
|
||||
}
|
||||
|
||||
int EQ::ItemInstance::RemoveTaskDeliveredItems()
|
||||
{
|
||||
int count = IsStackable() ? GetCharges() : 1;
|
||||
count -= GetTaskDeliveredCount();
|
||||
if (IsStackable())
|
||||
{
|
||||
SetCharges(count);
|
||||
}
|
||||
SetTaskDeliveredCount(0);
|
||||
return count;
|
||||
}
|
||||
|
||||
uint32 EQ::ItemInstance::GetItemGuildFavor() const
|
||||
{
|
||||
uint32 total = 0;
|
||||
const auto item = GetItem();
|
||||
if (item) {
|
||||
return total = item->GuildFavor;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// class EvolveInfo
|
||||
//
|
||||
|
||||
+38
-58
@@ -51,11 +51,6 @@ typedef enum {
|
||||
byFlagNotSet //apply action if the flag is NOT set
|
||||
} byFlagSetting;
|
||||
|
||||
enum OrnamentationAugmentTypes {
|
||||
StandardOrnamentation = 20,
|
||||
SpecialOrnamentation = 21
|
||||
};
|
||||
|
||||
class SharedDatabase;
|
||||
|
||||
// ########################################
|
||||
@@ -97,8 +92,6 @@ namespace EQ
|
||||
|
||||
// Can item be equipped by/at?
|
||||
bool IsEquipable(uint16 race, uint16 class_) const;
|
||||
bool IsClassEquipable(uint16 class_) const;
|
||||
bool IsRaceEquipable(uint16 race) const;
|
||||
bool IsEquipable(int16 slot_id) const;
|
||||
|
||||
//
|
||||
@@ -106,10 +99,9 @@ namespace EQ
|
||||
//
|
||||
bool IsAugmentable() const;
|
||||
bool AvailableWearSlot(uint32 aug_wear_slots) const;
|
||||
int8 AvailableAugmentSlot(int32 augment_type) const;
|
||||
bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const;
|
||||
inline int GetAugmentType() const { return m_item ? m_item->AugType : 0; }
|
||||
inline uint32 GetAugmentRestriction() const { return m_item ? m_item->AugRestrict : 0; }
|
||||
int8 AvailableAugmentSlot(int32 augtype) const;
|
||||
bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const;
|
||||
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); }
|
||||
|
||||
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); }
|
||||
|
||||
@@ -133,8 +125,8 @@ namespace EQ
|
||||
//
|
||||
// Augments
|
||||
//
|
||||
ItemInstance* GetAugment(uint8 augment_index) const;
|
||||
uint32 GetAugmentItemID(uint8 augment_index) const;
|
||||
ItemInstance* GetAugment(uint8 slot) const;
|
||||
uint32 GetAugmentItemID(uint8 slot) const;
|
||||
void PutAugment(uint8 slot, const ItemInstance& inst);
|
||||
void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id);
|
||||
void DeleteAugment(uint8 slot);
|
||||
@@ -142,8 +134,7 @@ namespace EQ
|
||||
bool IsAugmented();
|
||||
bool ContainsAugmentByID(uint32 item_id);
|
||||
int CountAugmentByID(uint32 item_id);
|
||||
bool IsOrnamentationAugment(EQ::ItemInstance* augment) const;
|
||||
ItemInstance* GetOrnamentationAugment() const;
|
||||
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
|
||||
bool UpdateOrnamentationInfo();
|
||||
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
||||
|
||||
@@ -157,8 +148,6 @@ namespace EQ
|
||||
const ItemData* GetItem() const;
|
||||
const ItemData* GetUnscaledItem() const;
|
||||
|
||||
const uint8 GetItemType() const { return m_item ? m_item->ItemType : 255; } // Return 255 so you know there's no valid item
|
||||
|
||||
int16 GetCharges() const { return m_charges; }
|
||||
void SetCharges(int16 charges) { m_charges = charges; }
|
||||
|
||||
@@ -182,13 +171,12 @@ namespace EQ
|
||||
void SetAttuned(bool flag) { m_attuned = flag; }
|
||||
|
||||
std::string GetCustomDataString() const;
|
||||
std::string GetCustomData(const std::string &identifier);
|
||||
void SetCustomDataString(const std::string& str);
|
||||
void SetCustomData(const std::string &identifier, const std::string& value);
|
||||
void SetCustomData(const std::string &identifier, int value);
|
||||
void SetCustomData(const std::string &identifier, float value);
|
||||
void SetCustomData(const std::string &identifier, bool value);
|
||||
void DeleteCustomData(const std::string& identifier);
|
||||
std::string GetCustomData(std::string identifier);
|
||||
void SetCustomData(std::string identifier, std::string value);
|
||||
void SetCustomData(std::string identifier, int value);
|
||||
void SetCustomData(std::string identifier, float value);
|
||||
void SetCustomData(std::string identifier, bool value);
|
||||
void DeleteCustomData(std::string identifier);
|
||||
|
||||
// Allows treatment of this object as though it were a pointer to m_item
|
||||
operator bool() const { return (m_item != nullptr); }
|
||||
@@ -241,13 +229,6 @@ namespace EQ
|
||||
void StopTimer(std::string name);
|
||||
void ClearTimers();
|
||||
|
||||
int GetTaskDeliveredCount() const { return m_task_delivered_count; }
|
||||
void SetTaskDeliveredCount(int count) { m_task_delivered_count = count; }
|
||||
// This function should only be used by trade return apis
|
||||
// Removes delivered task items from stack count and returns remaining count
|
||||
// Return value should be used to determine if an item still exists (for stackable and non-stackable)
|
||||
int RemoveTaskDeliveredItems();
|
||||
|
||||
// Get a total of a stat, including augs
|
||||
// These functions should be used in place of other code manually totaling
|
||||
// to centralize where it is done to make future changes easier (ex. whenever powersources come around)
|
||||
@@ -299,7 +280,6 @@ namespace EQ
|
||||
int GetItemHeroicDR(bool augments = false) const;
|
||||
int GetItemHeroicCorrup(bool augments = false) const;
|
||||
int GetItemHaste(bool augments = false) const;
|
||||
uint32 GetItemGuildFavor() const;
|
||||
|
||||
protected:
|
||||
//////////////////////////
|
||||
@@ -312,33 +292,33 @@ namespace EQ
|
||||
|
||||
void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; }
|
||||
|
||||
ItemInstTypes m_use_type {ItemInstNormal}; // Usage type for item
|
||||
const ItemData* m_item {nullptr}; // Ptr to item data
|
||||
int16 m_charges {0}; // # of charges for chargeable items
|
||||
uint32 m_price {0}; // Bazaar /trader price
|
||||
uint32 m_color {0};
|
||||
uint32 m_merchantslot {0};
|
||||
int16 m_currentslot {0};
|
||||
bool m_attuned {false};
|
||||
int32 m_merchantcount {1}; //number avaliable on the merchant, -1=unlimited
|
||||
int32 m_SerialNumber {0}; // Unique identifier for this instance of an item. Needed for Bazaar.
|
||||
uint32 m_exp {0};
|
||||
int8 m_evolveLvl {0};
|
||||
bool m_activated {false};
|
||||
ItemData* m_scaledItem {nullptr};
|
||||
::EvolveInfo* m_evolveInfo {nullptr};
|
||||
bool m_scaling {false};
|
||||
uint32 m_ornamenticon {0};
|
||||
uint32 m_ornamentidfile {0};
|
||||
uint32 m_new_id_file {0};
|
||||
uint32 m_ornament_hero_model {0};
|
||||
uint32 m_recast_timestamp {0};
|
||||
int m_task_delivered_count {0};
|
||||
ItemInstTypes m_use_type; // Usage type for item
|
||||
const ItemData* m_item; // Ptr to item data
|
||||
int16 m_charges; // # of charges for chargeable items
|
||||
uint32 m_price; // Bazaar /trader price
|
||||
uint32 m_color;
|
||||
uint32 m_merchantslot;
|
||||
int16 m_currentslot;
|
||||
bool m_attuned;
|
||||
int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited
|
||||
int32 m_SerialNumber; // Unique identifier for this instance of an item. Needed for Bazaar.
|
||||
uint32 m_exp;
|
||||
int8 m_evolveLvl;
|
||||
bool m_activated;
|
||||
ItemData* m_scaledItem;
|
||||
::EvolveInfo* m_evolveInfo;
|
||||
bool m_scaling;
|
||||
uint32 m_ornamenticon;
|
||||
uint32 m_ornamentidfile;
|
||||
uint32 m_new_id_file;
|
||||
uint32 m_ornament_hero_model;
|
||||
uint32 m_recast_timestamp;
|
||||
|
||||
// Items inside of this item (augs or contents) {};
|
||||
std::map<uint8, ItemInstance*> m_contents {}; // Zero-based index: min=0, max=9
|
||||
std::map<std::string, std::string> m_custom_data {};
|
||||
std::map<std::string, ::Timer> m_timers {};
|
||||
//
|
||||
// Items inside of this item (augs or contents);
|
||||
std::map<uint8, ItemInstance*> m_contents; // Zero-based index: min=0, max=9
|
||||
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
@@ -0,0 +1,52 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.org)
|
||||
|
||||
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
|
||||
*/
|
||||
#ifndef LANGUAGES_H
|
||||
#define LANGUAGES_H
|
||||
#include "../common/types.h"
|
||||
|
||||
#define LANG_COMMON_TONGUE 0
|
||||
#define LANG_BARBARIAN 1
|
||||
#define LANG_ERUDIAN 2
|
||||
#define LANG_ELVISH 3
|
||||
#define LANG_DARK_ELVISH 4
|
||||
#define LANG_DWARVISH 5
|
||||
#define LANG_TROLL 6
|
||||
#define LANG_OGRE 7
|
||||
#define LANG_GNOMISH 8
|
||||
#define LANG_HALFLING 9
|
||||
#define LANG_THIEVES_CANT 10
|
||||
#define LANG_OLD_ERUDIAN 11
|
||||
#define LANG_ELDER_ELVISH 12
|
||||
#define LANG_FROGLOK 13
|
||||
#define LANG_GOBLIN 14
|
||||
#define LANG_GNOLL 15
|
||||
#define LANG_COMBINE_TONGUE 16
|
||||
#define LANG_ELDER_TEIRDAL 17
|
||||
#define LANG_LIZARDMAN 18
|
||||
#define LANG_ORCISH 19
|
||||
#define LANG_FAERIE 20
|
||||
#define LANG_DRAGON 21
|
||||
#define LANG_ELDER_DRAGON 22
|
||||
#define LANG_DARK_SPEECH 23
|
||||
#define LANG_VAH_SHIR 24
|
||||
#define LANG_ALARAN 25
|
||||
#define LANG_HADAL 26
|
||||
#define LANG_UNKNOWN 27
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef CODE_LOOT_H
|
||||
#define CODE_LOOT_H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include "../common/types.h"
|
||||
|
||||
struct LootItem {
|
||||
uint32 item_id;
|
||||
int16 equip_slot;
|
||||
uint16 charges;
|
||||
uint16 lootslot;
|
||||
uint32 aug_1;
|
||||
uint32 aug_2;
|
||||
uint32 aug_3;
|
||||
uint32 aug_4;
|
||||
uint32 aug_5;
|
||||
uint32 aug_6;
|
||||
bool attuned;
|
||||
std::string custom_data;
|
||||
uint32 ornamenticon{};
|
||||
uint32 ornamentidfile{};
|
||||
uint32 ornament_hero_model{};
|
||||
uint16 trivial_min_level;
|
||||
uint16 trivial_max_level;
|
||||
uint16 npc_min_level;
|
||||
uint16 npc_max_level;
|
||||
};
|
||||
|
||||
typedef std::list<LootItem*> LootItems;
|
||||
|
||||
|
||||
#endif //CODE_LOOT_H
|
||||
@@ -0,0 +1,68 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2013 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef _EQEMU_LOOTTABLE_H
|
||||
#define _EQEMU_LOOTTABLE_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#pragma pack(1)
|
||||
struct LootTableEntries_Struct {
|
||||
uint32 lootdrop_id;
|
||||
uint8 droplimit;
|
||||
uint8 mindrop;
|
||||
uint8 multiplier;
|
||||
float probability;
|
||||
};
|
||||
|
||||
struct ContentFlags {
|
||||
int16 min_expansion;
|
||||
int16 max_expansion;
|
||||
char content_flags[100];
|
||||
char content_flags_disabled[100];
|
||||
};
|
||||
|
||||
struct LootTable_Struct {
|
||||
uint32 mincash;
|
||||
uint32 maxcash;
|
||||
uint32 avgcoin;
|
||||
uint32 NumEntries;
|
||||
ContentFlags content_flags;
|
||||
LootTableEntries_Struct Entries[0];
|
||||
};
|
||||
|
||||
struct LootDropEntries_Struct {
|
||||
uint32 item_id;
|
||||
int8 item_charges;
|
||||
uint8 equip_item;
|
||||
float chance;
|
||||
uint16 trivial_min_level;
|
||||
uint16 trivial_max_level;
|
||||
uint16 npc_min_level;
|
||||
uint16 npc_max_level;
|
||||
uint8 multiplier;
|
||||
};
|
||||
|
||||
struct LootDrop_Struct {
|
||||
uint32 NumEntries;
|
||||
ContentFlags content_flags;
|
||||
LootDropEntries_Struct Entries[0];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
|
||||
|
||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -41,7 +41,7 @@ namespace EQ
|
||||
MemoryBuffer& operator+=(const MemoryBuffer &rhs);
|
||||
friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; }
|
||||
~MemoryBuffer();
|
||||
|
||||
|
||||
uchar& operator[](size_t pos);
|
||||
const uchar& operator[](size_t pos) const;
|
||||
|
||||
@@ -64,20 +64,20 @@ namespace EQ
|
||||
size_t Size() const;
|
||||
size_t Capacity();
|
||||
size_t Capacity() const;
|
||||
|
||||
|
||||
void Resize(size_t sz);
|
||||
void Clear();
|
||||
void Zero();
|
||||
|
||||
template<typename T>
|
||||
void Write(T val) {
|
||||
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
|
||||
static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
|
||||
Write((const char*)&val, sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Read() {
|
||||
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
|
||||
static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
|
||||
T temp;
|
||||
Read((uchar*)&temp, sizeof(T));
|
||||
return temp;
|
||||
@@ -102,7 +102,7 @@ namespace EQ
|
||||
read_pos_ += len + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Write(const char *val, size_t len);
|
||||
void Read(uchar *buf, size_t len);
|
||||
void Read(char *str);
|
||||
@@ -113,7 +113,7 @@ namespace EQ
|
||||
inline size_t GetReadPosition() { return read_pos_; }
|
||||
inline void SetReadPosition(size_t rp) { read_pos_ = rp; }
|
||||
inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; }
|
||||
|
||||
|
||||
private:
|
||||
uchar *buffer_;
|
||||
size_t size_;
|
||||
|
||||
+118
-2
@@ -18,7 +18,6 @@
|
||||
#include "misc.h"
|
||||
#include "types.h"
|
||||
#include <cstring>
|
||||
#include "strings.h"
|
||||
|
||||
std::map<int,std::string> DBFieldNames;
|
||||
|
||||
@@ -151,7 +150,7 @@ static char *temp=nullptr;
|
||||
return false;
|
||||
}
|
||||
ptr++;
|
||||
uint32 id = Strings::ToUnsignedInt(field[id_pos]);
|
||||
uint32 id = atoi(field[id_pos].c_str());
|
||||
items[id]=field;
|
||||
|
||||
for(i=0;i<10;i++) {
|
||||
@@ -214,6 +213,123 @@ std::string x;
|
||||
return i;
|
||||
}
|
||||
|
||||
void LoadItemDBFieldNames() {
|
||||
DBFieldNames[0]="N/A"; // Charges
|
||||
DBFieldNames[1]="unknown002"; // ?
|
||||
DBFieldNames[2]="N/A"; // Current Equip Slot
|
||||
DBFieldNames[3]="unknown004";
|
||||
DBFieldNames[4]="unknown005"; // ?
|
||||
DBFieldNames[5]="itemclass"; // "Item Type (0=common, 1=container, 2=book)"
|
||||
DBFieldNames[6]="name"; // Name
|
||||
DBFieldNames[7]="lore"; // "Lore Name (*=lore, &=summoned, #=artifact)"
|
||||
DBFieldNames[8]="idfile"; // IDFile
|
||||
DBFieldNames[9]="id"; // ItemNumber
|
||||
DBFieldNames[10]="weight"; // Weight
|
||||
DBFieldNames[11]="norent"; // "NoRent (0=norent, 255=not norent)"
|
||||
DBFieldNames[12]="nodrop"; // "NoDrop (0=nodrop, 255=not nodrop)"
|
||||
DBFieldNames[13]="size"; // "Size (0=tiny, 1=small, 2=medium, 3=large, 4=giant)"
|
||||
DBFieldNames[14]="slots"; // EquipSlots
|
||||
DBFieldNames[15]="cost"; // Cost
|
||||
DBFieldNames[16]="icon"; // IconNumber
|
||||
DBFieldNames[17]="unknown018";
|
||||
DBFieldNames[18]="unknown019";
|
||||
DBFieldNames[19]="unknown020"; // ?
|
||||
DBFieldNames[20]="tradeskills"; // "Tradeskill Item (1=is a tradeskill item, 0=not)"
|
||||
DBFieldNames[21]="cr"; // SvCold
|
||||
DBFieldNames[22]="dr"; // SvDisease
|
||||
DBFieldNames[23]="pr"; // SvPoison
|
||||
DBFieldNames[24]="mr"; // SvMagic
|
||||
DBFieldNames[25]="fr"; // SvFire
|
||||
DBFieldNames[26]="astr"; // STR
|
||||
DBFieldNames[27]="asta"; // STA
|
||||
DBFieldNames[28]="aagi"; // AGI
|
||||
DBFieldNames[29]="adex"; // DEX
|
||||
DBFieldNames[30]="acha"; // CHA
|
||||
DBFieldNames[31]="aint"; // INT
|
||||
DBFieldNames[32]="awis"; // WIS
|
||||
DBFieldNames[33]="hp"; // HP
|
||||
DBFieldNames[34]="mana"; // Mana
|
||||
DBFieldNames[35]="ac"; // AC
|
||||
DBFieldNames[36]="deity"; // Deity
|
||||
DBFieldNames[37]="skillmodvalue"; // Skill Mod Value
|
||||
DBFieldNames[38]="skillmodtype"; // Skill Mod Type
|
||||
DBFieldNames[39]="banedmgrace"; // Bane Dmg Race
|
||||
DBFieldNames[40]="banedmgamt"; // Band Dmg
|
||||
DBFieldNames[41]="banedmgbody"; // Band Dmg Body
|
||||
DBFieldNames[42]="magic"; // "Magic (0=not magic, 1=magic)"
|
||||
DBFieldNames[43]="casttime2"; // Casttime appears twice
|
||||
DBFieldNames[44]="hasteproclvl"; // "Level (Haste value, rather)"
|
||||
DBFieldNames[45]="reqlevel"; // Required Level
|
||||
DBFieldNames[46]="bardtype"; // Bard Type
|
||||
DBFieldNames[47]="bardvalue"; // Bard Type Amount
|
||||
DBFieldNames[48]="light"; // Light
|
||||
DBFieldNames[49]="delay"; // Attack Delay
|
||||
DBFieldNames[50]="reclevel"; // Recommended Level
|
||||
DBFieldNames[51]="recskill"; // Recommended Skill
|
||||
DBFieldNames[52]="elemdmgamt"; // "Elemental Dmg Type (1=magic, 2=fire, 3=cold, 4=poison, 5=disease)"
|
||||
DBFieldNames[53]="elemdmgtype"; // Elemental Dmg
|
||||
DBFieldNames[54]="effecttype"; // "Effect Type (0=combat, 1=clicky, 2=Worn, 3=Expendable charges, 4=Must Equip Clicky, 5=clicky)"
|
||||
DBFieldNames[55]="range"; // Range
|
||||
DBFieldNames[56]="damage"; // Damage
|
||||
DBFieldNames[57]="color"; // Color
|
||||
DBFieldNames[58]="classes"; // Classes
|
||||
DBFieldNames[59]="races"; // Races
|
||||
DBFieldNames[60]="unknown061";
|
||||
DBFieldNames[61]="spellid"; // SpellId
|
||||
DBFieldNames[62]="maxcharges"; // MaxCharges
|
||||
DBFieldNames[63]="itemtype"; // "Skill (ItemType: 1hs, etc)"
|
||||
DBFieldNames[64]="material"; // Material
|
||||
DBFieldNames[65]="sellrate"; // ** Sell Rate
|
||||
DBFieldNames[66]="unknown067";
|
||||
DBFieldNames[67]="casttime"; // CastTime (milliseconds)
|
||||
DBFieldNames[68]="unknown069";
|
||||
DBFieldNames[69]="unknown070"; // ?
|
||||
DBFieldNames[70]="focusid"; // Focus Effect Spell Id
|
||||
DBFieldNames[71]="combateffects"; // CombatEffects
|
||||
DBFieldNames[72]="shielding"; // Shielding
|
||||
DBFieldNames[73]="stunresist"; // StunResist
|
||||
DBFieldNames[74]="strikethrough"; // StrikeThrough
|
||||
DBFieldNames[75]="unknown076";
|
||||
DBFieldNames[76]="unknown077"; // ?
|
||||
DBFieldNames[77]="spellshield"; // Spell Shield
|
||||
DBFieldNames[78]="avoidance"; // Avoidance
|
||||
DBFieldNames[79]="accuracy"; // Accuracy
|
||||
DBFieldNames[80]="factionmod1"; // Faction Mod Index 1
|
||||
DBFieldNames[81]="factionmod2"; // Faction Mod Index 2
|
||||
DBFieldNames[82]="factionmod3"; // Faction Mod Index 3
|
||||
DBFieldNames[83]="factionmod4"; // Faction Mod Index 4
|
||||
DBFieldNames[84]="factionamt1"; // Faction Mod Value 1
|
||||
DBFieldNames[85]="factionamt2"; // Faction Mod Value 2
|
||||
DBFieldNames[86]="factionamt3"; // Faction Mod Value 3
|
||||
DBFieldNames[87]="factionamt4"; // Faction Mod Value 4
|
||||
DBFieldNames[88]="unknown089";
|
||||
DBFieldNames[89]="charmfile"; // ** Charm File
|
||||
DBFieldNames[90]="unknown091";
|
||||
DBFieldNames[91]="augslot1type"; // Slot1Type
|
||||
DBFieldNames[92]="augslot2type"; // Slot2Type
|
||||
DBFieldNames[93]="augslot3type"; // Slot3Type
|
||||
DBFieldNames[94]="augslot4type"; // Slot4Type
|
||||
DBFieldNames[95]="augslot5type"; // Slot5Type
|
||||
DBFieldNames[96]="ldonpointtheme";
|
||||
DBFieldNames[97]="ldonpointcost"; // ?
|
||||
DBFieldNames[98]="unknown099";
|
||||
DBFieldNames[99]="bagtype"; // bag type
|
||||
DBFieldNames[100]="bagslots"; // bag slots
|
||||
DBFieldNames[101]="bagsize"; // bag size capacity
|
||||
DBFieldNames[102]="bagwr"; // bag weight reduction
|
||||
DBFieldNames[103]="booktype"; // "book type (0=rolled up note, 1=book)"
|
||||
DBFieldNames[104]="unknown105";
|
||||
DBFieldNames[105]="filename"; // Book Filename
|
||||
DBFieldNames[106]="unknown107";
|
||||
DBFieldNames[107]="unknown108";
|
||||
DBFieldNames[108]="loreflag";
|
||||
DBFieldNames[109]="unknown111";
|
||||
DBFieldNames[110]="unknown112";
|
||||
DBFieldNames[111]="unknown113";
|
||||
DBFieldNames[112]="unknown114";
|
||||
DBFieldNames[113]="unknown115"; // ? (end quote)
|
||||
}
|
||||
|
||||
void dump_message_column(unsigned char *buffer, unsigned long length, std::string leader, FILE *to)
|
||||
{
|
||||
unsigned long i,j;
|
||||
|
||||
@@ -15,6 +15,8 @@ bool ItemParse(const char *data, int length, std::map<int,std::map<int,std::stri
|
||||
|
||||
int Tokenize(std::string s, std::map<int,std::string> & tokens, char delim='|');
|
||||
|
||||
void LoadItemDBFieldNames();
|
||||
|
||||
#ifndef WIN32
|
||||
int print_stacktrace();
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "misc_functions.h"
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "strings.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
@@ -131,7 +130,7 @@ bool ParseAddress(const char* iAddress, uint32* oIP, uint16* oPort, char* errbuf
|
||||
if (*oIP == 0)
|
||||
return false;
|
||||
if (oPort)
|
||||
*oPort = Strings::ToUnsignedInt(sep.arg[1]);
|
||||
*oPort = atoi(sep.arg[1]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -51,7 +51,6 @@ void MySQLRequestResult::ZeroOut()
|
||||
m_RowCount = 0;
|
||||
m_RowsAffected = 0;
|
||||
m_LastInsertedID = 0;
|
||||
m_error_message = "";
|
||||
}
|
||||
|
||||
MySQLRequestResult::~MySQLRequestResult()
|
||||
@@ -138,23 +137,3 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other)
|
||||
other.ZeroOut();
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32 MySQLRequestResult::GetErrorNumber() const
|
||||
{
|
||||
return m_ErrorNumber;
|
||||
}
|
||||
|
||||
void MySQLRequestResult::SetErrorNumber(uint32 m_error_number)
|
||||
{
|
||||
m_ErrorNumber = m_error_number;
|
||||
}
|
||||
|
||||
const std::string &MySQLRequestResult::GetErrorMessage() const
|
||||
{
|
||||
return m_error_message;
|
||||
}
|
||||
|
||||
void MySQLRequestResult::SetErrorMessage(const std::string &m_error_message)
|
||||
{
|
||||
MySQLRequestResult::m_error_message = m_error_message;
|
||||
}
|
||||
|
||||
@@ -33,42 +33,30 @@ private:
|
||||
uint32 m_LastInsertedID;
|
||||
uint32 m_ErrorNumber;
|
||||
|
||||
std::string m_error_message;
|
||||
|
||||
public:
|
||||
|
||||
MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected = 0, uint32 rowCount = 0, uint32 columnCount = 0, uint32 lastInsertedID = 0, uint32 errorNumber = 0, char *errorBuffer = nullptr);
|
||||
MySQLRequestResult();
|
||||
MySQLRequestResult();
|
||||
MySQLRequestResult(MySQLRequestResult&& moveItem);
|
||||
~MySQLRequestResult();
|
||||
|
||||
MySQLRequestResult& operator=(MySQLRequestResult&& other);
|
||||
|
||||
bool Success() const { return m_Success;}
|
||||
std::string ErrorMessage() const {
|
||||
if (!m_error_message.empty()) {
|
||||
return m_error_message;
|
||||
}
|
||||
|
||||
return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string("");
|
||||
}
|
||||
std::string ErrorMessage() const {return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string("");}
|
||||
uint32 ErrorNumber() const {return m_ErrorNumber;}
|
||||
uint32 RowsAffected() const {return m_RowsAffected;}
|
||||
uint32 RowCount() const {return m_RowCount;}
|
||||
uint32 ColumnCount() const {return m_ColumnCount;}
|
||||
uint32 LastInsertedID() const {return m_LastInsertedID;}
|
||||
// default to 0 index since we mostly use it that way anyways.
|
||||
uint32 LengthOfColumn(int columnIndex = 0);
|
||||
uint32 LengthOfColumn(int columnIndex = 0);
|
||||
const std::string FieldName(int columnIndex);
|
||||
|
||||
MySQLRequestRow& begin() { return m_CurrentRow; }
|
||||
MySQLRequestRow& end() { return m_OneBeyondRow; }
|
||||
|
||||
uint32 GetErrorNumber() const;
|
||||
void SetErrorNumber(uint32 m_error_number);
|
||||
const std::string &GetErrorMessage() const;
|
||||
void SetErrorMessage(const std::string &m_error_message);
|
||||
|
||||
private:
|
||||
void FreeInternals();
|
||||
void ZeroOut();
|
||||
|
||||
@@ -7,7 +7,7 @@ EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
|
||||
m_server = std::make_unique<EQ::Net::TCPServer>();
|
||||
m_server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
ConsoleServerConnection *c = new ConsoleServerConnection(this, connection);
|
||||
m_connections.emplace(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleServerConnection>(c)));
|
||||
m_connections.insert(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleServerConnection>(c)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user