mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
Compare commits
261 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c90f42eb8b | |||
| 5ce1fef9ec | |||
| 874ca053f7 | |||
| b8e7e5bb0d | |||
| 15f3697df1 | |||
| 16cfad1966 | |||
| bffeee8d1a | |||
| d29c0fc332 | |||
| a031c20e7e | |||
| 67d3cab80b | |||
| b41f2dac66 | |||
| b5b473f25d | |||
| 0dc3e5ba35 | |||
| 499fe153ab | |||
| d1349e5ac9 | |||
| bd8e94ff17 | |||
| d89b2f11b5 | |||
| 88ff56b2f2 | |||
| 1728923bbb | |||
| cbd1f42a08 | |||
| f8735cf9ba | |||
| eb00667eab | |||
| cbc0ada454 | |||
| 54b33f959e | |||
| c6e4b5647f | |||
| 928070e994 | |||
| 40ef4c799b | |||
| 8ba7ddd054 | |||
| 973fd376e5 | |||
| b5575133cd | |||
| 6f846dc4ff | |||
| 0461fc1789 | |||
| aa6264266e | |||
| c3cbe90575 | |||
| c2c6282cc7 | |||
| fab071d9da | |||
| 358bd60716 | |||
| 03ca345b37 | |||
| 6ddcc2bb8a | |||
| 02cac686b6 | |||
| 4c348baabd | |||
| 035bac1044 | |||
| 5a8d467d25 | |||
| ae959be5ac | |||
| 4157a03f32 | |||
| 41d0b1a947 | |||
| 3c71e2c91d | |||
| 80d1601754 | |||
| cfcbfea3ab | |||
| 7aa8db76f4 | |||
| 561433902e | |||
| abeb93f1e6 | |||
| ef0b29dc8e | |||
| 42f959329d | |||
| a898a1d07b | |||
| 803c3aabe4 | |||
| 15dde4778a | |||
| f2b68e6783 | |||
| 8193b04627 | |||
| 47e56f9381 | |||
| 58b9b719f4 | |||
| a4bf484c74 | |||
| 4712b56078 | |||
| 9362890d26 | |||
| 6d3848b2c7 | |||
| 8974059577 | |||
| 963735e7dd | |||
| c94a2496ca | |||
| ceb8b31bc0 | |||
| 51b31b5e53 | |||
| 6fb6d8891d | |||
| d4ea9bbee0 | |||
| 3a7908b1de | |||
| 99c1c826a8 | |||
| 1b888784eb | |||
| 52a25c3b78 | |||
| 4b08ce1237 | |||
| b94fdda429 | |||
| a48153baa1 | |||
| e26b159efe | |||
| a2b381bc9e | |||
| 60e194e32b | |||
| 1cdf507b9f | |||
| 3e98e60877 | |||
| af5022b3db | |||
| 52d2469da2 | |||
| e431c56f7c | |||
| 0ab7291625 | |||
| e384cf6149 | |||
| 463c0d9e0e | |||
| 0f92287c02 | |||
| 6a61fd5df9 | |||
| dac7541d89 | |||
| e7266943e2 | |||
| 7f25f8a235 | |||
| 240d5c2a66 | |||
| 785804a936 | |||
| e451dad94e | |||
| 08414bda55 | |||
| c39978d3d8 | |||
| f3d8271066 | |||
| 431a325414 | |||
| c42d6dcd1b | |||
| fa12b146a3 | |||
| e7fab67d8a | |||
| 6438a37fb5 | |||
| 899e2d3397 | |||
| 53be04c39c | |||
| bfecd6ad14 | |||
| dd1470892d | |||
| d4a1ea82dc | |||
| 8d252dfd9a | |||
| 1577f2823b | |||
| cede38f562 | |||
| 201757567c | |||
| 2a9248697e | |||
| 3708efd8df | |||
| 1d907564e9 | |||
| 1b15ee141d | |||
| d838ac9582 | |||
| dce5dea609 | |||
| 581d5b1289 | |||
| 4915e86aba | |||
| 09e9c0b504 | |||
| a3eb74b855 | |||
| fb396e9f60 | |||
| d85469dff9 | |||
| 3f7ce5df72 | |||
| d5b3dc7c0a | |||
| ac3b4ade10 | |||
| 482584f95a | |||
| 57e7b4a2b8 | |||
| 7f6414d685 | |||
| 81e91d7956 | |||
| 3875485567 | |||
| eb104e40de | |||
| bec33e22da | |||
| ac104ed4e0 | |||
| 0ffb5c46a5 | |||
| 92638504db | |||
| 08002eacea | |||
| 79248cffec | |||
| 8787f51b58 | |||
| 69f4d90737 | |||
| 1371e1e7ed | |||
| 81ff7f5d57 | |||
| 8376ed5d3f | |||
| fe4a0cfdba | |||
| 0043f56984 | |||
| 6ddc5ea8e8 | |||
| be38a62d70 | |||
| fdc38315d3 | |||
| e7c000813f | |||
| 6fb0042e3f | |||
| 0a4429c0c0 | |||
| a63dc7d5e0 | |||
| 67449de27e | |||
| 10e5f0e949 | |||
| 141ecca2bc | |||
| bd4fa4fb6b | |||
| 5901df4485 | |||
| 8cda4257b4 | |||
| 709a25ba9e | |||
| ed09d4ae54 | |||
| 952fd43301 | |||
| 5f8d193d6a | |||
| a4a70cf225 | |||
| 29fccd9239 | |||
| cdc82f0ba7 | |||
| 78756f27b6 | |||
| 2f5909d4cb | |||
| 13c2df7eb1 | |||
| 16ac6f624b | |||
| 501204a4d2 | |||
| 8bcef6c2e7 | |||
| 2db47adf7b | |||
| 916c88939c | |||
| 1528e7cb09 | |||
| 8dacadb4f9 | |||
| e19db3b7f4 | |||
| e1adffc4be | |||
| 7eb71c5902 | |||
| da397606b6 | |||
| 6b27e88315 | |||
| 4accb4ea2a | |||
| c419df52ff | |||
| 46ff09f438 | |||
| b4f42c150f | |||
| 49134644bc | |||
| 861b879a94 | |||
| 929e4c1317 | |||
| 138cb80b19 | |||
| 86b6f543b9 | |||
| d7138e84c0 | |||
| 2d24cdf5e4 | |||
| 4416e774c2 | |||
| 342012c4f4 | |||
| 34005cd2ed | |||
| 6bc6b659d5 | |||
| ad1f18306b | |||
| 6a984a53b5 | |||
| f9b3b7aecf | |||
| 5fefdfcc17 | |||
| 00f118cfb4 | |||
| a7633f4ddf | |||
| f742d6427b | |||
| d65a97e556 | |||
| b8229c8459 | |||
| 424b669cbb | |||
| e09b0ae1e9 | |||
| c2300d514c | |||
| f195820854 | |||
| 59903313e4 | |||
| b351d3718a | |||
| ab3d65b2ea | |||
| b02e87cce7 | |||
| 50a39057e4 | |||
| c8e6d031cf | |||
| 158d8a011f | |||
| 14c070f845 | |||
| 6dee837f67 | |||
| 83ad9c86db | |||
| bcb08f99f0 | |||
| f968d0df4c | |||
| 712366293d | |||
| 9689787e56 | |||
| 92d32feb0d | |||
| 371265d143 | |||
| 43da07fb55 | |||
| f880663528 | |||
| 63b8df72b2 | |||
| c82d08cf11 | |||
| c6ba29f2e5 | |||
| 6514ccc41c | |||
| 2f49266d08 | |||
| ff897dc90a | |||
| f73f72b2b2 | |||
| c2b3e85272 | |||
| c590cf7c35 | |||
| 453bee511a | |||
| 1baeb01e65 | |||
| 8b37ef5e67 | |||
| caceae1028 | |||
| 8e6dd638ff | |||
| 51fb7d8b77 | |||
| f6ed4bb888 | |||
| 9cc73f2b4a | |||
| 6f73278cf8 | |||
| 6c91786cfb | |||
| 8eb60302a2 | |||
| 43df845233 | |||
| feefd7a23b | |||
| 5a1eac010b | |||
| d47bf6a73b | |||
| 6da0f84e18 | |||
| b2dd3df1e2 | |||
| 3ec500244e | |||
| 4425e3ab49 | |||
| 413c006785 | |||
| ae3052fbd1 | |||
| 8be23a1214 |
@@ -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}"
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -17,6 +17,8 @@
|
|||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
.bash_history
|
||||||
|
|
||||||
# CMake
|
# CMake
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
CMakeFiles
|
CMakeFiles
|
||||||
@@ -36,3 +38,19 @@ submodules/*
|
|||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
|
|
||||||
.nfs.*
|
.nfs.*
|
||||||
|
|
||||||
|
# Visual Studio and CMAKE Generated Files
|
||||||
|
/.vs/
|
||||||
|
*.vcxproj
|
||||||
|
*.vcxproj.filters
|
||||||
|
*.vcxproj.user
|
||||||
|
*.cmake
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.dir/
|
||||||
|
libs/
|
||||||
|
bin/
|
||||||
|
/Win32
|
||||||
|
/x64
|
||||||
|
/client_files/**/CMakeFiles/
|
||||||
|
|||||||
@@ -16,3 +16,6 @@
|
|||||||
[submodule "submodules/recastnavigation"]
|
[submodule "submodules/recastnavigation"]
|
||||||
path = submodules/recastnavigation
|
path = submodules/recastnavigation
|
||||||
url = https://github.com/EQEmu/recastnavigation.git
|
url = https://github.com/EQEmu/recastnavigation.git
|
||||||
|
[submodule "submodules/expected"]
|
||||||
|
path = submodules/expected
|
||||||
|
url = https://github.com/TartanLlama/expected.git
|
||||||
|
|||||||
+11
-19
@@ -1,26 +1,18 @@
|
|||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
dist: trusty
|
dist: bionic
|
||||||
|
|
||||||
before_install:
|
addons:
|
||||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
apt:
|
||||||
- sudo apt-get update -qq
|
packages:
|
||||||
- mkdir $HOME/usr
|
- libmysqlclient-dev
|
||||||
- export PATH="$HOME/usr/bin:$PATH"
|
- libperl-dev
|
||||||
- wget https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.sh
|
- libboost-dev
|
||||||
- chmod +x cmake-3.11.2-Linux-x86_64.sh
|
- liblua5.1-0-dev
|
||||||
- ./cmake-3.11.2-Linux-x86_64.sh --prefix=$HOME/usr --exclude-subdir --skip-license
|
- zlib1g-dev
|
||||||
|
- uuid-dev
|
||||||
|
- libssl-dev
|
||||||
|
|
||||||
install:
|
|
||||||
- sudo apt-get install -qq g++-7
|
|
||||||
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 90
|
|
||||||
- sudo apt-get install libmysqlclient-dev
|
|
||||||
- sudo apt-get install libperl-dev
|
|
||||||
- sudo apt-get install libboost-dev
|
|
||||||
- sudo apt-get install liblua5.1-0-dev
|
|
||||||
- sudo apt-get install zlib1g-dev
|
|
||||||
- sudo apt-get install uuid-dev
|
|
||||||
- sudo apt-get install libssl-dev
|
|
||||||
script:
|
script:
|
||||||
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
|
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
|
||||||
- make -j2
|
- make -j2
|
||||||
|
|||||||
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
+155
@@ -0,0 +1,155 @@
|
|||||||
|
{
|
||||||
|
// 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 build && make",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "make clean",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "cd build && make clean",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "cmake",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mkdir -p build && cd build && rm CMakeCache.txt && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' ..",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher":{
|
||||||
|
"owner": "cpp",
|
||||||
|
"fileLocation": "relative",
|
||||||
|
"pattern":[
|
||||||
|
{
|
||||||
|
"regexp": "([\\w+|\\\\]*\\.\\w+)\\((\\d+)\\)\\: (warning|error) (.*)$",
|
||||||
|
"file": 1,
|
||||||
|
"location": 2,
|
||||||
|
"severity": 3,
|
||||||
|
"message": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "download maps",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mkdir -p build/bin && cd build/bin && wget https://codeload.github.com/Akkadius/EQEmuMaps/zip/master -O maps.zip && unzip -o maps.zip && rm ./maps -rf && mv EQEmuMaps-master maps && rm maps.zip",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "download quests",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mkdir -p build/bin && cd build/bin && cd server && git -C ./quests pull 2> /dev/null || git clone https://github.com/ProjectEQ/projecteqquests.git quests",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "download eqemu_config",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mkdir -p build/bin && cd build/bin && wget --no-check-certificate https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/eqemu_config_docker.json -O eqemu_config.json",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "rebuild database (mariadb must be started)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mkdir -p build/bin && cd build/bin && docker run -i --rm --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --network=eqemu -it eqemu/server:0.0.3 bash -c './eqemu_server.pl source_peq_db && ./eqemu_server.pl check_db_updates && ./eqemu_server.pl linux_login_server_setup'",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "zone 7000",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker stop zone7000 | true && docker network create eqemu | true && docker run -i --rm --name zone7000 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu -p 7000:7000/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7000:7000",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "zone 7001",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker stop zone7001 | true && docker network create eqemu | true && docker run -i --rm --name zone7001 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu -p 7001:7001/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7001:7001",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "loginserver",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker stop loginserver | true && docker network create eqemu | true && docker run -i --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu --name loginserver -p 5999:5999/udp -p 5998:5998/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./loginserver",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "shared_memory, world",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker stop sharedmemory | true && docker stop world | true && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --network=eqemu --name sharedmemory eqemu/server:0.0.3 ./shared_memory && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name world -p 9000:9000 -p 9000:9000/udp -p 9001:9001 -p 9080:9080 eqemu/server:0.0.3 gdb -ex run ./world",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "queryserv",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker stop queryserv | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name queryserv eqemu/server:0.0.3 gdb -ex run ./queryserv",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "mariadb",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker stop mariadb | true && cd build/bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin/db:/bitnami/mariadb -p 3306:3306 -e MARIADB_DATABASE=peq -e MARIADB_USER=eqemu -e MARIADB_PASSWORD=eqemupass -e ALLOW_EMPTY_PASSWORD=yes --name mariadb --network=eqemu bitnami/mariadb:latest",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -270,6 +270,7 @@ INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_LIBRARY_INCLUDE}")
|
|||||||
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
|
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
|
||||||
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/expected/include")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/libuv/include" )
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/libuv/include" )
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# EQEmulator Core Server
|
# EQEmulator Core Server
|
||||||
|Travis CI (Linux)|Appveyor w/ Bots (Windows) |Appveyor w/o Bots (Windows) |
|
|Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) |
|
||||||
|:---:|:---:|:---:|
|
|:---:|:---:|:---:|
|
||||||
|[](https://travis-ci.org/EQEmu/Server) |[](https://ci.appveyor.com/project/KimLS/server-87crp/branch/master) |[](https://ci.appveyor.com/project/KimLS/server-w0pq2/branch/master) |
|
|[](https://travis-ci.org/EQEmu/Server) |[](https://ci.appveyor.com/project/KimLS/server) |[](https://ci.appveyor.com/project/KimLS/server-87crp) |
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|:---:|:---:|:---:|
|
|:---:|:---:|:---:|
|
||||||
|**Install Count**|||
|
|**Install Count**|||
|
||||||
### > Windows
|
### > Windows
|
||||||
* [Install](https://github.com/EQEmu/Server/wiki/Windows-Server)
|
* [Install](https://eqemu.gitbook.io/server/categories/how-to-guides/installation/server-installation-windows)
|
||||||
|
|
||||||
### > Debian/Ubuntu/CentOS/Fedora
|
### > Debian/Ubuntu/CentOS/Fedora
|
||||||
* You can use curl or wget to kick off the installer (whichever your OS has)
|
* You can use curl or wget to kick off the installer (whichever your OS has)
|
||||||
@@ -52,7 +52,7 @@ forum, although pull requests will be much quicker and easier on all parties.
|
|||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
- [EQEmulator Forums](http://www.eqemulator.org/forums)
|
- [EQEmulator Forums](http://www.eqemulator.org/forums)
|
||||||
- [EQEmulator Wiki](https://github.com/EQEmu/Server/wiki)
|
- [EQEmulator Wiki](https://eqemu.gitbook.io/)
|
||||||
|
|
||||||
## Related Repositories
|
## Related Repositories
|
||||||
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
|
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
|
||||||
|
|||||||
+22
-3
@@ -9,6 +9,7 @@ SET(common_sources
|
|||||||
crash.cpp
|
crash.cpp
|
||||||
crc16.cpp
|
crc16.cpp
|
||||||
crc32.cpp
|
crc32.cpp
|
||||||
|
database/database_dump_service.cpp
|
||||||
database.cpp
|
database.cpp
|
||||||
database_conversions.cpp
|
database_conversions.cpp
|
||||||
database_instances.cpp
|
database_instances.cpp
|
||||||
@@ -31,6 +32,7 @@ SET(common_sources
|
|||||||
event_sub.cpp
|
event_sub.cpp
|
||||||
extprofile.cpp
|
extprofile.cpp
|
||||||
faction.cpp
|
faction.cpp
|
||||||
|
file_util.cpp
|
||||||
guild_base.cpp
|
guild_base.cpp
|
||||||
guilds.cpp
|
guilds.cpp
|
||||||
inventory_profile.cpp
|
inventory_profile.cpp
|
||||||
@@ -44,7 +46,6 @@ SET(common_sources
|
|||||||
md5.cpp
|
md5.cpp
|
||||||
memory_buffer.cpp
|
memory_buffer.cpp
|
||||||
memory_mapped_file.cpp
|
memory_mapped_file.cpp
|
||||||
metric_manager.cpp
|
|
||||||
misc.cpp
|
misc.cpp
|
||||||
misc_functions.cpp
|
misc_functions.cpp
|
||||||
mutex.cpp
|
mutex.cpp
|
||||||
@@ -121,6 +122,7 @@ SET(common_headers
|
|||||||
cli/argh.h
|
cli/argh.h
|
||||||
cli/eqemu_command_handler.h
|
cli/eqemu_command_handler.h
|
||||||
cli/terminal_color.hpp
|
cli/terminal_color.hpp
|
||||||
|
database/database_dump_service.h
|
||||||
data_verification.h
|
data_verification.h
|
||||||
database.h
|
database.h
|
||||||
database_schema.h
|
database_schema.h
|
||||||
@@ -149,8 +151,10 @@ SET(common_headers
|
|||||||
eqtime.h
|
eqtime.h
|
||||||
errmsg.h
|
errmsg.h
|
||||||
event_sub.h
|
event_sub.h
|
||||||
|
expected.h
|
||||||
extprofile.h
|
extprofile.h
|
||||||
faction.h
|
faction.h
|
||||||
|
file_util.h
|
||||||
features.h
|
features.h
|
||||||
fixed_memory_hash_set.h
|
fixed_memory_hash_set.h
|
||||||
fixed_memory_variable_hash_set.h
|
fixed_memory_variable_hash_set.h
|
||||||
@@ -174,8 +178,6 @@ SET(common_headers
|
|||||||
md5.h
|
md5.h
|
||||||
memory_buffer.h
|
memory_buffer.h
|
||||||
memory_mapped_file.h
|
memory_mapped_file.h
|
||||||
metric_event.h
|
|
||||||
metric_manager.h
|
|
||||||
misc.h
|
misc.h
|
||||||
misc_functions.h
|
misc_functions.h
|
||||||
mutex.h
|
mutex.h
|
||||||
@@ -266,6 +268,13 @@ SET(common_headers
|
|||||||
patches/uf_limits.h
|
patches/uf_limits.h
|
||||||
patches/uf_ops.h
|
patches/uf_ops.h
|
||||||
patches/uf_structs.h
|
patches/uf_structs.h
|
||||||
|
shared/shared_memory.h
|
||||||
|
shared/shared_memory_error.h
|
||||||
|
shared/shared_memory_handle.h
|
||||||
|
shared/shared_memory_list.h
|
||||||
|
shared/shared_memory_map.h
|
||||||
|
shared/shared_memory_string.h
|
||||||
|
shared/shared_memory_vector.h
|
||||||
StackWalker/StackWalker.h
|
StackWalker/StackWalker.h
|
||||||
util/memory_stream.h
|
util/memory_stream.h
|
||||||
util/directory.h
|
util/directory.h
|
||||||
@@ -364,6 +373,16 @@ SOURCE_GROUP(Patches FILES
|
|||||||
patches/uf_limits.cpp
|
patches/uf_limits.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SOURCE_GROUP(shared FILES
|
||||||
|
shared/shared_memory.h
|
||||||
|
shared/shared_memory_error.h
|
||||||
|
shared/shared_memory_handle.h
|
||||||
|
shared/shared_memory_list.h
|
||||||
|
shared/shared_memory_map.h
|
||||||
|
shared/shared_memory_string.h
|
||||||
|
shared/shared_memory_vector.h
|
||||||
|
)
|
||||||
|
|
||||||
SOURCE_GROUP(StackWalker FILES
|
SOURCE_GROUP(StackWalker FILES
|
||||||
StackWalker/StackWalker.h
|
StackWalker/StackWalker.h
|
||||||
StackWalker/StackWalker.cpp
|
StackWalker/StackWalker.cpp
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ namespace EQEmuCommand {
|
|||||||
"\nCommand" <<
|
"\nCommand" <<
|
||||||
termcolor::reset << "\n\n" <<
|
termcolor::reset << "\n\n" <<
|
||||||
termcolor::green << argv[1] << arguments_string << termcolor::reset << "\n" <<
|
termcolor::green << argv[1] << arguments_string << termcolor::reset << "\n" <<
|
||||||
termcolor::yellow << (!options_string.empty() ? "\nOptions\n" : "") <<
|
termcolor::yellow << (!options_string.empty() ? "\nOptions\n\n" : "") <<
|
||||||
termcolor::reset << termcolor::cyan << options_string << termcolor::reset;
|
termcolor::reset << termcolor::cyan << options_string << termcolor::reset;
|
||||||
|
|
||||||
std::cout << command_string.str() << std::endl;
|
std::cout << command_string.str() << std::endl;
|
||||||
|
|||||||
+97
-37
@@ -45,6 +45,7 @@
|
|||||||
#include "eq_packet_structs.h"
|
#include "eq_packet_structs.h"
|
||||||
#include "extprofile.h"
|
#include "extprofile.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
|
#include "database_schema.h"
|
||||||
|
|
||||||
extern Client client;
|
extern Client client;
|
||||||
|
|
||||||
@@ -338,6 +339,21 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
|||||||
query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name);
|
query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name);
|
||||||
results = QueryDatabase(query);
|
results = QueryDatabase(query);
|
||||||
if (!results.Success() || results.ErrorMessage() != ""){ return false; }
|
if (!results.Success() || results.ErrorMessage() != ""){ return false; }
|
||||||
|
|
||||||
|
// Put character into the default guild if rule is being used.
|
||||||
|
int guild_id = RuleI(Character, DefaultGuild);
|
||||||
|
|
||||||
|
if (guild_id != 0) {
|
||||||
|
int character_id=results.LastInsertedID();
|
||||||
|
if (character_id > -1) {
|
||||||
|
query = StringFormat("INSERT INTO `guild_members` SET `char_id` = %i, `guild_id` = '%i'", character_id, guild_id);
|
||||||
|
results = QueryDatabase(query);
|
||||||
|
if (!results.Success() || results.ErrorMessage() != ""){
|
||||||
|
LogInfo("Could not put character [{}] into default Guild", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,6 +387,7 @@ bool Database::DeleteCharacter(char *character_name) {
|
|||||||
UPDATE
|
UPDATE
|
||||||
character_data
|
character_data
|
||||||
SET
|
SET
|
||||||
|
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64),
|
||||||
deleted_at = NOW()
|
deleted_at = NOW()
|
||||||
WHERE
|
WHERE
|
||||||
id = '{}'
|
id = '{}'
|
||||||
@@ -385,46 +402,18 @@ bool Database::DeleteCharacter(char *character_name) {
|
|||||||
|
|
||||||
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
|
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
|
||||||
|
|
||||||
query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
for (const auto& iter : DatabaseSchema::GetCharacterTables()) {
|
||||||
query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
std::string table_name = iter.first;
|
||||||
query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
std::string character_id_column_name = iter.second;
|
||||||
query = StringFormat("DELETE FROM `character_tasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id));
|
||||||
query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
}
|
||||||
query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", character_id); QueryDatabase(query);
|
|
||||||
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
|
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
|
||||||
#else
|
|
||||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", character_id);
|
|
||||||
#endif
|
|
||||||
QueryDatabase(query);
|
QueryDatabase(query);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -936,6 +925,38 @@ void Database::GetCharName(uint32 char_id, char* name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* Database::GetCharNameByID(uint32 char_id) {
|
||||||
|
std::string query = fmt::format("SELECT `name` FROM `character_data` WHERE id = {}", char_id);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.RowCount() == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
return row[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Database::GetNPCNameByID(uint32 npc_id) {
|
||||||
|
std::string query = fmt::format("SELECT `name` FROM `npc_types` WHERE id = {}", npc_id);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.RowCount() == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
return row[0];
|
||||||
|
}
|
||||||
|
|
||||||
bool Database::LoadVariables() {
|
bool Database::LoadVariables() {
|
||||||
auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache.last_update));
|
auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache.last_update));
|
||||||
|
|
||||||
@@ -2169,6 +2190,44 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
|
|||||||
return atoi(row[0]);
|
return atoi(row[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 Database::GetGroupIDByCharID(uint32 character_id)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(
|
||||||
|
SQL(
|
||||||
|
SELECT groupid
|
||||||
|
FROM group_id
|
||||||
|
WHERE charid = '{}'
|
||||||
|
),
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Database::GetRaidIDByCharID(uint32 character_id) {
|
||||||
|
std::string query = fmt::format(
|
||||||
|
SQL(
|
||||||
|
SELECT raidid
|
||||||
|
FROM raid_members
|
||||||
|
WHERE charid = '{}'
|
||||||
|
),
|
||||||
|
character_id
|
||||||
|
);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
return atoi(row[0]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param log_settings
|
* @param log_settings
|
||||||
*/
|
*/
|
||||||
@@ -2346,3 +2405,4 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,9 +133,13 @@ public:
|
|||||||
uint32 GetCharacterID(const char *name);
|
uint32 GetCharacterID(const char *name);
|
||||||
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
|
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
|
||||||
uint32 GetGuildIDByCharID(uint32 char_id);
|
uint32 GetGuildIDByCharID(uint32 char_id);
|
||||||
|
uint32 GetGroupIDByCharID(uint32 char_id);
|
||||||
|
uint32 GetRaidIDByCharID(uint32 char_id);
|
||||||
|
|
||||||
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
|
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
|
||||||
void GetCharName(uint32 char_id, char* name);
|
void GetCharName(uint32 char_id, char* name);
|
||||||
|
const char *GetCharNameByID(uint32 char_id);
|
||||||
|
const char *GetNPCNameByID(uint32 npc_id);
|
||||||
void LoginIP(uint32 AccountID, const char* LoginIP);
|
void LoginIP(uint32 AccountID, const char* LoginIP);
|
||||||
|
|
||||||
/* Instancing */
|
/* Instancing */
|
||||||
|
|||||||
@@ -0,0 +1,569 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iterator>
|
||||||
|
#include "database_dump_service.h"
|
||||||
|
#include "../eqemu_logsys.h"
|
||||||
|
#include "../string_util.h"
|
||||||
|
#include "../eqemu_config.h"
|
||||||
|
#include "../database_schema.h"
|
||||||
|
#include "../file_util.h"
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
*/
|
||||||
|
bool DatabaseDumpService::IsMySQLInstalled()
|
||||||
|
{
|
||||||
|
std::string version_output = GetMySQLVersion();
|
||||||
|
|
||||||
|
return version_output.find("mysql") != std::string::npos && version_output.find("Ver") != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Linux
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
bool DatabaseDumpService::IsTarAvailable()
|
||||||
|
{
|
||||||
|
std::string version_output = execute("tar --version");
|
||||||
|
|
||||||
|
return version_output.find("GNU tar") != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
bool DatabaseDumpService::Is7ZipAvailable()
|
||||||
|
{
|
||||||
|
std::string version_output = execute("7z --help");
|
||||||
|
|
||||||
|
return version_output.find("7-Zip") != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool DatabaseDumpService::HasCompressionBinary()
|
||||||
|
{
|
||||||
|
return IsTarAvailable() || Is7ZipAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetMySQLVersion()
|
||||||
|
{
|
||||||
|
std::string version_output = execute("mysql --version");
|
||||||
|
|
||||||
|
return trim(version_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
|
||||||
|
{
|
||||||
|
auto config = EQEmuConfig::get();
|
||||||
|
|
||||||
|
return fmt::format(
|
||||||
|
"mysqldump -u {} -p{} -h {} {}",
|
||||||
|
config->DatabaseUsername,
|
||||||
|
config->DatabasePassword,
|
||||||
|
config->DatabaseHost,
|
||||||
|
config->DatabaseDB
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetPlayerTablesList()
|
||||||
|
{
|
||||||
|
std::string tables_list;
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetPlayerTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetLoginTableList()
|
||||||
|
{
|
||||||
|
std::string tables_list;
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetLoginTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetQueryServTables()
|
||||||
|
{
|
||||||
|
std::string tables_list;
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetQueryServerTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetSystemTablesList()
|
||||||
|
{
|
||||||
|
std::string tables_list;
|
||||||
|
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetServerTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
tables = DatabaseSchema::GetVersionTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetStateTablesList()
|
||||||
|
{
|
||||||
|
std::string tables_list;
|
||||||
|
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetStateTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetContentTablesList()
|
||||||
|
{
|
||||||
|
std::string tables_list;
|
||||||
|
|
||||||
|
std::vector<std::string> tables = DatabaseSchema::GetContentTables();
|
||||||
|
for (const auto &table : tables) {
|
||||||
|
tables_list += table + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(tables_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string GetDumpDate()
|
||||||
|
{
|
||||||
|
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
struct tm time_struct{};
|
||||||
|
char buf[80];
|
||||||
|
time_struct = *localtime(&now);
|
||||||
|
strftime(buf, sizeof(buf), "%Y-%m-%d", &time_struct);
|
||||||
|
|
||||||
|
std::string time = buf;
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetSetDumpPath()
|
||||||
|
{
|
||||||
|
return !GetDumpPath().empty() ? GetDumpPath() : DATABASE_DUMP_PATH;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string DatabaseDumpService::GetDumpFileNameWithPath()
|
||||||
|
{
|
||||||
|
return GetSetDumpPath() + GetDumpFileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::Dump()
|
||||||
|
{
|
||||||
|
if (!IsMySQLInstalled()) {
|
||||||
|
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpDropTableSyntaxOnly()) {
|
||||||
|
SetDumpOutputToConsole(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpOutputToConsole()) {
|
||||||
|
LogSys.SilenceConsoleLogging();
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("MySQL installed [{}]", GetMySQLVersion());
|
||||||
|
|
||||||
|
SetDumpFileName(EQEmuConfig::get()->DatabaseDB + '-' + GetDumpDate());
|
||||||
|
|
||||||
|
auto config = EQEmuConfig::get();
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Database [{}] Host [{}] Username [{}]",
|
||||||
|
config->DatabaseDB,
|
||||||
|
config->DatabaseHost,
|
||||||
|
config->DatabaseUsername
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string options = "--allow-keywords --extended-insert";
|
||||||
|
|
||||||
|
if (IsDumpWithNoData()) {
|
||||||
|
options += " --no-data";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsDumpTableLock()) {
|
||||||
|
options += " --skip-lock-tables";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tables_to_dump;
|
||||||
|
std::string dump_descriptor;
|
||||||
|
|
||||||
|
if (!IsDumpAllTables()) {
|
||||||
|
if (IsDumpPlayerTables()) {
|
||||||
|
tables_to_dump += GetPlayerTablesList() + " ";
|
||||||
|
dump_descriptor += "-player";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpSystemTables()) {
|
||||||
|
tables_to_dump += GetSystemTablesList() + " ";
|
||||||
|
dump_descriptor += "-system";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpStateTables()) {
|
||||||
|
tables_to_dump += GetStateTablesList() + " ";
|
||||||
|
dump_descriptor += "-state";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpContentTables()) {
|
||||||
|
tables_to_dump += GetContentTablesList() + " ";
|
||||||
|
dump_descriptor += "-content";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpLoginServerTables()) {
|
||||||
|
tables_to_dump += GetLoginTableList() + " ";
|
||||||
|
dump_descriptor += "-login";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpQueryServerTables()) {
|
||||||
|
tables_to_dump += GetQueryServTables();
|
||||||
|
dump_descriptor += "-queryserv";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dump_descriptor.empty()) {
|
||||||
|
SetDumpFileName(GetDumpFileName() + dump_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we are dumping to stdout then we don't generate a file
|
||||||
|
*/
|
||||||
|
std::string pipe_file;
|
||||||
|
if (!IsDumpOutputToConsole()) {
|
||||||
|
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string execute_command = fmt::format(
|
||||||
|
"{} {} {} {}",
|
||||||
|
GetBaseMySQLDumpCommand(),
|
||||||
|
options,
|
||||||
|
tables_to_dump,
|
||||||
|
pipe_file
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
|
||||||
|
FileUtil::mkdir(GetSetDumpPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDumpDropTableSyntaxOnly()) {
|
||||||
|
std::vector<std::string> tables = SplitString(tables_to_dump, ' ');
|
||||||
|
|
||||||
|
for (auto &table : tables) {
|
||||||
|
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tables_to_dump.empty()) {
|
||||||
|
std::cerr << "No tables were specified" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
|
||||||
|
if (!execution_result.empty()) {
|
||||||
|
std::cout << execution_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tables_to_dump.empty()) {
|
||||||
|
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());
|
||||||
|
|
||||||
|
if (IsTarAvailable()) {
|
||||||
|
execute(
|
||||||
|
fmt::format(
|
||||||
|
"tar -zcvf {}.tar.gz -C {} {}.sql",
|
||||||
|
GetDumpFileNameWithPath(),
|
||||||
|
GetSetDumpPath(),
|
||||||
|
GetDumpFileName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
|
||||||
|
}
|
||||||
|
else if (Is7ZipAvailable()) {
|
||||||
|
execute(
|
||||||
|
fmt::format(
|
||||||
|
"7z a -t7z {}.zip {}.sql",
|
||||||
|
GetDumpFileNameWithPath(),
|
||||||
|
GetDumpFileNameWithPath()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogInfo("Compression requested, but no available compression binary was found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogWarning("Compression requested but binary not found... Skipping...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
|
||||||
|
// LogDebug("[{}] dump-path", GetSetDumpPath());
|
||||||
|
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
|
||||||
|
// LogDebug("[{}] query-serv", (IsDumpQueryServerTables() ? "true" : "false"));
|
||||||
|
// LogDebug("[{}] has-compression-binary", (HasCompressionBinary() ? "true" : "false"));
|
||||||
|
// LogDebug("[{}] content", (IsDumpContentTables() ? "true" : "false"));
|
||||||
|
// LogDebug("[{}] no-data", (IsDumpWithNoData() ? "true" : "false"));
|
||||||
|
// LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false"));
|
||||||
|
// LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false"));
|
||||||
|
// LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpSystemTables() const
|
||||||
|
{
|
||||||
|
return dump_system_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpSystemTables(bool dump_system_tables)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_system_tables = dump_system_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpContentTables() const
|
||||||
|
{
|
||||||
|
return dump_content_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpContentTables(bool dump_content_tables)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_content_tables = dump_content_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpPlayerTables() const
|
||||||
|
{
|
||||||
|
return dump_player_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpPlayerTables(bool dump_player_tables)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_player_tables = dump_player_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpLoginServerTables() const
|
||||||
|
{
|
||||||
|
return dump_login_server_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpLoginServerTables(bool dump_login_server_tables)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_login_server_tables = dump_login_server_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpWithNoData() const
|
||||||
|
{
|
||||||
|
return dump_with_no_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpWithNoData(bool dump_with_no_data)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_with_no_data = dump_with_no_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpAllTables() const
|
||||||
|
{
|
||||||
|
return dump_all_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpAllTables(bool dump_all_tables)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_all_tables = dump_all_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpTableLock() const
|
||||||
|
{
|
||||||
|
return dump_table_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpTableLock(bool dump_table_lock)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_table_lock = dump_table_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpWithCompression() const
|
||||||
|
{
|
||||||
|
return dump_with_compression;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpWithCompression(bool dump_with_compression)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_with_compression = dump_with_compression;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &DatabaseDumpService::GetDumpPath() const
|
||||||
|
{
|
||||||
|
return dump_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpPath(const std::string &dump_path)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_path = dump_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpFileName(const std::string &dump_file_name)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_file_name = dump_file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &DatabaseDumpService::GetDumpFileName() const
|
||||||
|
{
|
||||||
|
return dump_file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpQueryServerTables() const
|
||||||
|
{
|
||||||
|
return dump_query_server_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpQueryServerTables(bool dump_query_server_tables)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_query_server_tables = dump_query_server_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpOutputToConsole() const
|
||||||
|
{
|
||||||
|
return dump_output_to_console;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpOutputToConsole(bool dump_output_to_console)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_output_to_console = dump_output_to_console;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpDropTableSyntaxOnly() const
|
||||||
|
{
|
||||||
|
return dump_drop_table_syntax_only;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_drop_table_syntax_only = dump_drop_table_syntax_only;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseDumpService::IsDumpStateTables() const
|
||||||
|
{
|
||||||
|
return dump_state_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables)
|
||||||
|
{
|
||||||
|
DatabaseDumpService::dump_state_tables = dump_state_tables;
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_DATABASE_DUMP_SERVICE_H
|
||||||
|
#define EQEMU_DATABASE_DUMP_SERVICE_H
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseDumpService {
|
||||||
|
public:
|
||||||
|
void Dump();
|
||||||
|
bool IsDumpAllTables() const;
|
||||||
|
void SetDumpAllTables(bool dump_all_tables);
|
||||||
|
bool IsDumpWithNoData() const;
|
||||||
|
void SetDumpWithNoData(bool dump_with_no_data);
|
||||||
|
bool IsDumpSystemTables() const;
|
||||||
|
void SetDumpSystemTables(bool dump_system_tables);
|
||||||
|
bool IsDumpContentTables() const;
|
||||||
|
void SetDumpContentTables(bool dump_content_tables);
|
||||||
|
bool IsDumpPlayerTables() const;
|
||||||
|
void SetDumpPlayerTables(bool dump_player_tables);
|
||||||
|
bool IsDumpLoginServerTables() const;
|
||||||
|
void SetDumpLoginServerTables(bool dump_login_server_tables);
|
||||||
|
bool IsDumpTableLock() const;
|
||||||
|
void SetDumpTableLock(bool dump_table_lock);
|
||||||
|
bool IsDumpWithCompression() const;
|
||||||
|
void SetDumpWithCompression(bool dump_with_compression);
|
||||||
|
const std::string &GetDumpPath() const;
|
||||||
|
void SetDumpPath(const std::string &dump_path);
|
||||||
|
const std::string &GetDumpFileName() const;
|
||||||
|
void SetDumpFileName(const std::string &dump_file_name);
|
||||||
|
bool IsDumpQueryServerTables() const;
|
||||||
|
void SetDumpQueryServerTables(bool dump_query_server_tables);
|
||||||
|
bool IsDumpOutputToConsole() const;
|
||||||
|
void SetDumpOutputToConsole(bool dump_output_to_console);
|
||||||
|
bool IsDumpDropTableSyntaxOnly() const;
|
||||||
|
void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only);
|
||||||
|
bool IsDumpStateTables() const;
|
||||||
|
void SetDumpStateTables(bool dump_state_tables);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool dump_all_tables = false;
|
||||||
|
bool dump_state_tables = false;
|
||||||
|
bool dump_system_tables = false;
|
||||||
|
bool dump_content_tables = false;
|
||||||
|
bool dump_player_tables = false;
|
||||||
|
bool dump_query_server_tables = false;
|
||||||
|
bool dump_login_server_tables = false;
|
||||||
|
bool dump_with_no_data = false;
|
||||||
|
bool dump_table_lock = false;
|
||||||
|
bool dump_with_compression = false;
|
||||||
|
bool dump_output_to_console = false;
|
||||||
|
bool dump_drop_table_syntax_only = 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 GetSystemTablesList();
|
||||||
|
std::string GetStateTablesList();
|
||||||
|
std::string GetContentTablesList();
|
||||||
|
std::string GetLoginTableList();
|
||||||
|
bool IsTarAvailable();
|
||||||
|
bool Is7ZipAvailable();
|
||||||
|
bool HasCompressionBinary();
|
||||||
|
std::string GetDumpFileNameWithPath();
|
||||||
|
std::string GetSetDumpPath();
|
||||||
|
std::string GetQueryServTables();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EQEMU_DATABASE_DUMP_SERVICE_H
|
||||||
@@ -101,14 +101,20 @@ bool Database::CheckInstanceExpired(uint16 instance_id)
|
|||||||
int32 duration = 0;
|
int32 duration = 0;
|
||||||
uint32 never_expires = 0;
|
uint32 never_expires = 0;
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
|
std::string query = StringFormat(
|
||||||
|
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
|
||||||
|
instance_id
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success()) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0)
|
if (results.RowCount() == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
|
|
||||||
@@ -116,23 +122,28 @@ bool Database::CheckInstanceExpired(uint16 instance_id)
|
|||||||
duration = atoi(row[1]);
|
duration = atoi(row[1]);
|
||||||
never_expires = atoi(row[2]);
|
never_expires = atoi(row[2]);
|
||||||
|
|
||||||
if (never_expires == 1)
|
if (never_expires == 1) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
timeval tv;
|
timeval tv{};
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
|
|
||||||
if ((start_time + duration) <= tv.tv_sec)
|
return (start_time + duration) <= tv.tv_sec;
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
|
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
|
||||||
{
|
{
|
||||||
std::string query = StringFormat("INSERT INTO instance_list (id, zone, version, start_time, duration)"
|
std::string query = StringFormat(
|
||||||
" values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)",
|
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
|
||||||
(unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration);
|
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
|
||||||
|
instance_id,
|
||||||
|
zone_id,
|
||||||
|
version,
|
||||||
|
duration
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
return results.Success();
|
return results.Success();
|
||||||
@@ -140,66 +151,84 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
|
|||||||
|
|
||||||
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
||||||
{
|
{
|
||||||
uint32 count = RuleI(Zone, ReservedInstances);
|
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
|
||||||
uint32 max = 65535;
|
uint32 max = 32000;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count);
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success()) {
|
||||||
{
|
|
||||||
instance_id = 0;
|
instance_id = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0)
|
if (results.RowCount() == 0) {
|
||||||
{
|
instance_id = max_reserved_instance_id;
|
||||||
instance_id = 0;
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
|
|
||||||
if (atoi(row[0]) <= max)
|
if (atoi(row[0]) <= max) {
|
||||||
{
|
|
||||||
instance_id = atoi(row[0]);
|
instance_id = atoi(row[0]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", count);
|
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);
|
results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success()) {
|
||||||
{
|
|
||||||
instance_id = 0;
|
instance_id = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0)
|
if (results.RowCount() == 0) {
|
||||||
{
|
|
||||||
instance_id = 0;
|
instance_id = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
max_reserved_instance_id++;
|
||||||
for (auto row = results.begin(); row != results.end(); ++row)
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
{
|
if (max_reserved_instance_id < atoi(row[0])) {
|
||||||
if (count < atoi(row[0]))
|
instance_id = max_reserved_instance_id;
|
||||||
{
|
|
||||||
instance_id = count;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > max)
|
if (max_reserved_instance_id > max) {
|
||||||
{
|
|
||||||
instance_id = 0;
|
instance_id = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
max_reserved_instance_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance_id = count;
|
instance_id = max_reserved_instance_id;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,17 +577,36 @@ void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &ch
|
|||||||
|
|
||||||
void Database::PurgeExpiredInstances()
|
void Database::PurgeExpiredInstances()
|
||||||
{
|
{
|
||||||
std::string query("SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0");
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
std::string query =
|
||||||
|
SQL(
|
||||||
|
SELECT
|
||||||
|
id
|
||||||
|
FROM
|
||||||
|
instance_list
|
||||||
|
where
|
||||||
|
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
|
||||||
|
and never_expires = 0
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0)
|
if (results.RowCount() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row)
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
DeleteInstance(atoi(row[0]));
|
DeleteInstance(atoi(row[0]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||||
|
|||||||
+107
-33
@@ -22,17 +22,77 @@
|
|||||||
#define EQEMU_DATABASE_SCHEMA_H
|
#define EQEMU_DATABASE_SCHEMA_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace DatabaseSchema {
|
namespace DatabaseSchema {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets player tables
|
* Character-specific tables
|
||||||
|
*
|
||||||
|
* Does not included related meta-data tables such as 'guilds', 'accounts'
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static std::map<std::string, std::string> GetCharacterTables()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
{"adventure_stats", "player_id"},
|
||||||
|
{"buyer", "charid"},
|
||||||
|
{"char_recipe_list", "char_id"},
|
||||||
|
{"character_activities", "charid"},
|
||||||
|
{"character_alt_currency", "char_id"},
|
||||||
|
{"character_alternate_abilities", "id"},
|
||||||
|
{"character_auras", "id"},
|
||||||
|
{"character_bandolier", "id"},
|
||||||
|
{"character_bind", "id"},
|
||||||
|
{"character_buffs", "character_id"},
|
||||||
|
{"character_corpses", "id"},
|
||||||
|
{"character_currency", "id"},
|
||||||
|
{"character_data", "id"},
|
||||||
|
{"character_disciplines", "id"},
|
||||||
|
{"character_enabledtasks", "charid"},
|
||||||
|
{"character_inspect_messages", "id"},
|
||||||
|
{"character_item_recast", "id"},
|
||||||
|
{"character_languages", "id"},
|
||||||
|
{"character_leadership_abilities", "id"},
|
||||||
|
{"character_material", "id"},
|
||||||
|
{"character_memmed_spells", "id"},
|
||||||
|
{"character_pet_buffs", "char_id"},
|
||||||
|
{"character_pet_info", "char_id"},
|
||||||
|
{"character_pet_inventory", "char_id"},
|
||||||
|
{"character_potionbelt", "id"},
|
||||||
|
{"character_skills", "id"},
|
||||||
|
{"character_spells", "id"},
|
||||||
|
{"character_tasks", "charid"},
|
||||||
|
{"character_tribute", "id"},
|
||||||
|
{"completed_tasks", "charid"},
|
||||||
|
{"data_buckets", "id"},
|
||||||
|
{"faction_values", "char_id"},
|
||||||
|
{"friends", "charid"},
|
||||||
|
{"guild_members", "char_id"},
|
||||||
|
{"guilds", "id"},
|
||||||
|
{"instance_list_player", "id"},
|
||||||
|
{"inventory", "charid"},
|
||||||
|
{"inventory_snapshots", "charid"},
|
||||||
|
{"keyring", "char_id"},
|
||||||
|
{"mail", "charid"},
|
||||||
|
{"player_titlesets", "char_id"},
|
||||||
|
{"quest_globals", "charid"},
|
||||||
|
{"timers", "char_id"},
|
||||||
|
{"titles", "char_id"},
|
||||||
|
{"trader", "char_id"},
|
||||||
|
{"zone_flags", "charID"}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Gets all player and meta-data tables
|
||||||
|
* @note These tables have no content in the PEQ daily dump
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static std::vector<std::string> GetPlayerTables()
|
static std::vector<std::string> GetPlayerTables()
|
||||||
{
|
{
|
||||||
std::vector<std::string> tables = {
|
return {
|
||||||
"account",
|
"account",
|
||||||
"account_ip",
|
"account_ip",
|
||||||
"account_flags",
|
"account_flags",
|
||||||
@@ -70,6 +130,7 @@ namespace DatabaseSchema {
|
|||||||
"character_tribute",
|
"character_tribute",
|
||||||
"completed_tasks",
|
"completed_tasks",
|
||||||
"data_buckets",
|
"data_buckets",
|
||||||
|
"discovered_items",
|
||||||
"faction_values",
|
"faction_values",
|
||||||
"friends",
|
"friends",
|
||||||
"guild_bank",
|
"guild_bank",
|
||||||
@@ -82,17 +143,18 @@ namespace DatabaseSchema {
|
|||||||
"inventory_snapshots",
|
"inventory_snapshots",
|
||||||
"keyring",
|
"keyring",
|
||||||
"mail",
|
"mail",
|
||||||
|
"petitions",
|
||||||
"player_titlesets",
|
"player_titlesets",
|
||||||
"quest_globals",
|
"quest_globals",
|
||||||
"sharedbank",
|
"sharedbank",
|
||||||
|
"spell_buckets",
|
||||||
|
"spell_globals",
|
||||||
"timers",
|
"timers",
|
||||||
"titles",
|
"titles",
|
||||||
"trader",
|
"trader",
|
||||||
"trader_audit",
|
"trader_audit",
|
||||||
"zone_flags"
|
"zone_flags"
|
||||||
};
|
};
|
||||||
|
|
||||||
return tables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,7 +164,7 @@ namespace DatabaseSchema {
|
|||||||
*/
|
*/
|
||||||
static std::vector<std::string> GetContentTables()
|
static std::vector<std::string> GetContentTables()
|
||||||
{
|
{
|
||||||
std::vector<std::string> tables = {
|
return {
|
||||||
"aa_ability",
|
"aa_ability",
|
||||||
"aa_actions",
|
"aa_actions",
|
||||||
"aa_effects",
|
"aa_effects",
|
||||||
@@ -176,7 +238,6 @@ namespace DatabaseSchema {
|
|||||||
"task_activities",
|
"task_activities",
|
||||||
"tasks",
|
"tasks",
|
||||||
"tasksets",
|
"tasksets",
|
||||||
"titles",
|
|
||||||
"tradeskill_recipe",
|
"tradeskill_recipe",
|
||||||
"tradeskill_recipe_entries",
|
"tradeskill_recipe_entries",
|
||||||
"traps",
|
"traps",
|
||||||
@@ -188,8 +249,6 @@ namespace DatabaseSchema {
|
|||||||
"zone_server",
|
"zone_server",
|
||||||
"zoneserver_auth",
|
"zoneserver_auth",
|
||||||
};
|
};
|
||||||
|
|
||||||
return tables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -199,34 +258,48 @@ namespace DatabaseSchema {
|
|||||||
*/
|
*/
|
||||||
static std::vector<std::string> GetServerTables()
|
static std::vector<std::string> GetServerTables()
|
||||||
{
|
{
|
||||||
std::vector<std::string> tables = {
|
return {
|
||||||
"banned_ips",
|
"chatchannels",
|
||||||
"bugs",
|
|
||||||
"bug_reports",
|
|
||||||
"command_settings",
|
"command_settings",
|
||||||
"db_str",
|
"db_str",
|
||||||
"discovered_items",
|
|
||||||
"eqtime",
|
"eqtime",
|
||||||
"eventlog",
|
|
||||||
"gm_ips",
|
|
||||||
"hackers",
|
|
||||||
"ip_exemptions",
|
|
||||||
"launcher",
|
"launcher",
|
||||||
"launcher_zones",
|
"launcher_zones",
|
||||||
"level_exp_mods",
|
"level_exp_mods",
|
||||||
"logsys_categories",
|
"logsys_categories",
|
||||||
"name_filter",
|
"name_filter",
|
||||||
"perl_event_export_settings",
|
"perl_event_export_settings",
|
||||||
"petitions",
|
|
||||||
"profanity_list",
|
"profanity_list",
|
||||||
"reports",
|
|
||||||
"rule_sets",
|
"rule_sets",
|
||||||
"rule_values",
|
"rule_values",
|
||||||
"saylink",
|
|
||||||
"variables",
|
"variables",
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return tables;
|
/**
|
||||||
|
* Gets QueryServer tables
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static std::vector<std::string> GetQueryServerTables()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"qs_merchant_transaction_record",
|
||||||
|
"qs_merchant_transaction_record_entries",
|
||||||
|
"qs_player_aa_rate_hourly",
|
||||||
|
"qs_player_delete_record",
|
||||||
|
"qs_player_delete_record_entries",
|
||||||
|
"qs_player_events",
|
||||||
|
"qs_player_handin_record",
|
||||||
|
"qs_player_handin_record_entries",
|
||||||
|
"qs_player_move_record",
|
||||||
|
"qs_player_move_record_entries",
|
||||||
|
"qs_player_npc_kill_record",
|
||||||
|
"qs_player_npc_kill_record_entries",
|
||||||
|
"qs_player_speech",
|
||||||
|
"qs_player_trade_record",
|
||||||
|
"qs_player_trade_record_entries",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,11 +310,17 @@ namespace DatabaseSchema {
|
|||||||
*/
|
*/
|
||||||
static std::vector<std::string> GetStateTables()
|
static std::vector<std::string> GetStateTables()
|
||||||
{
|
{
|
||||||
std::vector<std::string> tables = {
|
return {
|
||||||
"adventure_members",
|
"adventure_members",
|
||||||
"chatchannels",
|
"banned_ips",
|
||||||
|
"bug_reports",
|
||||||
|
"bugs",
|
||||||
|
"eventlog",
|
||||||
|
"gm_ips",
|
||||||
"group_id",
|
"group_id",
|
||||||
"group_leaders",
|
"group_leaders",
|
||||||
|
"hackers",
|
||||||
|
"ip_exemptions",
|
||||||
"item_tick",
|
"item_tick",
|
||||||
"lfguild",
|
"lfguild",
|
||||||
"merchantlist_temp",
|
"merchantlist_temp",
|
||||||
@@ -249,12 +328,11 @@ namespace DatabaseSchema {
|
|||||||
"raid_details",
|
"raid_details",
|
||||||
"raid_leaders",
|
"raid_leaders",
|
||||||
"raid_members",
|
"raid_members",
|
||||||
|
"reports",
|
||||||
"respawn_times",
|
"respawn_times",
|
||||||
"spell_buckets",
|
"saylink",
|
||||||
"spell_globals",
|
|
||||||
};
|
|
||||||
|
|
||||||
return tables;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,15 +342,13 @@ namespace DatabaseSchema {
|
|||||||
*/
|
*/
|
||||||
static std::vector<std::string> GetLoginTables()
|
static std::vector<std::string> GetLoginTables()
|
||||||
{
|
{
|
||||||
std::vector<std::string> tables = {
|
return {
|
||||||
"login_accounts",
|
"login_accounts",
|
||||||
"login_api_tokens",
|
"login_api_tokens",
|
||||||
"login_server_admins",
|
"login_server_admins",
|
||||||
"login_server_list_types",
|
"login_server_list_types",
|
||||||
"login_world_servers",
|
"login_world_servers",
|
||||||
};
|
};
|
||||||
|
|
||||||
return tables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,12 +358,10 @@ namespace DatabaseSchema {
|
|||||||
*/
|
*/
|
||||||
static std::vector<std::string> GetVersionTables()
|
static std::vector<std::string> GetVersionTables()
|
||||||
{
|
{
|
||||||
std::vector<std::string> tables = {
|
return {
|
||||||
"db_version",
|
"db_version",
|
||||||
"inventory_versions",
|
"inventory_versions",
|
||||||
};
|
};
|
||||||
|
|
||||||
return tables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -115,14 +115,14 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
||||||
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
|
||||||
/* Implement Logging at the Root */
|
/**
|
||||||
|
* Error logging
|
||||||
|
*/
|
||||||
if (mysql_errno(&mysql) > 0 && strlen(query) > 0) {
|
if (mysql_errno(&mysql) > 0 && strlen(query) > 0) {
|
||||||
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)
|
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||||
Log(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer);
|
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// successful query. get results.
|
// successful query. get results.
|
||||||
@@ -143,9 +143,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
|
|
||||||
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
||||||
if ((strncasecmp(query, "select", 6) == 0)) {
|
if ((strncasecmp(query, "select", 6) == 0)) {
|
||||||
LogF(
|
LogMySQLQuery(
|
||||||
Logs::General,
|
|
||||||
Logs::MySQLQuery,
|
|
||||||
"{0} ({1} row{2} returned) ({3}s)",
|
"{0} ({1} row{2} returned) ({3}s)",
|
||||||
query,
|
query,
|
||||||
requestResult.RowCount(),
|
requestResult.RowCount(),
|
||||||
@@ -154,9 +152,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogF(
|
LogMySQLQuery(
|
||||||
Logs::General,
|
|
||||||
Logs::MySQLQuery,
|
|
||||||
"{0} ({1} row{2} affected) ({3}s)",
|
"{0} ({1} row{2} affected) ({3}s)",
|
||||||
query,
|
query,
|
||||||
requestResult.RowsAffected(),
|
requestResult.RowsAffected(),
|
||||||
|
|||||||
@@ -317,6 +317,15 @@ namespace EQEmu
|
|||||||
QuestControlGrid = -1
|
QuestControlGrid = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace consent {
|
||||||
|
enum eConsentType : uint8 {
|
||||||
|
Normal = 0,
|
||||||
|
Group,
|
||||||
|
Raid,
|
||||||
|
Guild
|
||||||
|
};
|
||||||
|
}; // namespace consent
|
||||||
|
|
||||||
} /*EQEmu*/
|
} /*EQEmu*/
|
||||||
|
|
||||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ static const uint32 MAX_MERC = 100;
|
|||||||
static const uint32 MAX_MERC_GRADES = 10;
|
static const uint32 MAX_MERC_GRADES = 10;
|
||||||
static const uint32 MAX_MERC_STANCES = 10;
|
static const uint32 MAX_MERC_STANCES = 10;
|
||||||
static const uint32 BLOCKED_BUFF_COUNT = 20;
|
static const uint32 BLOCKED_BUFF_COUNT = 20;
|
||||||
|
static const uint32 QUESTREWARD_COUNT = 8;
|
||||||
|
static const uint32 ADVANCED_LORE_LENGTH = 8192;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2180,14 +2182,7 @@ struct QuestReward_Struct
|
|||||||
/*024*/ uint32 silver; // Gives silver to the client
|
/*024*/ uint32 silver; // Gives silver to the client
|
||||||
/*028*/ uint32 gold; // Gives gold to the client
|
/*028*/ uint32 gold; // Gives gold to the client
|
||||||
/*032*/ uint32 platinum; // Gives platinum to the client
|
/*032*/ uint32 platinum; // Gives platinum to the client
|
||||||
/*036*/ uint32 item_id;
|
/*036*/ int32 item_id[QUESTREWARD_COUNT]; // -1 for nothing
|
||||||
/*040*/ uint32 unknown040;
|
|
||||||
/*044*/ uint32 unknown044;
|
|
||||||
/*048*/ uint32 unknown048;
|
|
||||||
/*052*/ uint32 unknown052;
|
|
||||||
/*056*/ uint32 unknown056;
|
|
||||||
/*060*/ uint32 unknown060;
|
|
||||||
/*064*/ uint32 unknown064;
|
|
||||||
/*068*/
|
/*068*/
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2972,6 +2967,12 @@ struct ItemViewRequest_Struct {
|
|||||||
/*046*/ char unknown046[2];
|
/*046*/ char unknown046[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ItemAdvancedLoreText_Struct {
|
||||||
|
int32 item_id;
|
||||||
|
char item_name[64];
|
||||||
|
char advanced_lore[ADVANCED_LORE_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
struct LDONItemViewRequest_Struct {
|
struct LDONItemViewRequest_Struct {
|
||||||
uint32 item_id;
|
uint32 item_id;
|
||||||
uint8 unknown004[4];
|
uint8 unknown004[4];
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
|||||||
log_settings[Logs::Loginserver].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::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
|
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RFC 5424
|
* RFC 5424
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ namespace Logs {
|
|||||||
AoeCast,
|
AoeCast,
|
||||||
EntityManagement,
|
EntityManagement,
|
||||||
Flee,
|
Flee,
|
||||||
|
Aura,
|
||||||
|
HotReload,
|
||||||
MaxCategoryID /* Don't Remove this */
|
MaxCategoryID /* Don't Remove this */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -185,6 +187,8 @@ namespace Logs {
|
|||||||
"AOE Cast",
|
"AOE Cast",
|
||||||
"Entity Management",
|
"Entity Management",
|
||||||
"Flee",
|
"Flee",
|
||||||
|
"Aura",
|
||||||
|
"HotReload",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -551,6 +551,26 @@
|
|||||||
OutF(LogSys, Logs::Detail, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
OutF(LogSys, Logs::Detail, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAura(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Aura].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAuraDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Aura].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogHotReload(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::HotReload].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogHotReloadDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::HotReload].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define Log(debug_level, log_category, message, ...) do {\
|
#define Log(debug_level, log_category, message, ...) do {\
|
||||||
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
||||||
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
@@ -878,6 +898,18 @@
|
|||||||
#define LogFleeDetail(message, ...) do {\
|
#define LogFleeDetail(message, ...) do {\
|
||||||
} while (0)
|
} 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 Log(debug_level, log_category, message, ...) do {\
|
#define Log(debug_level, log_category, message, ...) do {\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ namespace EQ
|
|||||||
uv_run(&m_loop, UV_RUN_DEFAULT);
|
uv_run(&m_loop, UV_RUN_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shutdown() {
|
||||||
|
uv_stop(&m_loop);
|
||||||
|
}
|
||||||
|
|
||||||
uv_loop_t* Handle() { return &m_loop; }
|
uv_loop_t* Handle() { return &m_loop; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) EQEMu Development Team (http://eqemulator.net)
|
||||||
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,22 +13,15 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../common/metric_event.h"
|
#pragma once
|
||||||
#include "npc.h"
|
|
||||||
|
|
||||||
class NPC::EventNpcStatsMonitor : EQEmu::MetricEvent {
|
#include <tl/expected.hpp>
|
||||||
public:
|
|
||||||
|
|
||||||
virtual EventType GetEventType() const { return EventType::eventNpcStatsMonitor; }
|
namespace eq
|
||||||
|
{
|
||||||
virtual void Process() {}
|
using tl::expected;
|
||||||
|
using tl::make_unexpected;
|
||||||
virtual void Flush() {}
|
}
|
||||||
|
|
||||||
virtual void Finalize() { MetricEvent::Finalize(); }
|
|
||||||
|
|
||||||
virtual void Expire() { MetricEvent::Expire(); }
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include "file_util.h"
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#include <direct.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <process.h>
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool FileUtil::exists(const std::string &name)
|
||||||
|
{
|
||||||
|
std::ifstream f(name.c_str());
|
||||||
|
|
||||||
|
return f.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param directory_name
|
||||||
|
*/
|
||||||
|
void FileUtil::mkdir(const std::string& directory_name)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
struct _stat st;
|
||||||
|
if (_stat(directory_name.c_str(), &st) == 0) // exists
|
||||||
|
return;
|
||||||
|
_mkdir(directory_name.c_str());
|
||||||
|
#else
|
||||||
|
struct stat st{};
|
||||||
|
if (stat(directory_name.c_str(), &st) == 0) { // exists
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
::mkdir(directory_name.c_str(), 0755);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_FILE_UTIL_H
|
||||||
|
#define EQEMU_FILE_UTIL_H
|
||||||
|
|
||||||
|
|
||||||
|
class FileUtil {
|
||||||
|
public:
|
||||||
|
static bool exists(const std::string &name);
|
||||||
|
static void mkdir(const std::string& directory_name);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EQEMU_FILE_UTIL_H
|
||||||
@@ -912,7 +912,7 @@ bool BaseGuildManager::GetEntireGuild(uint32 guild_id, std::vector<CharGuildInfo
|
|||||||
return(false);
|
return(false);
|
||||||
|
|
||||||
//load up the rank info for each guild.
|
//load up the rank info for each guild.
|
||||||
std::string query = StringFormat(GuildMemberBaseQuery " WHERE g.guild_id=%d", guild_id);
|
std::string query = StringFormat(GuildMemberBaseQuery " WHERE g.guild_id=%d AND c.deleted_at IS NULL", guild_id);
|
||||||
auto results = m_db->QueryDatabase(query);
|
auto results = m_db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -941,7 +941,7 @@ bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) {
|
|||||||
m_db->DoEscapeString(esc, char_name, nl);
|
m_db->DoEscapeString(esc, char_name, nl);
|
||||||
|
|
||||||
//load up the rank info for each guild.
|
//load up the rank info for each guild.
|
||||||
std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.name='%s'", esc);
|
std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.name='%s' AND c.deleted_at IS NULL", esc);
|
||||||
safe_delete_array(esc);
|
safe_delete_array(esc);
|
||||||
auto results = m_db->QueryDatabase(query);
|
auto results = m_db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
@@ -969,9 +969,9 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
|
|||||||
//load up the rank info for each guild.
|
//load up the rank info for each guild.
|
||||||
std::string query;
|
std::string query;
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C'", char_id);
|
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C' AND c.deleted_at IS NULL", char_id);
|
||||||
#else
|
#else
|
||||||
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d", char_id);
|
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id);
|
||||||
#endif
|
#endif
|
||||||
auto results = m_db->QueryDatabase(query);
|
auto results = m_db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
|
|
||||||
Copyright (C) 2001-2020 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 METRIC_EVENT_H
|
|
||||||
#define METRIC_EVENT_H
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
namespace EQEmu
|
|
||||||
{
|
|
||||||
class MetricEvent {
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum class EventType {
|
|
||||||
eventNone,
|
|
||||||
eventNpcStatsMonitor
|
|
||||||
};
|
|
||||||
|
|
||||||
MetricEvent() {
|
|
||||||
|
|
||||||
m_finalized = false;
|
|
||||||
m_expired = false;
|
|
||||||
m_event_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual EventType GetEventType() const = 0;
|
|
||||||
|
|
||||||
virtual void Process() = 0;
|
|
||||||
virtual void Flush() = 0;
|
|
||||||
|
|
||||||
virtual void Finalize() { m_finalized = true; } // invoke MetricEvent::Finalize() inside of derived class function if not handled locally
|
|
||||||
bool IsFinalized() const { return m_finalized; }
|
|
||||||
|
|
||||||
virtual void Expire() { m_finalized = true; m_expired = true; } // invoke MetricEvent::Expire() inside of derived class function if not handled locally
|
|
||||||
bool IsExpired() const { return m_expired; }
|
|
||||||
|
|
||||||
void SetEventId(int value) { if (m_event_id == 0) { m_event_id = value; } }
|
|
||||||
int GetEventId() const { return m_event_id; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool m_finalized;
|
|
||||||
bool m_expired;
|
|
||||||
int m_event_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // EQEmu
|
|
||||||
|
|
||||||
#endif // METRIC_EVENT_H
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
|
|
||||||
Copyright (C) 2001-2020 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "metric_manager.h"
|
|
||||||
#include "metric_event.h"
|
|
||||||
|
|
||||||
EQEmu::MetricManager::MetricManager() {
|
|
||||||
|
|
||||||
m_current_event_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmu::MetricManager::Process() {
|
|
||||||
|
|
||||||
for (std::list<MetricEvent*>::iterator iter = m_event_list.begin(); iter != m_event_list.end(); ) {
|
|
||||||
|
|
||||||
if ((*iter)->IsExpired()) {
|
|
||||||
|
|
||||||
iter = m_event_list.erase(iter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*iter)->Process();
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int EQEmu::MetricManager::RegisterEvent(MetricEvent* event_object) {
|
|
||||||
|
|
||||||
if (event_object == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
event_object->SetEventId(get_next_event_id());
|
|
||||||
m_event_list.push_back(event_object);
|
|
||||||
|
|
||||||
return event_object->GetEventId();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmu::MetricManager::FlushAll() {
|
|
||||||
|
|
||||||
for (auto iter : m_event_list) {
|
|
||||||
iter->Flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmu::MetricManager::FlushById(int event_id) {
|
|
||||||
|
|
||||||
for (auto iter : m_event_list) {
|
|
||||||
if (iter->GetEventId() == event_id) {
|
|
||||||
|
|
||||||
iter->Flush();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmu::MetricManager::FinalizeAll() {
|
|
||||||
|
|
||||||
for (auto iter : m_event_list) {
|
|
||||||
iter->Finalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmu::MetricManager::FinalizeById(int event_id) {
|
|
||||||
|
|
||||||
for (auto iter : m_event_list) {
|
|
||||||
if (iter->GetEventId() == event_id) {
|
|
||||||
|
|
||||||
iter->Finalize();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmu::MetricManager::ExpireAll() {
|
|
||||||
|
|
||||||
for (auto iter : m_event_list) {
|
|
||||||
iter->Expire();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmu::MetricManager::ExpireById(int event_id) {
|
|
||||||
|
|
||||||
for (auto iter : m_event_list) {
|
|
||||||
if (iter->GetEventId() == event_id) {
|
|
||||||
|
|
||||||
iter->Expire();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int EQEmu::MetricManager::get_next_event_id() {
|
|
||||||
|
|
||||||
return ++m_current_event_id;
|
|
||||||
}
|
|
||||||
@@ -1047,12 +1047,14 @@ void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t leng
|
|||||||
uint8_t new_buffer[2048] = { 0 };
|
uint8_t new_buffer[2048] = { 0 };
|
||||||
uint8_t *buffer = (uint8_t*)p.Data() + offset;
|
uint8_t *buffer = (uint8_t*)p.Data() + offset;
|
||||||
uint32_t new_length = 0;
|
uint32_t new_length = 0;
|
||||||
|
bool send_uncompressed = true;
|
||||||
|
|
||||||
if (length > 30) {
|
if (length > 30) {
|
||||||
new_length = Deflate(buffer, (uint32_t)length, new_buffer + 1, 2048) + 1;
|
new_length = Deflate(buffer, (uint32_t)length, new_buffer + 1, 2048) + 1;
|
||||||
new_buffer[0] = 0x5a;
|
new_buffer[0] = 0x5a;
|
||||||
|
send_uncompressed = (new_length > length);
|
||||||
}
|
}
|
||||||
else {
|
if (send_uncompressed) {
|
||||||
memcpy(new_buffer + 1, buffer, length);
|
memcpy(new_buffer + 1, buffer, length);
|
||||||
new_buffer[0] = 0xa5;
|
new_buffer[0] = 0xa5;
|
||||||
new_length = length + 1;
|
new_length = length + 1;
|
||||||
@@ -1380,7 +1382,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto stream = &m_streams[stream_id];
|
auto stream = &m_streams[stream_id];
|
||||||
auto max_raw_size = m_max_packet_size - m_crc_bytes - DaybreakReliableHeader::size();
|
auto max_raw_size = m_max_packet_size - m_crc_bytes - DaybreakReliableHeader::size() - 1; // -1 for compress flag
|
||||||
size_t length = p.Length();
|
size_t length = p.Length();
|
||||||
if (length > max_raw_size) {
|
if (length > max_raw_size) {
|
||||||
DaybreakReliableFragmentHeader first_header;
|
DaybreakReliableFragmentHeader first_header;
|
||||||
|
|||||||
+3
-3
@@ -89,9 +89,9 @@ namespace EQ {
|
|||||||
public:
|
public:
|
||||||
StaticPacket(void *data, size_t size) { m_data = data; m_data_length = size; m_max_data_length = size; }
|
StaticPacket(void *data, size_t size) { m_data = data; m_data_length = size; m_max_data_length = size; }
|
||||||
virtual ~StaticPacket() { }
|
virtual ~StaticPacket() { }
|
||||||
StaticPacket(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; }
|
StaticPacket(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; m_max_data_length = o.m_max_data_length; }
|
||||||
StaticPacket& operator=(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; return *this; }
|
StaticPacket& operator=(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; return *this; }
|
||||||
StaticPacket(StaticPacket &&o) { m_data = o.m_data; m_data_length = o.m_data_length; }
|
StaticPacket(StaticPacket &&o) noexcept { m_data = o.m_data; m_data_length = o.m_data_length; }
|
||||||
|
|
||||||
virtual const void *Data() const { return m_data; }
|
virtual const void *Data() const { return m_data; }
|
||||||
virtual void *Data() { return m_data; }
|
virtual void *Data() { return m_data; }
|
||||||
@@ -112,7 +112,7 @@ namespace EQ {
|
|||||||
public:
|
public:
|
||||||
DynamicPacket() { }
|
DynamicPacket() { }
|
||||||
virtual ~DynamicPacket() { }
|
virtual ~DynamicPacket() { }
|
||||||
DynamicPacket(DynamicPacket &&o) { m_data = std::move(o.m_data); }
|
DynamicPacket(DynamicPacket &&o) noexcept { m_data = std::move(o.m_data); }
|
||||||
DynamicPacket(const DynamicPacket &o) { m_data = o.m_data; }
|
DynamicPacket(const DynamicPacket &o) { m_data = o.m_data; }
|
||||||
DynamicPacket& operator=(const DynamicPacket &o) { m_data = o.m_data; return *this; }
|
DynamicPacket& operator=(const DynamicPacket &o) { m_data = o.m_data; return *this; }
|
||||||
|
|
||||||
|
|||||||
@@ -4401,7 +4401,7 @@ struct SendAA_Struct {
|
|||||||
/*0104*/ uint32 special_category;
|
/*0104*/ uint32 special_category;
|
||||||
/*0108*/ uint8 shroud;
|
/*0108*/ uint8 shroud;
|
||||||
/*0109*/ uint8 unknown109;
|
/*0109*/ uint8 unknown109;
|
||||||
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
/*0110*/ uint8 reset_on_death; // timer is reset on death
|
||||||
/*0111*/ uint8 unknown111;
|
/*0111*/ uint8 unknown111;
|
||||||
/*0112*/ uint32 total_abilities;
|
/*0112*/ uint32 total_abilities;
|
||||||
/*0116*/ AA_Ability abilities[0];
|
/*0116*/ AA_Ability abilities[0];
|
||||||
|
|||||||
@@ -4341,7 +4341,7 @@ struct SendAA_Struct {
|
|||||||
/*0104*/ uint32 special_category;
|
/*0104*/ uint32 special_category;
|
||||||
/*0108*/ uint8 shroud;
|
/*0108*/ uint8 shroud;
|
||||||
/*0109*/ uint8 unknown109;
|
/*0109*/ uint8 unknown109;
|
||||||
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
/*0110*/ uint8 reset_on_death; // timer is reset on death
|
||||||
/*0111*/ uint8 unknown111;
|
/*0111*/ uint8 unknown111;
|
||||||
/*0112*/ uint32 total_abilities;
|
/*0112*/ uint32 total_abilities;
|
||||||
/*0116*/ AA_Ability abilities[0];
|
/*0116*/ AA_Ability abilities[0];
|
||||||
|
|||||||
@@ -3780,7 +3780,7 @@ struct SendAA_Struct {
|
|||||||
/*0092*/ uint32 special_category;
|
/*0092*/ uint32 special_category;
|
||||||
/*0096*/ uint8 shroud;
|
/*0096*/ uint8 shroud;
|
||||||
/*0097*/ uint8 unknown97;
|
/*0097*/ uint8 unknown97;
|
||||||
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
/*0098*/ uint8 reset_on_death; // timer is reset on death
|
||||||
/*0099*/ uint8 unknown99;
|
/*0099*/ uint8 unknown99;
|
||||||
/*0100*/ uint32 total_abilities;
|
/*0100*/ uint32 total_abilities;
|
||||||
/*0104*/ AA_Ability abilities[0];
|
/*0104*/ AA_Ability abilities[0];
|
||||||
|
|||||||
@@ -3704,7 +3704,7 @@ struct SendAA_Struct {
|
|||||||
/*0088*/ uint32 aa_expansion;
|
/*0088*/ uint32 aa_expansion;
|
||||||
/*0092*/ uint32 special_category;
|
/*0092*/ uint32 special_category;
|
||||||
/*0096*/ uint8 shroud;
|
/*0096*/ uint8 shroud;
|
||||||
/*0097*/ uint8 unknown97;
|
/*0097*/ uint8 reset_on_death; // timer is reset on death -- guess
|
||||||
/*0098*/ uint32 total_abilities;
|
/*0098*/ uint32 total_abilities;
|
||||||
/*0102*/ AA_Ability abilities[0];
|
/*0102*/ AA_Ability abilities[0];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3835,7 +3835,7 @@ struct SendAA_Struct {
|
|||||||
/*0092*/ uint32 special_category;
|
/*0092*/ uint32 special_category;
|
||||||
/*0096*/ uint8 shroud;
|
/*0096*/ uint8 shroud;
|
||||||
/*0097*/ uint8 unknown97;
|
/*0097*/ uint8 unknown97;
|
||||||
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
|
/*0098*/ uint8 reset_on_death; // timer is reset on death
|
||||||
/*0099*/ uint8 unknown99;
|
/*0099*/ uint8 unknown99;
|
||||||
/*0100*/ uint32 total_abilities;
|
/*0100*/ uint32 total_abilities;
|
||||||
/*0104*/ AA_Ability abilities[0];
|
/*0104*/ AA_Ability abilities[0];
|
||||||
|
|||||||
+20
-2
@@ -121,6 +121,7 @@ RULE_BOOL(Character, EnableAggroMeter, true, "Enable Aggro Meter, for users with
|
|||||||
RULE_BOOL(Character, KeepLevelOverMax, false, "Don't delevel a character that has somehow gone over the level cap")
|
RULE_BOOL(Character, KeepLevelOverMax, false, "Don't delevel a character that has somehow gone over the level cap")
|
||||||
RULE_INT(Character, FoodLossPerUpdate, 32, "How much food/water you lose per stamina update")
|
RULE_INT(Character, FoodLossPerUpdate, 32, "How much food/water you lose per stamina update")
|
||||||
RULE_BOOL(Character, EnableHungerPenalties, false, "being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties")
|
RULE_BOOL(Character, EnableHungerPenalties, false, "being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties")
|
||||||
|
RULE_BOOL(Character, EnableFoodRequirement, true, "if disabled, food is no longer required")
|
||||||
RULE_INT(Character, BaseInstrumentSoftCap, 36, "Softcap for instrument mods, 36 commonly referred to as \"3.6\" as well")
|
RULE_INT(Character, BaseInstrumentSoftCap, 36, "Softcap for instrument mods, 36 commonly referred to as \"3.6\" as well")
|
||||||
RULE_BOOL(Character, UseSpellFileSongCap, true, "When they removed the AA that increased the cap they removed the above and just use the spell field")
|
RULE_BOOL(Character, UseSpellFileSongCap, true, "When they removed the AA that increased the cap they removed the above and just use the spell field")
|
||||||
RULE_INT(Character, BaseRunSpeedCap, 158, "Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225")
|
RULE_INT(Character, BaseRunSpeedCap, 158, "Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225")
|
||||||
@@ -159,6 +160,8 @@ RULE_BOOL(Character, PetsUseReagents, true, "Pets use reagent on spells")
|
|||||||
RULE_BOOL(Character, DismountWater, true, "Dismount horses when entering water")
|
RULE_BOOL(Character, DismountWater, true, "Dismount horses when entering water")
|
||||||
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
|
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
|
||||||
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
|
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
|
||||||
|
RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated")
|
||||||
|
RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Mercs)
|
RULE_CATEGORY(Mercs)
|
||||||
@@ -195,6 +198,7 @@ RULE_INT(Skills, SwimmingStartValue, 100, "")
|
|||||||
RULE_BOOL(Skills, TrainSenseHeading, false, "")
|
RULE_BOOL(Skills, TrainSenseHeading, false, "")
|
||||||
RULE_INT(Skills, SenseHeadingStartValue, 200, "")
|
RULE_INT(Skills, SenseHeadingStartValue, 200, "")
|
||||||
RULE_BOOL(Skills, SelfLanguageLearning, true, "")
|
RULE_BOOL(Skills, SelfLanguageLearning, true, "")
|
||||||
|
RULE_BOOL(Skills, RequireTomeHandin, false, "Disable click-to-learn and force turnin to Guild Master")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Pets)
|
RULE_CATEGORY(Pets)
|
||||||
@@ -266,7 +270,6 @@ RULE_INT(Zone, PEQZoneDebuff1, 4454, "First debuff casted by #peqzone Default is
|
|||||||
RULE_INT(Zone, PEQZoneDebuff2, 2209, "Second debuff casted by #peqzone Default is Tendrils of Apathy")
|
RULE_INT(Zone, PEQZoneDebuff2, 2209, "Second debuff casted by #peqzone Default is Tendrils of Apathy")
|
||||||
RULE_BOOL(Zone, UsePEQZoneDebuffs, true, "Will determine if #peqzone will debuff players or not when used")
|
RULE_BOOL(Zone, UsePEQZoneDebuffs, true, "Will determine if #peqzone will debuff players or not when used")
|
||||||
RULE_REAL(Zone, HotZoneBonus, 0.75, "")
|
RULE_REAL(Zone, HotZoneBonus, 0.75, "")
|
||||||
RULE_INT(Zone, ReservedInstances, 30, "Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running")
|
|
||||||
RULE_INT(Zone, EbonCrystalItemID, 40902, "")
|
RULE_INT(Zone, EbonCrystalItemID, 40902, "")
|
||||||
RULE_INT(Zone, RadiantCrystalItemID, 40903, "")
|
RULE_INT(Zone, RadiantCrystalItemID, 40903, "")
|
||||||
RULE_BOOL(Zone, LevelBasedEXPMods, false, "Allows you to use the level_exp_mods table in consideration to your players EXP hits")
|
RULE_BOOL(Zone, LevelBasedEXPMods, false, "Allows you to use the level_exp_mods table in consideration to your players EXP hits")
|
||||||
@@ -294,6 +297,7 @@ RULE_BOOL(Pathing, Find, true, "Enable pathing for FindPerson requests from the
|
|||||||
RULE_BOOL(Pathing, Fear, true, "Enable pathing for fear")
|
RULE_BOOL(Pathing, Fear, true, "Enable pathing for fear")
|
||||||
RULE_REAL(Pathing, NavmeshStepSize, 100.0f, "")
|
RULE_REAL(Pathing, NavmeshStepSize, 100.0f, "")
|
||||||
RULE_REAL(Pathing, ShortMovementUpdateRange, 130.0f, "")
|
RULE_REAL(Pathing, ShortMovementUpdateRange, 130.0f, "")
|
||||||
|
RULE_INT(Pathing, MaxNavmeshNodes, 4092, "Max navmesh nodes in a traversable path")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Watermap)
|
RULE_CATEGORY(Watermap)
|
||||||
@@ -492,6 +496,7 @@ RULE_INT(Combat, NPCAssistCapTimer, 6000, "Time in milliseconds a NPC will take
|
|||||||
RULE_BOOL(Combat, UseRevampHandToHand, false, "use h2h revamped dmg/delays I believe this was implemented during SoF")
|
RULE_BOOL(Combat, UseRevampHandToHand, false, "use h2h revamped dmg/delays I believe this was implemented during SoF")
|
||||||
RULE_BOOL(Combat, ClassicMasterWu, false, "classic master wu uses a random special, modern doesn't")
|
RULE_BOOL(Combat, ClassicMasterWu, false, "classic master wu uses a random special, modern doesn't")
|
||||||
RULE_INT(Combat, LevelToStopDamageCaps, 0, "1 will effectively disable them, 20 should give basically same results as old incorrect system")
|
RULE_INT(Combat, LevelToStopDamageCaps, 0, "1 will effectively disable them, 20 should give basically same results as old incorrect system")
|
||||||
|
RULE_INT(Combat, LevelToStopACTwinkControl, 50, "1 will effectively disable it, 50 should give basically same results as current system")
|
||||||
RULE_BOOL(Combat, ClassicNPCBackstab, false, "true disables npc facestab - npcs get normal attack if not behind")
|
RULE_BOOL(Combat, ClassicNPCBackstab, false, "true disables npc facestab - npcs get normal attack if not behind")
|
||||||
RULE_BOOL(Combat, UseNPCDamageClassLevelMods, true, "Uses GetClassLevelDamageMod calc in npc_scale_manager")
|
RULE_BOOL(Combat, UseNPCDamageClassLevelMods, true, "Uses GetClassLevelDamageMod calc in npc_scale_manager")
|
||||||
RULE_BOOL(Combat, UseExtendedPoisonProcs, false, "Allow old school poisons to last until characrer zones, at a lower proc rate")
|
RULE_BOOL(Combat, UseExtendedPoisonProcs, false, "Allow old school poisons to last until characrer zones, at a lower proc rate")
|
||||||
@@ -519,10 +524,11 @@ RULE_INT(NPC, NPCToNPCAggroTimerMin, 500, "")
|
|||||||
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000, "")
|
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000, "")
|
||||||
RULE_BOOL(NPC, UseClassAsLastName, true, "Uses class archetype as LastName for npcs with none")
|
RULE_BOOL(NPC, UseClassAsLastName, true, "Uses class archetype as LastName for npcs with none")
|
||||||
RULE_BOOL(NPC, NewLevelScaling, true, "Better level scaling, use old if new formulas would break your server")
|
RULE_BOOL(NPC, NewLevelScaling, true, "Better level scaling, use old if new formulas would break your server")
|
||||||
RULE_INT(NPC, NPCGatePercent, 5, "% at which the NPC Will attempt to gate at")
|
RULE_INT(NPC, NPCGatePercent, 20, "% at which the NPC Will attempt to gate at")
|
||||||
RULE_BOOL(NPC, NPCGateNearBind, false, "Will NPC attempt to gate when near bind location?")
|
RULE_BOOL(NPC, NPCGateNearBind, false, "Will NPC attempt to gate when near bind location?")
|
||||||
RULE_INT(NPC, NPCGateDistanceBind, 75, "Distance from bind before NPC will attempt to gate")
|
RULE_INT(NPC, NPCGateDistanceBind, 75, "Distance from bind before NPC will attempt to gate")
|
||||||
RULE_BOOL(NPC, NPCHealOnGate, true, "Will the NPC Heal on Gate")
|
RULE_BOOL(NPC, NPCHealOnGate, true, "Will the NPC Heal on Gate")
|
||||||
|
RULE_BOOL(NPC, UseMeditateBasedManaRegen, false, "Based NPC ooc regen on Meditate skill")
|
||||||
RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the npc will heal on gate if enabled")
|
RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the npc will heal on gate if enabled")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
@@ -762,6 +768,18 @@ RULE_CATEGORY(Logging)
|
|||||||
RULE_BOOL(Logging, PrintFileFunctionAndLine, false, "Ex: [World Server] [net.cpp::main:309] Loading variables...")
|
RULE_BOOL(Logging, PrintFileFunctionAndLine, false, "Ex: [World Server] [net.cpp::main:309] Loading variables...")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
|
RULE_CATEGORY(HotReload)
|
||||||
|
RULE_BOOL(HotReload, QuestsRepopWithReload, true, "When a hot reload is triggered, the zone will repop")
|
||||||
|
RULE_BOOL(HotReload, QuestsRepopWhenPlayersNotInCombat, true, "When a hot reload is triggered, the zone will repop when no clients are in combat")
|
||||||
|
RULE_BOOL(HotReload, QuestsResetTimersWithReload, true, "When a hot reload is triggered, quest timers will be reset")
|
||||||
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
|
RULE_CATEGORY(Instances)
|
||||||
|
RULE_INT(Instances, ReservedInstances, 30, "Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running")
|
||||||
|
RULE_BOOL(Instances, RecycleInstanceIds, true, "Will recycle free instance ids instead of gradually running out at 32k")
|
||||||
|
RULE_INT(Instances, GuildHallExpirationDays, 90, "Amount of days before a Guild Hall instance expires")
|
||||||
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
#undef RULE_CATEGORY
|
#undef RULE_CATEGORY
|
||||||
#undef RULE_INT
|
#undef RULE_INT
|
||||||
#undef RULE_REAL
|
#undef RULE_REAL
|
||||||
|
|||||||
+13
-3
@@ -197,7 +197,11 @@
|
|||||||
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
||||||
#define ServerOP_UCSServerStatusRequest 0x4013
|
#define ServerOP_UCSServerStatusRequest 0x4013
|
||||||
#define ServerOP_UCSServerStatusReply 0x4014
|
#define ServerOP_UCSServerStatusReply 0x4014
|
||||||
/* Query Server OP Codes */
|
#define ServerOP_HotReloadQuests 0x4015
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QueryServer
|
||||||
|
*/
|
||||||
#define ServerOP_QSPlayerLogTrades 0x5010
|
#define ServerOP_QSPlayerLogTrades 0x5010
|
||||||
#define ServerOP_QSPlayerLogHandins 0x5011
|
#define ServerOP_QSPlayerLogHandins 0x5011
|
||||||
#define ServerOP_QSPlayerLogNPCKills 0x5012
|
#define ServerOP_QSPlayerLogNPCKills 0x5012
|
||||||
@@ -866,10 +870,12 @@ struct SpawnPlayerCorpse_Struct {
|
|||||||
struct ServerOP_Consent_Struct {
|
struct ServerOP_Consent_Struct {
|
||||||
char grantname[64];
|
char grantname[64];
|
||||||
char ownername[64];
|
char ownername[64];
|
||||||
|
char zonename[32];
|
||||||
uint8 permission;
|
uint8 permission;
|
||||||
uint32 zone_id;
|
uint32 zone_id;
|
||||||
uint16 instance_id;
|
uint16 instance_id;
|
||||||
uint32 message_string_id;
|
uint8 consent_type; // 0 = normal, 1 = group, 2 = raid, 3 = guild
|
||||||
|
uint32 consent_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReloadTasks_Struct {
|
struct ReloadTasks_Struct {
|
||||||
@@ -1349,10 +1355,14 @@ struct CZSetEntVarByClientName_Struct {
|
|||||||
char m_var[256];
|
char m_var[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReloadWorld_Struct{
|
struct ReloadWorld_Struct {
|
||||||
uint32 Option;
|
uint32 Option;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HotReloadQuestsStruct {
|
||||||
|
char zone_short_name[200];
|
||||||
|
};
|
||||||
|
|
||||||
struct ServerRequestTellQueue_Struct {
|
struct ServerRequestTellQueue_Struct {
|
||||||
char name[64];
|
char name[64];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) 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 04111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../expected.h"
|
||||||
|
#include "shared_memory_error.h"
|
||||||
|
#include "shared_memory_handle.h"
|
||||||
|
|
||||||
|
#include <boost/interprocess/managed_mapped_file.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace eq
|
||||||
|
{
|
||||||
|
namespace shared
|
||||||
|
{
|
||||||
|
namespace detail {
|
||||||
|
typedef boost::interprocess::managed_mapped_file::segment_manager segment_manager_t;
|
||||||
|
typedef boost::interprocess::allocator<void, segment_manager_t> allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
using allocator = detail::allocator;
|
||||||
|
|
||||||
|
class shared_memory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
shared_memory(const std::string &path, size_t sz) {
|
||||||
|
_path = path;
|
||||||
|
_sz = sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
~shared_memory() = default;
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
expected<handle<Ty>, shared_memory_error> map(const std::string& key) {
|
||||||
|
if (!_memory) {
|
||||||
|
try {
|
||||||
|
_memory.reset(new boost::interprocess::managed_mapped_file(boost::interprocess::open_or_create, _path.c_str(), _sz));
|
||||||
|
}
|
||||||
|
catch (boost::interprocess::interprocess_exception) {
|
||||||
|
return eq::make_unexpected(shared_memory_error::error_mapping_memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle<Ty> inst;
|
||||||
|
auto ir = inst.initialize(key, _memory.get());
|
||||||
|
if (ir) {
|
||||||
|
return eq::expected<handle<Ty>, shared_memory_error>(inst);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return make_unexpected(ir.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
return expected<handle<Ty>, shared_memory_error>(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty, typename... Args>
|
||||||
|
Ty construct(Args&&... args) {
|
||||||
|
return Ty(std::forward<Args>(args)..., _memory->get_allocator<void>());
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::unique_ptr<boost::interprocess::managed_mapped_file> _memory;
|
||||||
|
std::string _path;
|
||||||
|
size_t _sz;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) EQEMu Development Team (http://eqemulator.net)
|
||||||
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,45 +13,20 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef METRIC_MANAGER_H
|
#pragma once
|
||||||
#define METRIC_MANAGER_H
|
|
||||||
|
|
||||||
#include <list>
|
namespace eq
|
||||||
|
|
||||||
namespace EQEmu
|
|
||||||
{
|
{
|
||||||
class MetricEvent;
|
namespace shared
|
||||||
|
{
|
||||||
class MetricManager {
|
enum class shared_memory_error
|
||||||
public:
|
{
|
||||||
|
no_error,
|
||||||
MetricManager();
|
error_mapping_memory,
|
||||||
|
error_alloc
|
||||||
void Process();
|
|
||||||
|
|
||||||
int RegisterEvent(MetricEvent*);
|
|
||||||
|
|
||||||
void FlushAll();
|
|
||||||
void FlushById(int);
|
|
||||||
|
|
||||||
void FinalizeAll();
|
|
||||||
void FinalizeById(int);
|
|
||||||
|
|
||||||
void ExpireAll();
|
|
||||||
void ExpireById(int);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int get_next_event_id();
|
|
||||||
|
|
||||||
int m_current_event_id;
|
|
||||||
|
|
||||||
std::list<MetricEvent*> m_event_list;
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
} // EQEmu
|
}
|
||||||
|
|
||||||
#endif // METRIC_MANAGER_H
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) 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 04111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shared_memory_error.h"
|
||||||
|
#include "../expected.h"
|
||||||
|
|
||||||
|
#include <boost/interprocess/managed_mapped_file.hpp>
|
||||||
|
#include <boost/interprocess/allocators/allocator.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace eq
|
||||||
|
{
|
||||||
|
namespace shared
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
struct type_factory {
|
||||||
|
static_assert(std::is_trivially_constructible<Ty>::value,
|
||||||
|
"Non-specialized types must be trivially constructible, consider creating a type_factory in eq::shared::detail if you want to use this type.");
|
||||||
|
Ty* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
return mmf->find_or_construct<Ty>(key.c_str())();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
class handle {
|
||||||
|
public:
|
||||||
|
handle() = default;
|
||||||
|
~handle() = default;
|
||||||
|
|
||||||
|
expected<void, shared_memory_error> initialize(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
try {
|
||||||
|
_mmf = mmf;
|
||||||
|
detail::type_factory<Ty> fac;
|
||||||
|
_ptr = fac.create(key, mmf);
|
||||||
|
return expected<void, shared_memory_error>();
|
||||||
|
}
|
||||||
|
catch (boost::interprocess::interprocess_exception) {
|
||||||
|
return make_unexpected(shared_memory_error::error_mapping_memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Ty& () {
|
||||||
|
return *_ptr;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Ty* _ptr;
|
||||||
|
boost::interprocess::managed_mapped_file* _mmf;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) 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 04111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shared_memory_handle.h"
|
||||||
|
|
||||||
|
#include <boost/interprocess/containers/list.hpp>
|
||||||
|
|
||||||
|
namespace eq
|
||||||
|
{
|
||||||
|
namespace shared
|
||||||
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
using list = boost::interprocess::list<Ty, boost::interprocess::allocator<Ty, boost::interprocess::managed_mapped_file::segment_manager>>;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
struct type_factory<list<Ty>>
|
||||||
|
{
|
||||||
|
list<Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
return mmf->find_or_construct<list<Ty>>(key.c_str())(mmf->get_allocator<void>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) 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 04111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shared_memory_handle.h"
|
||||||
|
|
||||||
|
#include <boost/interprocess/containers/map.hpp>
|
||||||
|
#include <boost/interprocess/containers/flat_map.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
namespace eq
|
||||||
|
{
|
||||||
|
namespace shared
|
||||||
|
{
|
||||||
|
template<typename Ky, typename Ty>
|
||||||
|
using unordered_map = boost::unordered_map<int,
|
||||||
|
Ty,
|
||||||
|
boost::hash<Ky>,
|
||||||
|
std::equal_to<Ky>,
|
||||||
|
boost::interprocess::allocator<std::pair<const Ky, Ty>, boost::interprocess::managed_mapped_file::segment_manager>>;
|
||||||
|
|
||||||
|
template<typename Ky, typename Ty>
|
||||||
|
using map = boost::interprocess::map<Ky,
|
||||||
|
Ty,
|
||||||
|
std::less<Ky>,
|
||||||
|
boost::interprocess::allocator<std::pair<const Ky, Ty>, boost::interprocess::managed_mapped_file::segment_manager>>;
|
||||||
|
|
||||||
|
template<typename Ky, typename Ty>
|
||||||
|
using flat_map = boost::interprocess::flat_map<Ky,
|
||||||
|
Ty,
|
||||||
|
std::less<Ky>,
|
||||||
|
boost::interprocess::allocator<std::pair<const Ky, Ty>, boost::interprocess::managed_mapped_file::segment_manager>>;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename Ky, typename Ty>
|
||||||
|
struct type_factory<unordered_map<Ky, Ty>>
|
||||||
|
{
|
||||||
|
unordered_map<Ky, Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
return mmf->find_or_construct<unordered_map<Ky, Ty>>(key.c_str())(3, boost::hash<Ky>(), std::equal_to<Ky>(), mmf->get_allocator<void>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ky, typename Ty>
|
||||||
|
struct type_factory<map<Ky, Ty>>
|
||||||
|
{
|
||||||
|
map<Ky, Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
return mmf->find_or_construct<map<Ky, Ty>>(key.c_str())(std::less<Ky>(), mmf->get_allocator<void>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ky, typename Ty>
|
||||||
|
struct type_factory<flat_map<Ky, Ty>>
|
||||||
|
{
|
||||||
|
flat_map<Ky, Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
return mmf->find_or_construct<flat_map<Ky, Ty>>(key.c_str())(std::less<Ky>(), mmf->get_allocator<void>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) 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 04111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shared_memory_handle.h"
|
||||||
|
|
||||||
|
#include <boost/interprocess/containers/string.hpp>
|
||||||
|
|
||||||
|
namespace eq
|
||||||
|
{
|
||||||
|
namespace shared
|
||||||
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
using basic_string = boost::interprocess::basic_string<Ty, std::char_traits<Ty>, boost::interprocess::allocator<Ty, boost::interprocess::managed_mapped_file::segment_manager>>;
|
||||||
|
|
||||||
|
using string = basic_string<char>;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
struct type_factory<basic_string<Ty>>
|
||||||
|
{
|
||||||
|
list<Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
return mmf->find_or_construct<list<Ty>>(key.c_str())(mmf->get_allocator<void>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
std::basic_string<Ty> to_std_string(const eq::shared::basic_string<Ty> &in) {
|
||||||
|
return std::basic_string<Ty>(in.begin(), in.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) 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 04111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shared_memory_handle.h"
|
||||||
|
|
||||||
|
#include <boost/interprocess/containers/vector.hpp>
|
||||||
|
|
||||||
|
namespace eq
|
||||||
|
{
|
||||||
|
namespace shared
|
||||||
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
using vector = boost::interprocess::vector<Ty, boost::interprocess::allocator<Ty, boost::interprocess::managed_mapped_file::segment_manager>>;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
struct type_factory<vector<Ty>>
|
||||||
|
{
|
||||||
|
vector<Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
|
||||||
|
return mmf->find_or_construct<vector<Ty>>(key.c_str())(mmf->get_allocator<void>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+137
-139
@@ -1656,21 +1656,19 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) {
|
int SharedDatabase::LoadDamageShieldType(int spell_id) {
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 "
|
std::string query = StringFormat("SELECT `type` FROM `damageshieldtypes` WHERE `spellid` = %i", spell_id);
|
||||||
"AND `spellid` <= %i", iMaxSpellID);
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
for(auto &row : results) {
|
||||||
int spellID = atoi(row[0]);
|
return atoi(row[0]);
|
||||||
if((spellID > 0) && (spellID <= iMaxSpellID))
|
|
||||||
sp[spellID].DamageShieldType = atoi(row[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) {
|
const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) {
|
||||||
@@ -1689,6 +1687,18 @@ int SharedDatabase::GetMaxSpellID() {
|
|||||||
return atoi(row[0]);
|
return atoi(row[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SharedDatabase::GetSpellCount() {
|
||||||
|
std::string query = "SELECT COUNT(id) FROM spells_new";
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
return atoi(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) {
|
bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) {
|
||||||
spells_mmf.reset(nullptr);
|
spells_mmf.reset(nullptr);
|
||||||
|
|
||||||
@@ -1710,10 +1720,7 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
void SharedDatabase::LoadSpells(std::function<void(const SPDat_Spell_Struct & sp)> on_load) {
|
||||||
*(uint32*)data = max_spells;
|
|
||||||
SPDat_Spell_Struct *sp = reinterpret_cast<SPDat_Spell_Struct*>((char*)data + sizeof(uint32));
|
|
||||||
|
|
||||||
const std::string query = "SELECT * FROM spells_new ORDER BY id ASC";
|
const std::string query = "SELECT * FROM spells_new ORDER BY id ASC";
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
@@ -1725,160 +1732,151 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tempid = 0;
|
for (auto &row : results) {
|
||||||
int counter = 0;
|
SPDat_Spell_Struct sp;
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
sp.id = atoi(row[0]);
|
||||||
tempid = atoi(row[0]);
|
strn0cpy(sp.name, row[1], sizeof(sp.name));
|
||||||
if(tempid >= max_spells) {
|
strn0cpy(sp.player_1, row[2], sizeof(sp.player_1));
|
||||||
LogSpells("Non fatal error: spell.id >= max_spells, ignoring");
|
strn0cpy(sp.teleport_zone, row[3], sizeof(sp.teleport_zone));
|
||||||
continue;
|
strn0cpy(sp.you_cast, row[4], sizeof(sp.you_cast));
|
||||||
}
|
strn0cpy(sp.other_casts, row[5], sizeof(sp.other_casts));
|
||||||
|
strn0cpy(sp.cast_on_you, row[6], sizeof(sp.cast_on_you));
|
||||||
|
strn0cpy(sp.cast_on_other, row[7], sizeof(sp.cast_on_other));
|
||||||
|
strn0cpy(sp.spell_fades, row[8], sizeof(sp.spell_fades));
|
||||||
|
|
||||||
++counter;
|
sp.range = static_cast<float>(atof(row[9]));
|
||||||
sp[tempid].id = tempid;
|
sp.aoerange = static_cast<float>(atof(row[10]));
|
||||||
strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name));
|
sp.pushback = static_cast<float>(atof(row[11]));
|
||||||
strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1));
|
sp.pushup = static_cast<float>(atof(row[12]));
|
||||||
strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone));
|
sp.cast_time = atoi(row[13]);
|
||||||
strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast));
|
sp.recovery_time = atoi(row[14]);
|
||||||
strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts));
|
sp.recast_time = atoi(row[15]);
|
||||||
strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you));
|
sp.buffdurationformula = atoi(row[16]);
|
||||||
strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other));
|
sp.buffduration = atoi(row[17]);
|
||||||
strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades));
|
sp.AEDuration = atoi(row[18]);
|
||||||
|
sp.mana = atoi(row[19]);
|
||||||
|
|
||||||
sp[tempid].range=static_cast<float>(atof(row[9]));
|
int y = 0;
|
||||||
sp[tempid].aoerange=static_cast<float>(atof(row[10]));
|
for (y = 0; y < EFFECT_COUNT; y++)
|
||||||
sp[tempid].pushback=static_cast<float>(atof(row[11]));
|
sp.base[y] = atoi(row[20 + y]); // effect_base_value
|
||||||
sp[tempid].pushup=static_cast<float>(atof(row[12]));
|
|
||||||
sp[tempid].cast_time=atoi(row[13]);
|
|
||||||
sp[tempid].recovery_time=atoi(row[14]);
|
|
||||||
sp[tempid].recast_time=atoi(row[15]);
|
|
||||||
sp[tempid].buffdurationformula=atoi(row[16]);
|
|
||||||
sp[tempid].buffduration=atoi(row[17]);
|
|
||||||
sp[tempid].AEDuration=atoi(row[18]);
|
|
||||||
sp[tempid].mana=atoi(row[19]);
|
|
||||||
|
|
||||||
int y=0;
|
for (y = 0; y < EFFECT_COUNT; y++)
|
||||||
for(y=0; y< EFFECT_COUNT;y++)
|
sp.base2[y] = atoi(row[32 + y]); // effect_limit_value
|
||||||
sp[tempid].base[y]=atoi(row[20+y]); // effect_base_value
|
|
||||||
|
|
||||||
for(y=0; y < EFFECT_COUNT; y++)
|
for (y = 0; y < EFFECT_COUNT; y++)
|
||||||
sp[tempid].base2[y]=atoi(row[32+y]); // effect_limit_value
|
sp.max[y] = atoi(row[44 + y]);
|
||||||
|
|
||||||
for(y=0; y< EFFECT_COUNT;y++)
|
for (y = 0; y < 4; y++)
|
||||||
sp[tempid].max[y]=atoi(row[44+y]);
|
sp.components[y] = atoi(row[58 + y]);
|
||||||
|
|
||||||
for(y=0; y< 4;y++)
|
for (y = 0; y < 4; y++)
|
||||||
sp[tempid].components[y]=atoi(row[58+y]);
|
sp.component_counts[y] = atoi(row[62 + y]);
|
||||||
|
|
||||||
for(y=0; y< 4;y++)
|
for (y = 0; y < 4; y++)
|
||||||
sp[tempid].component_counts[y]=atoi(row[62+y]);
|
sp.NoexpendReagent[y] = atoi(row[66 + y]);
|
||||||
|
|
||||||
for(y=0; y< 4;y++)
|
for (y = 0; y < EFFECT_COUNT; y++)
|
||||||
sp[tempid].NoexpendReagent[y]=atoi(row[66+y]);
|
sp.formula[y] = atoi(row[70 + y]);
|
||||||
|
|
||||||
for(y=0; y< EFFECT_COUNT;y++)
|
sp.goodEffect = atoi(row[83]);
|
||||||
sp[tempid].formula[y]=atoi(row[70+y]);
|
sp.Activated = atoi(row[84]);
|
||||||
|
sp.resisttype = atoi(row[85]);
|
||||||
|
|
||||||
sp[tempid].goodEffect=atoi(row[83]);
|
for (y = 0; y < EFFECT_COUNT; y++)
|
||||||
sp[tempid].Activated=atoi(row[84]);
|
sp.effectid[y] = atoi(row[86 + y]);
|
||||||
sp[tempid].resisttype=atoi(row[85]);
|
|
||||||
|
|
||||||
for(y=0; y< EFFECT_COUNT;y++)
|
sp.targettype = (SpellTargetType)atoi(row[98]);
|
||||||
sp[tempid].effectid[y]=atoi(row[86+y]);
|
sp.basediff = atoi(row[99]);
|
||||||
|
|
||||||
sp[tempid].targettype = (SpellTargetType) atoi(row[98]);
|
|
||||||
sp[tempid].basediff=atoi(row[99]);
|
|
||||||
|
|
||||||
int tmp_skill = atoi(row[100]);;
|
int tmp_skill = atoi(row[100]);;
|
||||||
|
|
||||||
if (tmp_skill < 0 || tmp_skill > EQEmu::skills::HIGHEST_SKILL)
|
if (tmp_skill < 0 || tmp_skill > EQEmu::skills::HIGHEST_SKILL)
|
||||||
sp[tempid].skill = EQEmu::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated
|
sp.skill = EQEmu::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated
|
||||||
else
|
else
|
||||||
sp[tempid].skill = (EQEmu::skills::SkillType) tmp_skill;
|
sp.skill = (EQEmu::skills::SkillType) tmp_skill;
|
||||||
|
|
||||||
sp[tempid].zonetype=atoi(row[101]);
|
sp.zonetype = atoi(row[101]);
|
||||||
sp[tempid].EnvironmentType=atoi(row[102]);
|
sp.EnvironmentType = atoi(row[102]);
|
||||||
sp[tempid].TimeOfDay=atoi(row[103]);
|
sp.TimeOfDay = atoi(row[103]);
|
||||||
|
|
||||||
for(y=0; y < PLAYER_CLASS_COUNT;y++)
|
for (y = 0; y < PLAYER_CLASS_COUNT; y++)
|
||||||
sp[tempid].classes[y]=atoi(row[104+y]);
|
sp.classes[y] = atoi(row[104 + y]);
|
||||||
|
|
||||||
sp[tempid].CastingAnim=atoi(row[120]);
|
sp.CastingAnim = atoi(row[120]);
|
||||||
sp[tempid].SpellAffectIndex=atoi(row[123]);
|
sp.SpellAffectIndex = atoi(row[123]);
|
||||||
sp[tempid].disallow_sit=atoi(row[124]);
|
sp.disallow_sit = atoi(row[124]);
|
||||||
sp[tempid].diety_agnostic=atoi(row[125]);
|
sp.diety_agnostic = atoi(row[125]);
|
||||||
|
|
||||||
for (y = 0; y < 16; y++)
|
for (y = 0; y < 16; y++)
|
||||||
sp[tempid].deities[y]=atoi(row[126+y]);
|
sp.deities[y] = atoi(row[126 + y]);
|
||||||
|
|
||||||
sp[tempid].new_icon=atoi(row[144]);
|
sp.new_icon = atoi(row[144]);
|
||||||
sp[tempid].uninterruptable=atoi(row[146]) != 0;
|
sp.uninterruptable = atoi(row[146]) != 0;
|
||||||
sp[tempid].ResistDiff=atoi(row[147]);
|
sp.ResistDiff = atoi(row[147]);
|
||||||
sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0;
|
sp.dot_stacking_exempt = atoi(row[148]) != 0;
|
||||||
sp[tempid].RecourseLink = atoi(row[150]);
|
sp.RecourseLink = atoi(row[150]);
|
||||||
sp[tempid].no_partial_resist = atoi(row[151]) != 0;
|
sp.no_partial_resist = atoi(row[151]) != 0;
|
||||||
|
|
||||||
sp[tempid].short_buff_box = atoi(row[154]);
|
sp.short_buff_box = atoi(row[154]);
|
||||||
sp[tempid].descnum = atoi(row[155]);
|
sp.descnum = atoi(row[155]);
|
||||||
sp[tempid].typedescnum = atoi(row[156]);
|
sp.typedescnum = atoi(row[156]);
|
||||||
sp[tempid].effectdescnum = atoi(row[157]);
|
sp.effectdescnum = atoi(row[157]);
|
||||||
|
|
||||||
sp[tempid].npc_no_los = atoi(row[159]) != 0;
|
sp.npc_no_los = atoi(row[159]) != 0;
|
||||||
sp[tempid].reflectable = atoi(row[161]) != 0;
|
sp.reflectable = atoi(row[161]) != 0;
|
||||||
sp[tempid].bonushate=atoi(row[162]);
|
sp.bonushate = atoi(row[162]);
|
||||||
|
|
||||||
sp[tempid].ldon_trap = atoi(row[165]) != 0;
|
sp.ldon_trap = atoi(row[165]) != 0;
|
||||||
sp[tempid].EndurCost=atoi(row[166]);
|
sp.EndurCost = atoi(row[166]);
|
||||||
sp[tempid].EndurTimerIndex=atoi(row[167]);
|
sp.EndurTimerIndex = atoi(row[167]);
|
||||||
sp[tempid].IsDisciplineBuff = atoi(row[168]) != 0;
|
sp.IsDisciplineBuff = atoi(row[168]) != 0;
|
||||||
sp[tempid].HateAdded=atoi(row[173]);
|
sp.HateAdded = atoi(row[173]);
|
||||||
sp[tempid].EndurUpkeep=atoi(row[174]);
|
sp.EndurUpkeep = atoi(row[174]);
|
||||||
sp[tempid].numhitstype = atoi(row[175]);
|
sp.numhitstype = atoi(row[175]);
|
||||||
sp[tempid].numhits = atoi(row[176]);
|
sp.numhits = atoi(row[176]);
|
||||||
sp[tempid].pvpresistbase=atoi(row[177]);
|
sp.pvpresistbase = atoi(row[177]);
|
||||||
sp[tempid].pvpresistcalc=atoi(row[178]);
|
sp.pvpresistcalc = atoi(row[178]);
|
||||||
sp[tempid].pvpresistcap=atoi(row[179]);
|
sp.pvpresistcap = atoi(row[179]);
|
||||||
sp[tempid].spell_category=atoi(row[180]);
|
sp.spell_category = atoi(row[180]);
|
||||||
sp[tempid].pcnpc_only_flag=atoi(row[183]);
|
sp.pcnpc_only_flag = atoi(row[183]);
|
||||||
sp[tempid].cast_not_standing = atoi(row[184]) != 0;
|
sp.cast_not_standing = atoi(row[184]) != 0;
|
||||||
sp[tempid].can_mgb=atoi(row[185]);
|
sp.can_mgb = atoi(row[185]);
|
||||||
sp[tempid].dispel_flag = atoi(row[186]);
|
sp.dispel_flag = atoi(row[186]);
|
||||||
sp[tempid].MinResist = atoi(row[189]);
|
sp.MinResist = atoi(row[189]);
|
||||||
sp[tempid].MaxResist = atoi(row[190]);
|
sp.MaxResist = atoi(row[190]);
|
||||||
sp[tempid].viral_targets = atoi(row[191]);
|
sp.viral_targets = atoi(row[191]);
|
||||||
sp[tempid].viral_timer = atoi(row[192]);
|
sp.viral_timer = atoi(row[192]);
|
||||||
sp[tempid].NimbusEffect = atoi(row[193]);
|
sp.NimbusEffect = atoi(row[193]);
|
||||||
sp[tempid].directional_start = static_cast<float>(atoi(row[194]));
|
sp.directional_start = static_cast<float>(atoi(row[194]));
|
||||||
sp[tempid].directional_end = static_cast<float>(atoi(row[195]));
|
sp.directional_end = static_cast<float>(atoi(row[195]));
|
||||||
sp[tempid].sneak = atoi(row[196]) != 0;
|
sp.sneak = atoi(row[196]) != 0;
|
||||||
sp[tempid].not_focusable = atoi(row[197]) != 0;
|
sp.not_focusable = atoi(row[197]) != 0;
|
||||||
sp[tempid].no_detrimental_spell_aggro = atoi(row[198]) != 0;
|
sp.no_detrimental_spell_aggro = atoi(row[198]) != 0;
|
||||||
sp[tempid].suspendable = atoi(row[200]) != 0;
|
sp.suspendable = atoi(row[200]) != 0;
|
||||||
sp[tempid].viral_range = atoi(row[201]);
|
sp.viral_range = atoi(row[201]);
|
||||||
sp[tempid].songcap = atoi(row[202]);
|
sp.songcap = atoi(row[202]);
|
||||||
sp[tempid].no_block = atoi(row[205]);
|
sp.no_block = atoi(row[205]);
|
||||||
sp[tempid].spellgroup=atoi(row[207]);
|
sp.spellgroup = atoi(row[207]);
|
||||||
sp[tempid].rank = atoi(row[208]);
|
sp.rank = atoi(row[208]);
|
||||||
sp[tempid].no_resist=atoi(row[209]);
|
sp.no_resist = atoi(row[209]);
|
||||||
sp[tempid].CastRestriction = atoi(row[211]);
|
sp.CastRestriction = atoi(row[211]);
|
||||||
sp[tempid].AllowRest = atoi(row[212]) != 0;
|
sp.AllowRest = atoi(row[212]) != 0;
|
||||||
sp[tempid].InCombat = atoi(row[213]) != 0;
|
sp.InCombat = atoi(row[213]) != 0;
|
||||||
sp[tempid].OutofCombat = atoi(row[214]) != 0;
|
sp.OutofCombat = atoi(row[214]) != 0;
|
||||||
sp[tempid].override_crit_chance = atoi(row[217]);
|
sp.override_crit_chance = atoi(row[217]);
|
||||||
sp[tempid].aemaxtargets = atoi(row[218]);
|
sp.aemaxtargets = atoi(row[218]);
|
||||||
sp[tempid].no_heal_damage_item_mod = atoi(row[219]);
|
sp.no_heal_damage_item_mod = atoi(row[219]);
|
||||||
sp[tempid].persistdeath = atoi(row[224]) != 0;
|
sp.persistdeath = atoi(row[224]) != 0;
|
||||||
sp[tempid].min_dist = atof(row[227]);
|
sp.min_dist = atof(row[227]);
|
||||||
sp[tempid].min_dist_mod = atof(row[228]);
|
sp.min_dist_mod = atof(row[228]);
|
||||||
sp[tempid].max_dist = atof(row[229]);
|
sp.max_dist = atof(row[229]);
|
||||||
sp[tempid].max_dist_mod = atof(row[230]);
|
sp.max_dist_mod = atof(row[230]);
|
||||||
sp[tempid].min_range = static_cast<float>(atoi(row[231]));
|
sp.min_range = static_cast<float>(atoi(row[231]));
|
||||||
sp[tempid].no_remove = atoi(row[232]) != 0;
|
sp.no_remove = atoi(row[232]) != 0;
|
||||||
sp[tempid].DamageShieldType = 0;
|
sp.DamageShieldType = LoadDamageShieldType(sp.id); //ideally we could do this with a simple join but we need to formalize the table first.
|
||||||
|
on_load(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadDamageShieldTypes(sp, max_spells);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SharedDatabase::GetMaxBaseDataLevel() {
|
int SharedDatabase::GetMaxBaseDataLevel() {
|
||||||
|
|||||||
+3
-2
@@ -140,9 +140,10 @@ class SharedDatabase : public Database
|
|||||||
uint8 GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level);
|
uint8 GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level);
|
||||||
|
|
||||||
int GetMaxSpellID();
|
int GetMaxSpellID();
|
||||||
|
int GetSpellCount();
|
||||||
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
|
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
|
||||||
void LoadSpells(void *data, int max_spells);
|
void LoadSpells(std::function<void(const SPDat_Spell_Struct & sp)> on_load);
|
||||||
void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID);
|
int LoadDamageShieldType(int spell_id);
|
||||||
|
|
||||||
int GetMaxBaseDataLevel();
|
int GetMaxBaseDataLevel();
|
||||||
bool LoadBaseData(const std::string &prefix);
|
bool LoadBaseData(const std::string &prefix);
|
||||||
|
|||||||
+1
-1
@@ -607,7 +607,7 @@ typedef enum {
|
|||||||
#define SE_LimitSpellGroup 385 // implemented - Limits to spell group(ie type 3 reuse reduction augs that are class specific and thus all share s SG)
|
#define SE_LimitSpellGroup 385 // implemented - Limits to spell group(ie type 3 reuse reduction augs that are class specific and thus all share s SG)
|
||||||
#define SE_CastOnCurer 386 // implemented - Casts a spell on the person curing
|
#define SE_CastOnCurer 386 // implemented - Casts a spell on the person curing
|
||||||
#define SE_CastOnCure 387 // implemented - Casts a spell on the cured person
|
#define SE_CastOnCure 387 // implemented - Casts a spell on the cured person
|
||||||
//#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
|
#define SE_SummonCorpseZone 388 // implemented - summons a corpse from any zone(nec AA)
|
||||||
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
|
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
|
||||||
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
|
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
|
||||||
#define SE_LimitManaMax 391 // implemented
|
#define SE_LimitManaMax 391 // implemented
|
||||||
|
|||||||
+8
-4
@@ -129,13 +129,17 @@ void Timer::SetTimer(uint32 set_timer_time) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Timer::GetRemainingTime() const {
|
uint32 Timer::GetRemainingTime() const
|
||||||
|
{
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
if (current_time - start_time > timer_time)
|
if (current_time - start_time > timer_time) {
|
||||||
return 0;
|
return 0;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return (start_time + timer_time) - current_time;
|
return (start_time + timer_time) - current_time;
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -34,10 +34,10 @@
|
|||||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9146
|
#define CURRENT_BINARY_DATABASE_VERSION 9152
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027
|
||||||
#else
|
#else
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+23
-16
@@ -19,28 +19,35 @@
|
|||||||
#include "spells.h"
|
#include "spells.h"
|
||||||
#include "../common/global_define.h"
|
#include "../common/global_define.h"
|
||||||
#include "../common/shareddb.h"
|
#include "../common/shareddb.h"
|
||||||
#include "../common/ipc_mutex.h"
|
|
||||||
#include "../common/memory_mapped_file.h"
|
|
||||||
#include "../common/eqemu_exception.h"
|
|
||||||
#include "../common/spdat.h"
|
#include "../common/spdat.h"
|
||||||
|
#include "../common/shared/shared_memory.h"
|
||||||
|
#include "../common/shared/shared_memory_map.h"
|
||||||
|
|
||||||
|
namespace eqs = eq::shared;
|
||||||
|
|
||||||
void LoadSpells(SharedDatabase *database, const std::string &prefix) {
|
void LoadSpells(SharedDatabase *database, const std::string &prefix) {
|
||||||
EQEmu::IPCMutex mutex("spells");
|
int records = database->GetSpellCount();
|
||||||
mutex.Lock();
|
int max_spell_id = database->GetMaxSpellID() + 1;
|
||||||
int records = database->GetMaxSpellID() + 1;
|
auto size = records * sizeof(SPDat_Spell_Struct) * 125 / 100 + (64 * 1024);
|
||||||
if(records == 0) {
|
eqs::shared_memory shared("shared/spells", size);
|
||||||
EQ_EXCEPT("Shared Memory", "Unable to get any spells from the database.");
|
|
||||||
|
auto spells_result = shared.map<eqs::unordered_map<int, SPDat_Spell_Struct>>("spells");
|
||||||
|
if (!spells_result) {
|
||||||
|
//todo: get rid of the exceptions entirely.
|
||||||
|
EQ_EXCEPT("Shared Memory", "Unable to map shared memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size = records * sizeof(SPDat_Spell_Struct) + sizeof(uint32);
|
auto max_spell_id_result = shared.map<int>("max_spell_id");
|
||||||
|
if (!max_spell_id_result) {
|
||||||
|
EQ_EXCEPT("Shared Memory", "Unable to map shared memory");
|
||||||
|
}
|
||||||
|
|
||||||
auto Config = EQEmuConfig::get();
|
eqs::unordered_map<int, SPDat_Spell_Struct>& spells_shm = spells_result.value();
|
||||||
std::string file_name = Config->SharedMemDir + prefix + std::string("spells");
|
int& max_spell_id_shm = max_spell_id_result.value();
|
||||||
EQEmu::MemoryMappedFile mmf(file_name, size);
|
max_spell_id_shm = max_spell_id;
|
||||||
mmf.ZeroFile();
|
|
||||||
|
|
||||||
void *ptr = mmf.Get();
|
database->LoadSpells([&spells_shm](const SPDat_Spell_Struct &spell) {
|
||||||
database->LoadSpells(ptr, records);
|
spells_shm.insert_or_assign(spell.id, spell);
|
||||||
mutex.Unlock();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Submodule
+1
Submodule submodules/expected added at 3d741708b9
+17
-12
@@ -47,8 +47,13 @@ ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string in
|
|||||||
|
|
||||||
Moderated = false;
|
Moderated = false;
|
||||||
|
|
||||||
LogInfo("New ChatChannel created: Name: [[{}]], Owner: [[{}]], Password: [[{}]], MinStatus: [{}]",
|
LogDebug(
|
||||||
Name.c_str(), Owner.c_str(), Password.c_str(), MinimumStatus);
|
"New ChatChannel created: Name: [[{}]], Owner: [[{}]], Password: [[{}]], MinStatus: [{}]",
|
||||||
|
Name.c_str(),
|
||||||
|
Owner.c_str(),
|
||||||
|
Password.c_str(),
|
||||||
|
MinimumStatus
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +159,7 @@ void ChatChannelList::SendAllChannels(Client *c) {
|
|||||||
|
|
||||||
void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
|
void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
|
||||||
|
|
||||||
LogInfo("RemoveChannel([{}])", Channel->GetName().c_str());
|
LogDebug("RemoveChannel ([{}])", Channel->GetName().c_str());
|
||||||
|
|
||||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||||
|
|
||||||
@@ -175,7 +180,7 @@ void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
|
|||||||
|
|
||||||
void ChatChannelList::RemoveAllChannels() {
|
void ChatChannelList::RemoveAllChannels() {
|
||||||
|
|
||||||
LogInfo("RemoveAllChannels");
|
LogDebug("RemoveAllChannels");
|
||||||
|
|
||||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||||
|
|
||||||
@@ -242,7 +247,7 @@ void ChatChannel::AddClient(Client *c) {
|
|||||||
|
|
||||||
int AccountStatus = c->GetAccountStatus();
|
int AccountStatus = c->GetAccountStatus();
|
||||||
|
|
||||||
LogInfo("Adding [{}] to channel [{}]", c->GetName().c_str(), Name.c_str());
|
LogDebug("Adding [{}] to channel [{}]", c->GetName().c_str(), Name.c_str());
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||||
|
|
||||||
@@ -267,7 +272,7 @@ bool ChatChannel::RemoveClient(Client *c) {
|
|||||||
|
|
||||||
if(!c) return false;
|
if(!c) return false;
|
||||||
|
|
||||||
LogInfo("RemoveClient [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str());
|
LogDebug("RemoveClient [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str());
|
||||||
|
|
||||||
bool HideMe = c->GetHideMe();
|
bool HideMe = c->GetHideMe();
|
||||||
|
|
||||||
@@ -304,7 +309,7 @@ bool ChatChannel::RemoveClient(Client *c) {
|
|||||||
if((Password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0))
|
if((Password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
LogInfo("Starting delete timer for empty password protected channel [{}]", Name.c_str());
|
LogDebug("Starting delete timer for empty password protected channel [{}]", Name.c_str());
|
||||||
|
|
||||||
DeleteTimer.Start(RuleI(Channels, DeleteTimer) * 60000);
|
DeleteTimer.Start(RuleI(Channels, DeleteTimer) * 60000);
|
||||||
}
|
}
|
||||||
@@ -402,7 +407,7 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
|
|||||||
|
|
||||||
if(ChannelClient)
|
if(ChannelClient)
|
||||||
{
|
{
|
||||||
LogInfo("Sending message to [{}] from [{}]",
|
LogDebug("Sending message to [{}] from [{}]",
|
||||||
ChannelClient->GetName().c_str(), Sender->GetName().c_str());
|
ChannelClient->GetName().c_str(), Sender->GetName().c_str());
|
||||||
|
|
||||||
if (cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())].length() == 0) {
|
if (cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())].length() == 0) {
|
||||||
@@ -505,7 +510,7 @@ ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("AddClient to channel [[{}]] with password [[{}]]", NormalisedName.c_str(), Password.c_str());
|
LogDebug("AddClient to channel [[{}]] with password [[{}]]", NormalisedName.c_str(), Password.c_str());
|
||||||
|
|
||||||
ChatChannel *RequiredChannel = FindChannel(NormalisedName);
|
ChatChannel *RequiredChannel = FindChannel(NormalisedName);
|
||||||
|
|
||||||
@@ -581,7 +586,7 @@ void ChatChannelList::Process() {
|
|||||||
|
|
||||||
if(CurrentChannel && CurrentChannel->ReadyToDelete()) {
|
if(CurrentChannel && CurrentChannel->ReadyToDelete()) {
|
||||||
|
|
||||||
LogInfo("Empty temporary password protected channel [{}] being destroyed",
|
LogDebug("Empty temporary password protected channel [{}] being destroyed",
|
||||||
CurrentChannel->GetName().c_str());
|
CurrentChannel->GetName().c_str());
|
||||||
|
|
||||||
RemoveChannel(CurrentChannel);
|
RemoveChannel(CurrentChannel);
|
||||||
@@ -597,7 +602,7 @@ void ChatChannel::AddInvitee(const std::string &Invitee)
|
|||||||
if (!IsInvitee(Invitee)) {
|
if (!IsInvitee(Invitee)) {
|
||||||
Invitees.push_back(Invitee);
|
Invitees.push_back(Invitee);
|
||||||
|
|
||||||
LogInfo("Added [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
|
LogDebug("Added [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -608,7 +613,7 @@ void ChatChannel::RemoveInvitee(std::string Invitee)
|
|||||||
|
|
||||||
if(it != std::end(Invitees)) {
|
if(it != std::end(Invitees)) {
|
||||||
Invitees.erase(it);
|
Invitees.erase(it);
|
||||||
LogInfo("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
|
LogDebug("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-14
@@ -235,7 +235,7 @@ std::vector<std::string> ParseRecipients(std::string RecipientString) {
|
|||||||
|
|
||||||
static void ProcessMailTo(Client *c, std::string MailMessage) {
|
static void ProcessMailTo(Client *c, std::string MailMessage) {
|
||||||
|
|
||||||
LogInfo("MAILTO: From [{}], [{}]", c->MailBoxName().c_str(), MailMessage.c_str());
|
LogDebug("MAILTO: From [{}], [{}]", c->MailBoxName().c_str(), MailMessage.c_str());
|
||||||
|
|
||||||
std::vector<std::string> Recipients;
|
std::vector<std::string> Recipients;
|
||||||
|
|
||||||
@@ -304,7 +304,7 @@ static void ProcessMailTo(Client *c, std::string MailMessage) {
|
|||||||
|
|
||||||
if (!database.SendMail(Recipient, c->MailBoxName(), Subject, Body, RecipientsString)) {
|
if (!database.SendMail(Recipient, c->MailBoxName(), Subject, Body, RecipientsString)) {
|
||||||
|
|
||||||
LogInfo("Failed in SendMail([{}], [{}], [{}], [{}])", Recipient.c_str(),
|
LogError("Failed in SendMail([{}], [{}], [{}], [{}])", Recipient.c_str(),
|
||||||
c->MailBoxName().c_str(), Subject.c_str(), RecipientsString.c_str());
|
c->MailBoxName().c_str(), Subject.c_str(), RecipientsString.c_str());
|
||||||
|
|
||||||
int PacketLength = 10 + Recipient.length() + Subject.length();
|
int PacketLength = 10 + Recipient.length() + Subject.length();
|
||||||
@@ -556,6 +556,17 @@ void Client::CloseConnection() {
|
|||||||
ClientStream->ReleaseFromUse();
|
ClientStream->ReleaseFromUse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clientlist::CheckForStaleConnectionsAll()
|
||||||
|
{
|
||||||
|
LogDebug("Checking for stale connections");
|
||||||
|
|
||||||
|
auto it = ClientChatConnections.begin();
|
||||||
|
while (it != ClientChatConnections.end()) {
|
||||||
|
(*it)->SendKeepAlive();
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Clientlist::CheckForStaleConnections(Client *c) {
|
void Clientlist::CheckForStaleConnections(Client *c) {
|
||||||
|
|
||||||
if (!c) return;
|
if (!c) return;
|
||||||
@@ -634,10 +645,12 @@ void Clientlist::Process()
|
|||||||
//
|
//
|
||||||
std::string::size_type LastPeriod = MailBoxString.find_last_of(".");
|
std::string::size_type LastPeriod = MailBoxString.find_last_of(".");
|
||||||
|
|
||||||
if (LastPeriod == std::string::npos)
|
if (LastPeriod == std::string::npos) {
|
||||||
CharacterName = MailBoxString;
|
CharacterName = MailBoxString;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
CharacterName = MailBoxString.substr(LastPeriod + 1);
|
CharacterName = MailBoxString.substr(LastPeriod + 1);
|
||||||
|
}
|
||||||
|
|
||||||
LogInfo("Received login for user [{}] with key [{}]",
|
LogInfo("Received login for user [{}] with key [{}]",
|
||||||
MailBox, Key);
|
MailBox, Key);
|
||||||
@@ -652,8 +665,9 @@ void Clientlist::Process()
|
|||||||
|
|
||||||
database.GetAccountStatus((*it));
|
database.GetAccountStatus((*it));
|
||||||
|
|
||||||
if ((*it)->GetConnectionType() == ConnectionTypeCombined)
|
if ((*it)->GetConnectionType() == ConnectionTypeCombined) {
|
||||||
(*it)->SendFriends();
|
(*it)->SendFriends();
|
||||||
|
}
|
||||||
|
|
||||||
(*it)->SendMailBoxes();
|
(*it)->SendMailBoxes();
|
||||||
|
|
||||||
@@ -865,7 +879,9 @@ void Clientlist::CloseAllConnections() {
|
|||||||
void Client::AddCharacter(int CharID, const char *CharacterName, int Level) {
|
void Client::AddCharacter(int CharID, const char *CharacterName, int Level) {
|
||||||
|
|
||||||
if (!CharacterName) return;
|
if (!CharacterName) return;
|
||||||
LogInfo("Adding character [{}] with ID [{}] for [{}]", CharacterName, CharID, GetName().c_str());
|
|
||||||
|
LogDebug("Adding character [{}] with ID [{}] for [{}]", CharacterName, CharID, GetName().c_str());
|
||||||
|
|
||||||
CharacterEntry NewCharacter;
|
CharacterEntry NewCharacter;
|
||||||
NewCharacter.CharID = CharID;
|
NewCharacter.CharID = CharID;
|
||||||
NewCharacter.Name = CharacterName;
|
NewCharacter.Name = CharacterName;
|
||||||
@@ -874,6 +890,10 @@ void Client::AddCharacter(int CharID, const char *CharacterName, int Level) {
|
|||||||
Characters.push_back(NewCharacter);
|
Characters.push_back(NewCharacter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::SendKeepAlive() {
|
||||||
|
QueuePacket(new EQApplicationPacket(OP_SessionReady, 0));
|
||||||
|
}
|
||||||
|
|
||||||
void Client::SendMailBoxes() {
|
void Client::SendMailBoxes() {
|
||||||
|
|
||||||
int Count = Characters.size();
|
int Count = Characters.size();
|
||||||
@@ -930,7 +950,7 @@ void Client::AddToChannelList(ChatChannel *JoinedChannel) {
|
|||||||
for (int i = 0; i < MAX_JOINED_CHANNELS; i++)
|
for (int i = 0; i < MAX_JOINED_CHANNELS; i++)
|
||||||
if (JoinedChannels[i] == nullptr) {
|
if (JoinedChannels[i] == nullptr) {
|
||||||
JoinedChannels[i] = JoinedChannel;
|
JoinedChannels[i] = JoinedChannel;
|
||||||
LogInfo("Added Channel [{}] to slot [{}] for [{}]", JoinedChannel->GetName().c_str(), i + 1, GetName().c_str());
|
LogDebug("Added Channel [{}] to slot [{}] for [{}]", JoinedChannel->GetName().c_str(), i + 1, GetName().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2346,17 +2366,16 @@ void Client::SendFriends() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Client::MailBoxName() {
|
std::string Client::MailBoxName()
|
||||||
|
{
|
||||||
if ((Characters.empty()) || (CurrentMailBox > (Characters.size() - 1)))
|
if ((Characters.empty()) || (CurrentMailBox > (Characters.size() - 1))) {
|
||||||
{
|
LogDebug("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
||||||
LogInfo("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
|
||||||
CurrentMailBox, Characters.size());
|
CurrentMailBox, Characters.size());
|
||||||
|
|
||||||
return "";
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
LogDebug("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
||||||
CurrentMailBox, Characters.size());
|
CurrentMailBox, Characters.size());
|
||||||
|
|
||||||
return Characters[CurrentMailBox].Name;
|
return Characters[CurrentMailBox].Name;
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ public:
|
|||||||
void SendFriends();
|
void SendFriends();
|
||||||
int GetCharID();
|
int GetCharID();
|
||||||
void SendUptime();
|
void SendUptime();
|
||||||
|
void SendKeepAlive();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int CurrentMailBox;
|
unsigned int CurrentMailBox;
|
||||||
@@ -183,6 +184,7 @@ public:
|
|||||||
void Process();
|
void Process();
|
||||||
void CloseAllConnections();
|
void CloseAllConnections();
|
||||||
Client *FindCharacter(std::string CharacterName);
|
Client *FindCharacter(std::string CharacterName);
|
||||||
|
void CheckForStaleConnectionsAll();
|
||||||
void CheckForStaleConnections(Client *c);
|
void CheckForStaleConnections(Client *c);
|
||||||
Client *IsCharacterOnline(std::string CharacterName);
|
Client *IsCharacterOnline(std::string CharacterName);
|
||||||
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
||||||
|
|||||||
+3
-3
@@ -108,7 +108,7 @@ void Database::GetAccountStatus(Client *client)
|
|||||||
{
|
{
|
||||||
|
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"SELECT `status`, `hideme`, `karma`, `revoked` FROM `account` WHERE `id` = '%i' LIMIT 1",
|
"SELECT `status`, `hideme`, `karma`, `revoked` FROM `account` WHERE `id` = %i LIMIT 1",
|
||||||
client->GetAccountID()
|
client->GetAccountID()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ int Database::FindAccount(const char *characterName, Client *client)
|
|||||||
|
|
||||||
query = StringFormat(
|
query = StringFormat(
|
||||||
"SELECT `id`, `name`, `level` FROM `character_data` "
|
"SELECT `id`, `name`, `level` FROM `character_data` "
|
||||||
"WHERE `account_id` = %i AND `name` != '%s'",
|
"WHERE `account_id` = %i AND `name` != '%s' AND deleted_at is NULL",
|
||||||
accountID, characterName
|
accountID, characterName
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ void Database::SendHeaders(Client *client)
|
|||||||
int unknownField3 = 1;
|
int unknownField3 = 1;
|
||||||
int characterID = FindCharacter(client->MailBoxName().c_str());
|
int characterID = FindCharacter(client->MailBoxName().c_str());
|
||||||
|
|
||||||
LogInfo("Sendheaders for [{}], CharID is [{}]", client->MailBoxName().c_str(), characterID);
|
LogDebug("Sendheaders for [{}], CharID is [{}]", client->MailBoxName().c_str(), characterID);
|
||||||
|
|
||||||
if (characterID <= 0) {
|
if (characterID <= 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+14
-6
@@ -70,6 +70,7 @@ int main() {
|
|||||||
// Check every minute for unused channels we can delete
|
// Check every minute for unused channels we can delete
|
||||||
//
|
//
|
||||||
Timer ChannelListProcessTimer(60000);
|
Timer ChannelListProcessTimer(60000);
|
||||||
|
Timer ClientConnectionPruneTimer(60000);
|
||||||
|
|
||||||
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
|
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
|
||||||
|
|
||||||
@@ -144,20 +145,27 @@ int main() {
|
|||||||
|
|
||||||
worldserver = new WorldServer;
|
worldserver = new WorldServer;
|
||||||
|
|
||||||
while(RunLoops) {
|
auto loop_fn = [&](EQ::Timer* t) {
|
||||||
|
|
||||||
Timer::SetCurrentTime();
|
Timer::SetCurrentTime();
|
||||||
|
|
||||||
g_Clientlist->Process();
|
g_Clientlist->Process();
|
||||||
|
|
||||||
if(ChannelListProcessTimer.Check())
|
if (ChannelListProcessTimer.Check()) {
|
||||||
ChannelList->Process();
|
ChannelList->Process();
|
||||||
|
|
||||||
EQ::EventLoop::Get().Process();
|
|
||||||
|
|
||||||
Sleep(5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ClientConnectionPruneTimer.Check()) {
|
||||||
|
g_Clientlist->CheckForStaleConnectionsAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EQ::Timer process_timer(loop_fn);
|
||||||
|
process_timer.Start(32, true);
|
||||||
|
|
||||||
|
EQ::EventLoop::Get().Run();
|
||||||
|
|
||||||
ChannelList->RemoveAllChannels();
|
ChannelList->RemoveAllChannels();
|
||||||
|
|
||||||
g_Clientlist->CloseAllConnections();
|
g_Clientlist->CloseAllConnections();
|
||||||
|
|||||||
+1
-1
@@ -61,7 +61,7 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
|
|||||||
ServerPacket tpack(opcode, p);
|
ServerPacket tpack(opcode, p);
|
||||||
ServerPacket *pack = &tpack;
|
ServerPacket *pack = &tpack;
|
||||||
|
|
||||||
LogInfo("Received Opcode: {:#04x}", opcode);
|
LogNetcode("Received Opcode: {:#04x}", opcode);
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ OP_LDoNButton=0x596e
|
|||||||
OP_SetStartCity=0x7936 # Was 0x2d1b
|
OP_SetStartCity=0x7936 # Was 0x2d1b
|
||||||
OP_VoiceMacroIn=0x202e
|
OP_VoiceMacroIn=0x202e
|
||||||
OP_VoiceMacroOut=0x3920
|
OP_VoiceMacroOut=0x3920
|
||||||
OP_ItemViewUnknown=0x0b64
|
OP_ItemAdvancedLoreText=0x0b64
|
||||||
OP_VetRewardsAvaliable=0x05d9
|
OP_VetRewardsAvaliable=0x05d9
|
||||||
OP_VetClaimRequest=0xcdde
|
OP_VetClaimRequest=0xcdde
|
||||||
OP_VetClaimReply=0x361b
|
OP_VetClaimReply=0x361b
|
||||||
|
|||||||
@@ -448,6 +448,8 @@ OP_FinishWindow2=0x40ef
|
|||||||
OP_ItemVerifyRequest=0x189c
|
OP_ItemVerifyRequest=0x189c
|
||||||
OP_ItemVerifyReply=0x097b
|
OP_ItemVerifyReply=0x097b
|
||||||
|
|
||||||
|
OP_ItemAdvancedLoreText=0x023b
|
||||||
|
|
||||||
# merchant stuff
|
# merchant stuff
|
||||||
OP_ShopPlayerSell=0x791b
|
OP_ShopPlayerSell=0x791b
|
||||||
OP_ShopRequest=0x4fed
|
OP_ShopRequest=0x4fed
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ OP_LDoNButton=0x41b5 # C
|
|||||||
OP_SetStartCity=0x7bf6 # C
|
OP_SetStartCity=0x7bf6 # C
|
||||||
OP_VoiceMacroIn=0x31b1 # C
|
OP_VoiceMacroIn=0x31b1 # C
|
||||||
OP_VoiceMacroOut=0x7880 # C
|
OP_VoiceMacroOut=0x7880 # C
|
||||||
OP_ItemViewUnknown=0x21c7 # C
|
OP_ItemAdvancedLoreText=0x21c7 # C
|
||||||
OP_VetRewardsAvaliable=0x4e4e # C
|
OP_VetRewardsAvaliable=0x4e4e # C
|
||||||
OP_VetClaimRequest=0x771f # C
|
OP_VetClaimRequest=0x771f # C
|
||||||
OP_VetClaimReply=0x2f95 # C
|
OP_VetClaimReply=0x2f95 # C
|
||||||
|
|||||||
@@ -576,7 +576,7 @@ OP_QueryResponseThing=0x0000 #
|
|||||||
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
|
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
|
||||||
OP_LoginUnknown1=0x22cf
|
OP_LoginUnknown1=0x22cf
|
||||||
OP_LoginUnknown2=0x43ba
|
OP_LoginUnknown2=0x43ba
|
||||||
OP_ItemViewUnknown=0x4db4
|
OP_ItemAdvancedLoreText=0x4db4
|
||||||
|
|
||||||
#Petition Opcodes
|
#Petition Opcodes
|
||||||
OP_PetitionSearch=0x0000 #search term for petition
|
OP_PetitionSearch=0x0000 #search term for petition
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ OP_LDoNButton=0x1031 # C
|
|||||||
OP_SetStartCity=0x68f0 # C
|
OP_SetStartCity=0x68f0 # C
|
||||||
OP_VoiceMacroIn=0x1524 # C
|
OP_VoiceMacroIn=0x1524 # C
|
||||||
OP_VoiceMacroOut=0x1d99 # C
|
OP_VoiceMacroOut=0x1d99 # C
|
||||||
OP_ItemViewUnknown=0x4eb3 # C
|
OP_ItemAdvancedLoreText=0x4eb3 # C
|
||||||
OP_VetRewardsAvaliable=0x0baa # C Mispelled?
|
OP_VetRewardsAvaliable=0x0baa # C Mispelled?
|
||||||
OP_VetClaimRequest=0x34f8 # C
|
OP_VetClaimRequest=0x34f8 # C
|
||||||
OP_VetClaimReply=0x6a5d # C
|
OP_VetClaimReply=0x6a5d # C
|
||||||
|
|||||||
+179
-224
@@ -52,6 +52,10 @@ if (-e "eqemu_server_skip_update.txt") {
|
|||||||
$skip_self_update_check = 1;
|
$skip_self_update_check = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-e "eqemu_server_skip_maps_update.txt") {
|
||||||
|
$skip_self_maps_update_check = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#::: Check for script self update
|
#::: Check for script self update
|
||||||
check_xml_to_json_conversion() if $ARGV[0] eq "convert_xml";
|
check_xml_to_json_conversion() if $ARGV[0] eq "convert_xml";
|
||||||
do_self_update_check_routine() if !$skip_self_update_check;
|
do_self_update_check_routine() if !$skip_self_update_check;
|
||||||
@@ -460,7 +464,7 @@ sub do_installer_routines {
|
|||||||
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
|
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
map_files_fetch_bulk();
|
map_files_fetch_bulk() if !$skip_self_maps_update_check;
|
||||||
opcodes_fetch();
|
opcodes_fetch();
|
||||||
plugins_fetch();
|
plugins_fetch();
|
||||||
quest_files_fetch();
|
quest_files_fetch();
|
||||||
@@ -493,9 +497,7 @@ sub do_installer_routines {
|
|||||||
|
|
||||||
#::: Download PEQ latest
|
#::: Download PEQ latest
|
||||||
fetch_peq_db_full();
|
fetch_peq_db_full();
|
||||||
print "[Database] Fetching Latest Database Updates...\n";
|
print "[Database] Fetching and Applying Latest Database Updates...\n";
|
||||||
main_db_management();
|
|
||||||
print "[Database] Applying Latest Database Updates...\n";
|
|
||||||
main_db_management();
|
main_db_management();
|
||||||
|
|
||||||
remove_duplicate_rule_values();
|
remove_duplicate_rule_values();
|
||||||
@@ -531,58 +533,76 @@ sub check_for_world_bootup_database_update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$binary_database_version = trim($db_version[1]);
|
$binary_database_version = trim($db_version[1]);
|
||||||
$local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
|
$local_database_version = get_main_db_version();
|
||||||
|
|
||||||
#::: Bots
|
|
||||||
$bots_binary_version = trim($db_version[2]);
|
|
||||||
if ($bots_binary_version > 0) {
|
|
||||||
$bots_local_db_version = get_bots_db_version();
|
|
||||||
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
|
||||||
|
|
||||||
if ($bots_local_db_version < $bots_binary_version && $ARGV[0] eq "ran_from_world") {
|
|
||||||
print "[Update] Bots Database not up to date with binaries... Automatically updating...\n";
|
|
||||||
print "[Update] Issuing database backup first...\n";
|
|
||||||
database_dump_compress();
|
|
||||||
print "[Update] Updating bots database...\n";
|
|
||||||
sleep(1);
|
|
||||||
bots_db_management();
|
|
||||||
run_database_check();
|
|
||||||
print "[Update] Continuing bootup\n";
|
|
||||||
analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
|
|
||||||
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print "[Update] Bots database up to Date: Continuing World Bootup...\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") {
|
if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") {
|
||||||
print "[Update] Database up to date...\n";
|
print "[Update] Database up to date...\n";
|
||||||
|
if (trim($db_version[2]) == 0) {
|
||||||
|
print "[Update] Continuing bootup\n";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
||||||
if ($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world") {
|
if ($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world") {
|
||||||
print "[Update] Database not up to date with binaries... Automatically updating...\n";
|
print "[Update] Database not up to date with binaries... Automatically updating...\n";
|
||||||
print "[Update] Issuing database backup first...\n";
|
print "[Update] Issuing database backup first...\n";
|
||||||
database_dump_compress();
|
database_dump_compress();
|
||||||
|
$db_already_backed_up = 1;
|
||||||
print "[Update] Updating database...\n";
|
print "[Update] Updating database...\n";
|
||||||
sleep(1);
|
sleep(1);
|
||||||
main_db_management();
|
main_db_management();
|
||||||
main_db_management();
|
|
||||||
print "[Update] Continuing bootup\n";
|
|
||||||
analytics_insertion("auto database upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
|
|
||||||
|
|
||||||
exit;
|
analytics_insertion("auto database upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
#::: Make sure that we didn't pass any arugments to the script
|
#::: Make sure that we didn't pass any arugments to the script
|
||||||
else {
|
else {
|
||||||
|
if ($local_database_version > $binary_database_version) {
|
||||||
|
print "[Update] Database version is ahead of current binaries...\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; }
|
if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; }
|
||||||
show_menu_prompt();
|
show_menu_prompt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#::: Bots
|
||||||
|
$binary_database_version = trim($db_version[2]);
|
||||||
|
if ($binary_database_version > 0) {
|
||||||
|
$local_database_version = get_bots_db_version();
|
||||||
|
|
||||||
|
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
||||||
|
if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") {
|
||||||
|
print "[Update] Bots database up to date...\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world") {
|
||||||
|
print "[Update] Bots Database not up to date with binaries... Automatically updating...\n";
|
||||||
|
if (!$db_already_backed_up) {
|
||||||
|
print "[Update] Issuing database backup first...\n";
|
||||||
|
database_dump_compress();
|
||||||
|
}
|
||||||
|
print "[Update] Updating bots database...\n";
|
||||||
|
sleep(1);
|
||||||
|
bots_db_management();
|
||||||
|
|
||||||
|
analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
#::: Make sure that we didn't pass any arugments to the script
|
||||||
|
else {
|
||||||
|
if ($local_database_version > $binary_database_version) {
|
||||||
|
print "[Update] Bots database version is ahead of current binaries...\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; }
|
||||||
|
show_menu_prompt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print "[Update] Continuing bootup\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub check_internet_connection {
|
sub check_internet_connection {
|
||||||
@@ -629,7 +649,7 @@ sub do_self_update_check_routine {
|
|||||||
|
|
||||||
#::: Check for internet connection before updating
|
#::: Check for internet connection before updating
|
||||||
if (!$has_internet_connection) {
|
if (!$has_internet_connection) {
|
||||||
print "[Update] Cannot check update without internet connection...\n";
|
print "[Update] Cannot check self-update without internet connection...\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -819,7 +839,6 @@ sub setup_bots {
|
|||||||
build_linux_source("bots");
|
build_linux_source("bots");
|
||||||
}
|
}
|
||||||
bots_db_management();
|
bots_db_management();
|
||||||
run_database_check();
|
|
||||||
|
|
||||||
print "Bots should be setup, run your server and the bot command should be available in-game (type '^help')\n";
|
print "Bots should be setup, run your server and the bot command should be available in-game (type '^help')\n";
|
||||||
}
|
}
|
||||||
@@ -953,13 +972,11 @@ sub show_menu_prompt {
|
|||||||
$dc = 1;
|
$dc = 1;
|
||||||
}
|
}
|
||||||
elsif ($input eq "check_db_updates") {
|
elsif ($input eq "check_db_updates") {
|
||||||
main_db_management();
|
|
||||||
main_db_management();
|
main_db_management();
|
||||||
$dc = 1;
|
$dc = 1;
|
||||||
}
|
}
|
||||||
elsif ($input eq "check_bot_db_updates") {
|
elsif ($input eq "check_bot_db_updates") {
|
||||||
bots_db_management();
|
bots_db_management();
|
||||||
run_database_check();
|
|
||||||
$dc = 1;
|
$dc = 1;
|
||||||
}
|
}
|
||||||
elsif ($input eq "setup_loginserver") {
|
elsif ($input eq "setup_loginserver") {
|
||||||
@@ -1400,6 +1417,7 @@ sub remove_duplicate_rule_values {
|
|||||||
sub copy_file {
|
sub copy_file {
|
||||||
$l_source_file = $_[0];
|
$l_source_file = $_[0];
|
||||||
$l_destination_file = $_[1];
|
$l_destination_file = $_[1];
|
||||||
|
|
||||||
if ($l_destination_file =~ /\//i) {
|
if ($l_destination_file =~ /\//i) {
|
||||||
my @directory_path = split('/', $l_destination_file);
|
my @directory_path = split('/', $l_destination_file);
|
||||||
$build_path = "";
|
$build_path = "";
|
||||||
@@ -1418,6 +1436,7 @@ sub copy_file {
|
|||||||
$directory_index++;
|
$directory_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
copy $l_source_file, $l_destination_file;
|
copy $l_source_file, $l_destination_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1693,26 +1712,22 @@ sub fetch_server_dlls {
|
|||||||
|
|
||||||
sub fetch_peq_db_full {
|
sub fetch_peq_db_full {
|
||||||
print "[Install] Downloading latest PEQ Database... Please wait...\n";
|
print "[Install] Downloading latest PEQ Database... Please wait...\n";
|
||||||
get_remote_file("http://edit.projecteq.net/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1);
|
get_remote_file("http://db.projecteq.net/api/v1/dump/latest", "updates_staged/peq-latest.zip", 1);
|
||||||
print "[Install] Downloaded latest PEQ Database... Extracting...\n";
|
print "[Install] Downloaded latest PEQ Database... Extracting...\n";
|
||||||
unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/');
|
unzip('updates_staged/peq-latest.zip', 'updates_staged/peq_db/');
|
||||||
my $start_dir = "updates_staged/peq_db";
|
my $start_dir = "updates_staged/peq_db/peq-dump";
|
||||||
find(
|
find(
|
||||||
sub { push @files, $File::Find::name unless -d; },
|
sub { push @files, $File::Find::name unless -d; },
|
||||||
$start_dir
|
$start_dir
|
||||||
);
|
);
|
||||||
for my $file (@files) {
|
for my $file (@files) {
|
||||||
$destination_file = $file;
|
$destination_file = $file;
|
||||||
$destination_file =~ s/updates_staged\/peq_db\///g;
|
$destination_file =~ s/updates_staged\/peq_db\/peq-dump\///g;
|
||||||
if ($file =~ /peqbeta|player_tables/i) {
|
if ($file =~ /create_tables_content|create_tables_login|create_tables_player|create_tables_queryserv|create_tables_state|create_tables_system/i) {
|
||||||
print "[Install] DB :: Installing :: " . $destination_file . "\n";
|
print "[Install] DB :: Installing :: " . $destination_file . "\n";
|
||||||
get_mysql_result_from_file($file);
|
get_mysql_result_from_file($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#::: PEQ DB baseline version
|
|
||||||
print get_mysql_result("DELETE FROM db_version");
|
|
||||||
print get_mysql_result("INSERT INTO `db_version` (`version`) VALUES (9130);");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub map_files_fetch_bulk {
|
sub map_files_fetch_bulk {
|
||||||
@@ -2001,15 +2016,6 @@ sub do_bots_db_schema_drop {
|
|||||||
print get_mysql_result_from_file("db_update/drop_bots.sql");
|
print get_mysql_result_from_file("db_update/drop_bots.sql");
|
||||||
|
|
||||||
print "[Database] Removing bot database tables...\n";
|
print "[Database] Removing bot database tables...\n";
|
||||||
print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';");
|
|
||||||
|
|
||||||
if (get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db) {
|
|
||||||
print get_mysql_result("DELETE FROM `commands` WHERE `command` LIKE 'bot';");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && $db) {
|
|
||||||
print get_mysql_result("DELETE FROM `command_settings` WHERE `command` LIKE 'bot';");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db) {
|
if (get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db) {
|
||||||
print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;");
|
print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;");
|
||||||
@@ -2043,70 +2049,6 @@ sub modify_db_for_bots {
|
|||||||
}
|
}
|
||||||
print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`);");
|
print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`);");
|
||||||
|
|
||||||
if (get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && get_mysql_result("SELECT `command` FROM `command_settings` WHERE `command` LIKE 'bot'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `command_settings` VALUES ('bot', '0', '');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && get_mysql_result("SELECT `command` FROM `commands` WHERE `command` LIKE 'bot'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `commands` VALUES ('bot', '0');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:FinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:GroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:ManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpawnLimit', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\\\'s (Anita_Thrall.pl) Bot Spell Scriber quests.');");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount'") ne "" && $db) {
|
|
||||||
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount';");
|
|
||||||
}
|
|
||||||
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit'") eq "" && $db) {
|
|
||||||
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:SpawnLimit', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid');");
|
|
||||||
}
|
|
||||||
|
|
||||||
convert_existing_bot_data();
|
convert_existing_bot_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2205,47 +2147,49 @@ sub convert_existing_bot_data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub get_main_db_version {
|
||||||
|
$main_local_db_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
|
||||||
|
return $main_local_db_version;
|
||||||
|
}
|
||||||
|
|
||||||
sub get_bots_db_version {
|
sub get_bots_db_version {
|
||||||
#::: Check if bots_version column exists...
|
#::: Check if bots_version column exists...
|
||||||
if (get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db) {
|
if (get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db) {
|
||||||
print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;");
|
print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;");
|
||||||
print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n";
|
print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1"));
|
$bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1"));
|
||||||
return $bots_local_db_version;
|
return $bots_local_db_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#::: Safe for call from world startup or menu option
|
||||||
sub bots_db_management {
|
sub bots_db_management {
|
||||||
if ($OS eq "Windows") {
|
|
||||||
@db_version = split(': ', `world db_version`);
|
|
||||||
}
|
|
||||||
if ($OS eq "Linux") {
|
|
||||||
@db_version = split(': ', `./world db_version`);
|
|
||||||
}
|
|
||||||
|
|
||||||
#::: Main Binary Database version
|
|
||||||
$binary_database_version = trim($db_version[2]);
|
|
||||||
|
|
||||||
#::: If we have stale data from main db run
|
#::: If we have stale data from main db run
|
||||||
if ($db_run_stage > 0 && $bots_db_management == 0) {
|
if ($db_run_stage > 0 && $bots_db_management == 0) {
|
||||||
clear_database_runs();
|
clear_database_runs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#::: Main Binary Database version
|
||||||
|
$binary_database_version = trim($db_version[2]);
|
||||||
if ($binary_database_version == 0) {
|
if ($binary_database_version == 0) {
|
||||||
print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n";
|
print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$local_database_version = get_bots_db_version();
|
||||||
|
|
||||||
#::: Set on flag for running bot updates...
|
#::: Set on flag for running bot updates...
|
||||||
$bots_db_management = 1;
|
$bots_db_management = 1;
|
||||||
|
|
||||||
$bots_local_db_version = get_bots_db_version();
|
if ($local_database_version > $binary_database_version) {
|
||||||
|
print "[Update] Bots database version is ahead of current binaries...\n";
|
||||||
$local_database_version = $bots_local_db_version;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
run_database_check();
|
run_database_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#::: Safe for call from world startup or menu option
|
||||||
sub main_db_management {
|
sub main_db_management {
|
||||||
#::: If we have stale data from bots db run
|
#::: If we have stale data from bots db run
|
||||||
if ($db_run_stage > 0 && $bots_db_management == 1) {
|
if ($db_run_stage > 0 && $bots_db_management == 1) {
|
||||||
@@ -2254,8 +2198,15 @@ sub main_db_management {
|
|||||||
|
|
||||||
#::: Main Binary Database version
|
#::: Main Binary Database version
|
||||||
$binary_database_version = trim($db_version[1]);
|
$binary_database_version = trim($db_version[1]);
|
||||||
|
$local_database_version = get_main_db_version();
|
||||||
|
|
||||||
$bots_db_management = 0;
|
$bots_db_management = 0;
|
||||||
|
|
||||||
|
if ($local_database_version > $binary_database_version) {
|
||||||
|
print "[Update] Database version is ahead of current binaries...\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
run_database_check();
|
run_database_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2265,8 +2216,6 @@ sub clear_database_runs {
|
|||||||
%m_d = ();
|
%m_d = ();
|
||||||
#::: Clear updates...
|
#::: Clear updates...
|
||||||
@total_updates = ();
|
@total_updates = ();
|
||||||
#::: Clear stage
|
|
||||||
$db_run_stage = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#::: Responsible for Database Upgrade Routines
|
#::: Responsible for Database Upgrade Routines
|
||||||
@@ -2277,7 +2226,6 @@ sub run_database_check {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!@total_updates) {
|
|
||||||
#::: Pull down bots database manifest
|
#::: Pull down bots database manifest
|
||||||
if ($bots_db_management == 1) {
|
if ($bots_db_management == 1) {
|
||||||
print "[Database] Retrieving latest bots database manifest...\n";
|
print "[Database] Retrieving latest bots database manifest...\n";
|
||||||
@@ -2288,29 +2236,8 @@ sub run_database_check {
|
|||||||
print "[Database] Retrieving latest database manifest...\n";
|
print "[Database] Retrieving latest database manifest...\n";
|
||||||
get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt");
|
get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#::: Run 2 - Running pending updates...
|
#::: Parse manifest
|
||||||
if (@total_updates || $db_run_stage == 1) {
|
|
||||||
@total_updates = sort @total_updates;
|
|
||||||
foreach my $val (@total_updates) {
|
|
||||||
$file_name = trim($m_d{$val}[1]);
|
|
||||||
print "[Database] Running Update: " . $val . " - " . $file_name . "\n";
|
|
||||||
print get_mysql_result_from_file("db_update/$file_name");
|
|
||||||
print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val");
|
|
||||||
|
|
||||||
if ($bots_db_management == 1 && $val == 9000) {
|
|
||||||
modify_db_for_bots();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($val == 9138) {
|
|
||||||
fix_quest_factions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$db_run_stage = 2;
|
|
||||||
}
|
|
||||||
#::: Run 1 - Initial checking of needed updates...
|
|
||||||
else {
|
|
||||||
print "[Database] Reading manifest...\n";
|
print "[Database] Reading manifest...\n";
|
||||||
|
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
@@ -2325,88 +2252,34 @@ sub run_database_check {
|
|||||||
@manifest = split('\|', $o);
|
@manifest = split('\|', $o);
|
||||||
$m_d{$manifest[0]} = [ @manifest ];
|
$m_d{$manifest[0]} = [ @manifest ];
|
||||||
}
|
}
|
||||||
#::: Setting Manifest stage...
|
|
||||||
$db_run_stage = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@total_updates = ();
|
|
||||||
|
|
||||||
#::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest...
|
#::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest...
|
||||||
if ($local_database_version >= 9000) {
|
if ($local_database_version >= 9000) {
|
||||||
$revision_check = $local_database_version;
|
$revision_check = $local_database_version + 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#::: This does not negatively affect bots
|
||||||
$revision_check = 1000;
|
$revision_check = 1000;
|
||||||
if (get_mysql_result("SHOW TABLES LIKE 'character_data'") ne "") {
|
if (get_mysql_result("SHOW TABLES LIKE 'character_data'") ne "") {
|
||||||
$revision_check = 8999;
|
$revision_check = 8999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#::: Iterate through Manifest backwards from binary version down to local version...
|
@total_updates = ();
|
||||||
|
|
||||||
|
#::: Fetch and register sqls for this database update cycle
|
||||||
for ($i = $revision_check; $i <= $binary_database_version; $i++) {
|
for ($i = $revision_check; $i <= $binary_database_version; $i++) {
|
||||||
if (!defined($m_d{$i}[0])) {
|
if (!defined($m_d{$i}[0])) {
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
$file_name = trim($m_d{$i}[1]);
|
$file_name = trim($m_d{$i}[1]);
|
||||||
$query_check = trim($m_d{$i}[2]);
|
print "[Database] fetching update: " . $i . " '" . $file_name . "' \n";
|
||||||
$match_type = trim($m_d{$i}[3]);
|
fetch_missing_db_update($i, $file_name);
|
||||||
$match_text = trim($m_d{$i}[4]);
|
push(@total_updates, $i);
|
||||||
|
}
|
||||||
|
|
||||||
#::: Match type update
|
if (scalar(@total_updates) == 0) {
|
||||||
if ($match_type eq "contains") {
|
|
||||||
if (trim(get_mysql_result($query_check)) =~ /$match_text/i) {
|
|
||||||
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
|
|
||||||
fetch_missing_db_update($i, $file_name);
|
|
||||||
push(@total_updates, $i);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
|
|
||||||
}
|
|
||||||
print_match_debug();
|
|
||||||
print_break();
|
|
||||||
}
|
|
||||||
if ($match_type eq "missing") {
|
|
||||||
if (get_mysql_result($query_check) =~ /$match_text/i) {
|
|
||||||
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
|
|
||||||
fetch_missing_db_update($i, $file_name);
|
|
||||||
push(@total_updates, $i);
|
|
||||||
}
|
|
||||||
print_match_debug();
|
|
||||||
print_break();
|
|
||||||
}
|
|
||||||
if ($match_type eq "empty") {
|
|
||||||
if (get_mysql_result($query_check) eq "") {
|
|
||||||
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
|
|
||||||
fetch_missing_db_update($i, $file_name);
|
|
||||||
push(@total_updates, $i);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
|
|
||||||
}
|
|
||||||
print_match_debug();
|
|
||||||
print_break();
|
|
||||||
}
|
|
||||||
if ($match_type eq "not_empty") {
|
|
||||||
if (get_mysql_result($query_check) ne "") {
|
|
||||||
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
|
|
||||||
fetch_missing_db_update($i, $file_name);
|
|
||||||
push(@total_updates, $i);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
|
|
||||||
}
|
|
||||||
print_match_debug();
|
|
||||||
print_break();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print "\n";
|
|
||||||
|
|
||||||
if (scalar(@total_updates) == 0 && $db_run_stage == 2) {
|
|
||||||
print "[Database] No updates need to be run...\n";
|
print "[Database] No updates need to be run...\n";
|
||||||
if ($bots_db_management == 1) {
|
if ($bots_db_management == 1) {
|
||||||
print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n";
|
print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n";
|
||||||
@@ -2418,23 +2291,105 @@ sub run_database_check {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear_database_runs();
|
clear_database_runs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#::: Execute pending updates
|
||||||
|
@total_updates = sort @total_updates;
|
||||||
|
foreach my $val (@total_updates) {
|
||||||
|
$file_name = trim($m_d{$val}[1]);
|
||||||
|
$query_check = trim($m_d{$val}[2]);
|
||||||
|
$match_type = trim($m_d{$val}[3]);
|
||||||
|
$match_text = trim($m_d{$val}[4]);
|
||||||
|
|
||||||
|
#::: Match type update
|
||||||
|
if ($match_type eq "contains") {
|
||||||
|
if (trim(get_mysql_result($query_check)) =~ /$match_text/i) {
|
||||||
|
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
|
||||||
|
print get_mysql_result_from_file("db_update/$file_name");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[Database] Has update [" . $val . "]:[" . $file_name . "]\n";
|
||||||
|
}
|
||||||
|
print_match_debug();
|
||||||
|
print_break();
|
||||||
|
}
|
||||||
|
if ($match_type eq "missing") {
|
||||||
|
if (get_mysql_result($query_check) =~ /$match_text/i) {
|
||||||
|
print "[Database] Has update [" . $val . "]:[" . $file_name . "]\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
|
||||||
|
print get_mysql_result_from_file("db_update/$file_name");
|
||||||
|
}
|
||||||
|
print_match_debug();
|
||||||
|
print_break();
|
||||||
|
}
|
||||||
|
if ($match_type eq "empty") {
|
||||||
|
if (get_mysql_result($query_check) eq "") {
|
||||||
|
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
|
||||||
|
print get_mysql_result_from_file("db_update/$file_name");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[Database] Has update [" . $val . "]:[" . $file_name . "' \n";
|
||||||
|
}
|
||||||
|
print_match_debug();
|
||||||
|
print_break();
|
||||||
|
}
|
||||||
|
if ($match_type eq "not_empty") {
|
||||||
|
if (get_mysql_result($query_check) ne "") {
|
||||||
|
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
|
||||||
|
print get_mysql_result_from_file("db_update/$file_name");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[Database] Has update [" . $val . "]:[" . $file_name . "]\n";
|
||||||
|
}
|
||||||
|
print_match_debug();
|
||||||
|
print_break();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($bots_db_management == 1) {
|
||||||
|
print get_mysql_result("UPDATE db_version SET bots_version = $val WHERE bots_version < $val");
|
||||||
|
|
||||||
|
if ($val == 9000) {
|
||||||
|
modify_db_for_bots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val");
|
||||||
|
|
||||||
|
if ($val == 9138) {
|
||||||
|
fix_quest_factions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($bots_db_management == 1) {
|
||||||
|
print "[Database] Bots database update cycle complete at version [" . get_bots_db_version() . "]\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[Database] Mainstream database update cycle complete at version [" . get_main_db_version() . "]\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub fetch_missing_db_update {
|
sub fetch_missing_db_update {
|
||||||
$db_update = $_[0];
|
$db_update = $_[0];
|
||||||
$update_file = $_[1];
|
$update_file = $_[1];
|
||||||
if ($db_update >= 9000) {
|
|
||||||
if ($bots_db_management == 1) {
|
if ($bots_db_management == 1) {
|
||||||
|
if ($db_update >= 9000) {
|
||||||
get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . "");
|
get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . "");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . "");
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if ($db_update >= 9000) {
|
||||||
|
get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . "");
|
||||||
}
|
}
|
||||||
elsif ($db_update >= 5000 && $db_update <= 9000) {
|
elsif ($db_update >= 5000 && $db_update <= 9000) {
|
||||||
get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . "");
|
get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . "");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub print_match_debug {
|
sub print_match_debug {
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
account
|
|
||||||
account_ip
|
|
||||||
account_flags
|
|
||||||
account_rewards
|
|
||||||
adventure_details
|
|
||||||
adventure_stats
|
|
||||||
buyer
|
|
||||||
char_recipe_list
|
|
||||||
character_activities
|
|
||||||
character_alt_currency
|
|
||||||
character_alternate_abilities
|
|
||||||
character_auras
|
|
||||||
character_bandolier
|
|
||||||
character_bind
|
|
||||||
character_buffs
|
|
||||||
character_corpse_items
|
|
||||||
character_corpses
|
|
||||||
character_currency
|
|
||||||
character_data
|
|
||||||
character_disciplines
|
|
||||||
character_enabledtasks
|
|
||||||
character_inspect_messages
|
|
||||||
character_item_recast
|
|
||||||
character_languages
|
|
||||||
character_leadership_abilities
|
|
||||||
character_material
|
|
||||||
character_memmed_spells
|
|
||||||
character_pet_buffs
|
|
||||||
character_pet_info
|
|
||||||
character_pet_inventory
|
|
||||||
character_potionbelt
|
|
||||||
character_skills
|
|
||||||
character_spells
|
|
||||||
character_tasks
|
|
||||||
character_tribute
|
|
||||||
completed_tasks
|
|
||||||
data_buckets
|
|
||||||
faction_values
|
|
||||||
friends
|
|
||||||
guild_bank
|
|
||||||
guild_members
|
|
||||||
guild_ranks
|
|
||||||
guild_relations
|
|
||||||
guilds
|
|
||||||
instance_list_player
|
|
||||||
inventory
|
|
||||||
inventory_snapshots
|
|
||||||
keyring
|
|
||||||
mail
|
|
||||||
player_titlesets
|
|
||||||
quest_globals
|
|
||||||
sharedbank
|
|
||||||
timers
|
|
||||||
titles
|
|
||||||
trader
|
|
||||||
trader_audit
|
|
||||||
zone_flags"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
command_settings
|
|
||||||
inventory_versions
|
|
||||||
launcher
|
|
||||||
rule_sets
|
|
||||||
rule_values
|
|
||||||
variables
|
|
||||||
@@ -400,6 +400,12 @@
|
|||||||
9144|2019_11_09_logsys_description_update.sql|SELECT * FROM db_version WHERE version >= 9143|empty|
|
9144|2019_11_09_logsys_description_update.sql|SELECT * FROM db_version WHERE version >= 9143|empty|
|
||||||
9145|2019_12_24_banned_ips_update.sql|SHOW TABLES LIKE 'Banned_IPs'|not_empty|
|
9145|2019_12_24_banned_ips_update.sql|SHOW TABLES LIKE 'Banned_IPs'|not_empty|
|
||||||
9146|2020_01_10_character_soft_deletes.sql|SHOW COLUMNS FROM `character_data` LIKE 'deleted_at'|empty|
|
9146|2020_01_10_character_soft_deletes.sql|SHOW COLUMNS FROM `character_data` LIKE 'deleted_at'|empty|
|
||||||
|
9147|2020_01_24_grid_centerpoint_wp.sql|SHOW COLUMNS FROM `grid_entries` LIKE 'centerpoint'|empty|
|
||||||
|
9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty|
|
||||||
|
9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty|
|
||||||
|
9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty|
|
||||||
|
9151|2020_03_05_npc_always_aggro.sql|SHOW COLUMNS FROM `npc_types` LIKE 'always_aggro'|empty|
|
||||||
|
9152|2020_03_09_convert_myisam_to_innodb.sql|SELECT * FROM db_version WHERE version >= 9152|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
9024|2019_06_27_bots_pet_get_lost.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'petgetlost'|empty|
|
9024|2019_06_27_bots_pet_get_lost.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'petgetlost'|empty|
|
||||||
9025|2019_08_26_bots_owner_option_spawn_message.sql|SELECT * FROM db_version WHERE bots_version >= 9025|empty|
|
9025|2019_08_26_bots_owner_option_spawn_message.sql|SELECT * FROM db_version WHERE bots_version >= 9025|empty|
|
||||||
9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty|
|
9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty|
|
||||||
|
9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
DROP VIEW IF EXISTS `vw_bot_character_mobs`;
|
||||||
|
|
||||||
|
-- Views
|
||||||
|
CREATE VIEW `vw_bot_character_mobs` AS
|
||||||
|
SELECT
|
||||||
|
_utf8'C' AS mob_type,
|
||||||
|
c.`id`,
|
||||||
|
c.`name`,
|
||||||
|
c.`class`,
|
||||||
|
c.`level`,
|
||||||
|
c.`last_login`,
|
||||||
|
c.`zone_id`,
|
||||||
|
c.`deleted_at`
|
||||||
|
FROM `character_data` AS c
|
||||||
|
UNION ALL
|
||||||
|
SELECT _utf8'B' AS mob_type,
|
||||||
|
b.`bot_id` AS id,
|
||||||
|
b.`name`,
|
||||||
|
b.`class`,
|
||||||
|
b.`level`,
|
||||||
|
b.`last_spawn` AS last_login,
|
||||||
|
b.`zone_id`,
|
||||||
|
NULL AS `deleted_at`
|
||||||
|
FROM `bot_data` AS b;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
-- Run this to un-reserve deleted characters
|
||||||
|
UPDATE
|
||||||
|
character_data
|
||||||
|
SET
|
||||||
|
name = SUBSTRING(
|
||||||
|
CONCAT(name, '-deleted-', UNIX_TIMESTAMP()),
|
||||||
|
1,
|
||||||
|
64
|
||||||
|
)
|
||||||
|
WHERE
|
||||||
|
deleted_at IS NOT NULL
|
||||||
|
AND name NOT LIKE '%-deleted-%';
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table grid_entries add column `centerpoint` tinyint(4) not null default 0;
|
||||||
|
alter table spawngroup add column `wp_spawns` tinyint(1) unsigned not null default 0;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `character_corpses` ADD COLUMN `guild_consent_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `time_of_death`;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `aa_ability` ADD `reset_on_death` TINYINT(4) NOT NULL DEFAULT '0';
|
||||||
|
UPDATE `aa_ability` SET `reset_on_death` = '1' WHERE `id` = 6001;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `global_loot` ADD `hot_zone` TINYINT NULL;
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `npc_types` ADD COLUMN `always_aggro` tinyint(1) NOT NULL DEFAULT 0;
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
ALTER TABLE `account_flags` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `account_ip` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `account` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `adventure_template_entry_flavor` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `adventure_template_entry` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `altadv_vars` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `alternate_currency` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `banned_ips` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `base_data` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `blocked_spells` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `buyer` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `char_create_combinations` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `char_create_point_allocations` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `character_activities` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `character_enabledtasks` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `character_tasks` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `chatchannels` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `completed_tasks` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `damageshieldtypes` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `discovered_items` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `eqtime` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `eventlog` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `faction_list_mod` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `faction_list` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `faction_values` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `friends` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `goallists` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `guild_bank` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `guild_members` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `guild_ranks` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `guild_relations` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `guilds` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `hackers` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `horses` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `inventory_versions` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `item_tick` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `items` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `keyring` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `launcher_zones` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `launcher` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `ldon_trap_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `ldon_trap_templates` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `lfguild` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `lootdrop_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `lootdrop` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `loottable_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `loottable` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `mail` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_armorinfo` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_buffs` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_inventory` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_merchant_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_merchant_template_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_merchant_templates` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_name_types` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_npc_types` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_spell_list_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_spell_lists` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_stance_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_stats` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_subtypes` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_templates` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_types` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `merc_weaponinfo` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `mercs` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `name_filter` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `npc_types` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `object_contents` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `petitions` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `pets_equipmentset_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `pets_equipmentset` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `player_titlesets` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `proximities` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `races` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `raid_details` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `raid_leaders` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `raid_members` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `rule_sets` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `rule_values` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `saylink` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `sharedbank` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `skill_caps` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `spell_globals` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `spells_new` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `task_activities` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `tasks` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `tasksets` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `timers` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `titles` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `trader_audit` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `trader` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `tradeskill_recipe_entries` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `tradeskill_recipe` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `variables` ENGINE=InnoDB;
|
||||||
|
ALTER TABLE `veteran_reward_templates` ENGINE=InnoDB;
|
||||||
Executable
+71
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Run from the context of server directory
|
||||||
|
|
||||||
|
world_path=""
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# world path
|
||||||
|
#############################################
|
||||||
|
if [ -d "bin" ]
|
||||||
|
then
|
||||||
|
world_path="bin/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
world_bin="${world_path}world"
|
||||||
|
|
||||||
|
echo "World path is [$world_path] bin is [$world_bin]"
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# dump
|
||||||
|
#############################################
|
||||||
|
|
||||||
|
dump_path=/tmp/peq-dump/
|
||||||
|
echo "Generating dump path [${dump_path}]"
|
||||||
|
rm -rf ${dump_path}
|
||||||
|
mkdir -p ${dump_path}
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# generate "drop_" table files
|
||||||
|
#############################################
|
||||||
|
echo "Generating [drop_*] table exports..."
|
||||||
|
bash -c "${world_bin} database:dump --content-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_content.sql"
|
||||||
|
bash -c "${world_bin} database:dump --login-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_login.sql"
|
||||||
|
bash -c "${world_bin} database:dump --player-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_player.sql"
|
||||||
|
bash -c "${world_bin} database:dump --system-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_system.sql"
|
||||||
|
bash -c "${world_bin} database:dump --state-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_state.sql"
|
||||||
|
bash -c "${world_bin} database:dump --query-serv-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_queryserv.sql"
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# generate "create_" table files
|
||||||
|
#############################################
|
||||||
|
echo "Generating [create_*] table exports..."
|
||||||
|
|
||||||
|
# structure only
|
||||||
|
bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_login.sql"
|
||||||
|
bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_player.sql"
|
||||||
|
bash -c "${world_bin} database:dump --state-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_state.sql"
|
||||||
|
echo 'REPLACE INTO `instance_list` VALUES (1,25,1,1,0,0,1),(2,25,2,1,0,0,1),(3,151,1,1,0,0,1),(4,114,1,1,0,0,1),(5,344,1,1,0,0,1),(6,202,0,1,0,0,1);' >> "${dump_path}create_tables_state.sql"
|
||||||
|
bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_queryserv.sql"
|
||||||
|
|
||||||
|
# with content
|
||||||
|
bash -c "${world_bin} database:dump --content-tables --dump-output-to-console > ${dump_path}create_tables_content.sql"
|
||||||
|
bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql"
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# "all" exports
|
||||||
|
#############################################
|
||||||
|
bash -c "cd ${dump_path} && ls * | grep create | sed 's/.*/source &;/' > create_all_tables.sql"
|
||||||
|
bash -c "cd ${dump_path} && ls * | grep drop | sed 's/.*/source &;/' > drop_all_tables.sql"
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# zip
|
||||||
|
#############################################
|
||||||
|
human_date=$(date +"%B-%d-%Y" | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
echo "Compressing..."
|
||||||
|
bash -c "cd /tmp/ && rm -rf peq-latest.zip && zip peq-latest.zip peq-dump/* && mv ${dump_path}peq-latest.zip /tmp/peq-latest.zip"
|
||||||
|
|
||||||
|
echo "Cleaning up..."
|
||||||
|
rm -rf ${dump_path}
|
||||||
|
|
||||||
|
echo "Dump located [/tmp/peq-latest.zip]"
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
aa_ability
|
|
||||||
aa_actions
|
|
||||||
aa_effects
|
|
||||||
aa_rank_effects
|
|
||||||
aa_rank_prereqs
|
|
||||||
aa_ranks
|
|
||||||
aa_required_level_cost
|
|
||||||
adventure_template
|
|
||||||
adventure_template_entry
|
|
||||||
adventure_template_entry_flavor
|
|
||||||
altadv_vars
|
|
||||||
alternate_currency
|
|
||||||
auras
|
|
||||||
base_data
|
|
||||||
blocked_spells
|
|
||||||
books
|
|
||||||
bug_reports
|
|
||||||
char_create_combinations
|
|
||||||
char_create_point_allocations
|
|
||||||
class_skill
|
|
||||||
damageshieldtypes
|
|
||||||
data_buckets
|
|
||||||
db_str
|
|
||||||
doors
|
|
||||||
eqtime
|
|
||||||
faction_base_data
|
|
||||||
faction_list
|
|
||||||
faction_list_mod
|
|
||||||
fear_hints
|
|
||||||
fishing
|
|
||||||
forage
|
|
||||||
global_loot
|
|
||||||
goallists
|
|
||||||
graveyard
|
|
||||||
grid
|
|
||||||
grid_entries
|
|
||||||
ground_spawns
|
|
||||||
horses
|
|
||||||
instance_list
|
|
||||||
items
|
|
||||||
ip_exemptions
|
|
||||||
ldon_trap_entries
|
|
||||||
ldon_trap_templates
|
|
||||||
level_exp_mods
|
|
||||||
logsys_categories
|
|
||||||
lootdrop
|
|
||||||
lootdrop_entries
|
|
||||||
loottable
|
|
||||||
loottable_entries
|
|
||||||
merc_armorinfo
|
|
||||||
merc_buffs
|
|
||||||
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
|
|
||||||
merchantlist
|
|
||||||
mercs
|
|
||||||
name_filter
|
|
||||||
npc_emotes
|
|
||||||
npc_faction
|
|
||||||
npc_faction_entries
|
|
||||||
npc_scale_global_base
|
|
||||||
npc_spells
|
|
||||||
npc_spells_effects
|
|
||||||
npc_spells_effects_entries
|
|
||||||
npc_spells_entries
|
|
||||||
npc_types
|
|
||||||
npc_types_metadata
|
|
||||||
npc_types_tint
|
|
||||||
object
|
|
||||||
perl_event_export_settings
|
|
||||||
pets
|
|
||||||
pets_equipmentset
|
|
||||||
pets_equipmentset_entries
|
|
||||||
profanity_list
|
|
||||||
proximities
|
|
||||||
races
|
|
||||||
saylink
|
|
||||||
skill_caps
|
|
||||||
spawn2
|
|
||||||
spawn_condition_values
|
|
||||||
spawn_conditions
|
|
||||||
spawn_events
|
|
||||||
spawnentry
|
|
||||||
spawngroup
|
|
||||||
spells_new
|
|
||||||
start_zones
|
|
||||||
starting_items
|
|
||||||
task_activities
|
|
||||||
tasks
|
|
||||||
tasksets
|
|
||||||
titles
|
|
||||||
tradeskill_recipe
|
|
||||||
tradeskill_recipe_entries
|
|
||||||
traps
|
|
||||||
tribute_levels
|
|
||||||
tributes
|
|
||||||
veteran_reward_templates
|
|
||||||
zone
|
|
||||||
zone_points
|
|
||||||
zone_server
|
|
||||||
zone_state_dump
|
|
||||||
zoneserver_auth
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
aa_timers
|
|
||||||
account
|
|
||||||
account_flags
|
|
||||||
account_ip
|
|
||||||
account_rewards
|
|
||||||
adventure_details
|
|
||||||
adventure_members
|
|
||||||
adventure_stats
|
|
||||||
banned_ips
|
|
||||||
bugs
|
|
||||||
buyer
|
|
||||||
char_recipe_list
|
|
||||||
character_activities
|
|
||||||
character_alt_currency
|
|
||||||
character_alternate_abilities
|
|
||||||
character_auras
|
|
||||||
character_bandolier
|
|
||||||
character_bind
|
|
||||||
character_buffs
|
|
||||||
character_corpse_items
|
|
||||||
character_corpses
|
|
||||||
character_currency
|
|
||||||
character_data
|
|
||||||
character_disciplines
|
|
||||||
character_enabledtasks
|
|
||||||
character_inspect_messages
|
|
||||||
character_item_recast
|
|
||||||
character_languages
|
|
||||||
character_leadership_abilities
|
|
||||||
character_material
|
|
||||||
character_memmed_spells
|
|
||||||
character_pet_buffs
|
|
||||||
character_pet_info
|
|
||||||
character_pet_inventory
|
|
||||||
character_potionbelt
|
|
||||||
character_skills
|
|
||||||
character_spells
|
|
||||||
character_tasks
|
|
||||||
character_tribute
|
|
||||||
chatchannels
|
|
||||||
completed_tasks
|
|
||||||
discovered_items
|
|
||||||
eventlog
|
|
||||||
faction_values
|
|
||||||
friends
|
|
||||||
gm_ips
|
|
||||||
group_id
|
|
||||||
group_leaders
|
|
||||||
guild_bank
|
|
||||||
guild_members
|
|
||||||
guild_ranks
|
|
||||||
guild_relations
|
|
||||||
guilds
|
|
||||||
hackers
|
|
||||||
instance_list_player
|
|
||||||
inventory
|
|
||||||
inventory_snapshots
|
|
||||||
item_tick
|
|
||||||
keyring
|
|
||||||
launcher_zones
|
|
||||||
lfguild
|
|
||||||
mail
|
|
||||||
merchantlist_temp
|
|
||||||
object_contents
|
|
||||||
petitions
|
|
||||||
player_titlesets
|
|
||||||
qs_merchant_transaction_record
|
|
||||||
qs_merchant_transaction_record_entries
|
|
||||||
qs_player_aa_rate_hourly
|
|
||||||
qs_player_delete_record
|
|
||||||
qs_player_delete_record_entries
|
|
||||||
qs_player_events
|
|
||||||
qs_player_handin_record
|
|
||||||
qs_player_handin_record_entries
|
|
||||||
qs_player_move_record
|
|
||||||
qs_player_move_record_entries
|
|
||||||
qs_player_npc_kill_record
|
|
||||||
qs_player_npc_kill_record_entries
|
|
||||||
qs_player_speech
|
|
||||||
qs_player_trade_record
|
|
||||||
qs_player_trade_record_entries
|
|
||||||
quest_globals
|
|
||||||
raid_details
|
|
||||||
raid_leaders
|
|
||||||
raid_members
|
|
||||||
reports
|
|
||||||
respawn_times
|
|
||||||
sharedbank
|
|
||||||
spell_buckets
|
|
||||||
spell_globals
|
|
||||||
timers
|
|
||||||
trader
|
|
||||||
trader_audit
|
|
||||||
zone_flags
|
|
||||||
+36
-7
@@ -802,9 +802,9 @@ void ConsoleIpLookup(
|
|||||||
const std::vector<std::string> &args
|
const std::vector<std::string> &args
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (args.size() > 0) {
|
if (!args.empty()) {
|
||||||
WorldConsoleTCPConnection console_connection(connection);
|
WorldConsoleTCPConnection console_connection(connection);
|
||||||
client_list.SendCLEList(connection->Admin(), 0, &console_connection, args[0].c_str());
|
client_list.SendCLEList(connection->Admin(), nullptr, &console_connection, args[0].c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,6 +855,34 @@ void ConsoleReloadWorld(
|
|||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param connection
|
||||||
|
* @param command
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
void ConsoleReloadZoneQuests(
|
||||||
|
EQ::Net::ConsoleServerConnection *connection,
|
||||||
|
const std::string &command,
|
||||||
|
const std::vector<std::string> &args
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (args.empty()) {
|
||||||
|
connection->SendLine("[zone_short_name] required as argument");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string zone_short_name = args[0];
|
||||||
|
|
||||||
|
connection->SendLine(fmt::format("Reloading Zone [{}]...", zone_short_name));
|
||||||
|
|
||||||
|
auto pack = new ServerPacket(ServerOP_HotReloadQuests, sizeof(HotReloadQuestsStruct));
|
||||||
|
auto *hot_reload_quests = (HotReloadQuestsStruct *) pack->pBuffer;
|
||||||
|
strn0cpy(hot_reload_quests->zone_short_name, (char *) zone_short_name.c_str(), 200);
|
||||||
|
|
||||||
|
zoneserver_list.SendPacket(pack);
|
||||||
|
safe_delete(pack);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param connection
|
* @param connection
|
||||||
* @param command
|
* @param command
|
||||||
@@ -892,18 +920,19 @@ void RegisterConsoleFunctions(std::unique_ptr<EQ::Net::ConsoleServer>& console)
|
|||||||
console->RegisterCall("md5", 50, "md5", std::bind(ConsoleMd5, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("md5", 50, "md5", std::bind(ConsoleMd5, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("ooc", 50, "ooc [message]", std::bind(ConsoleOOC, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("ooc", 50, "ooc [message]", std::bind(ConsoleOOC, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("reloadworld", 200, "reloadworld", std::bind(ConsoleReloadWorld, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("reloadworld", 200, "reloadworld", std::bind(ConsoleReloadWorld, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("setpass", 200, "setpass [accountname] [newpass]", std::bind(ConsoleSetPass, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("reloadzonequests", 200, "reloadzonequests [zone_short_name]", std::bind(ConsoleReloadZoneQuests, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
console->RegisterCall("setpass", 200, "setpass [account_name] [new_password]", std::bind(ConsoleSetPass, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("signalcharbyname", 50, "signalcharbyname charname ID", std::bind(ConsoleSignalCharByName, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("signalcharbyname", 50, "signalcharbyname charname ID", std::bind(ConsoleSignalCharByName, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("tell", 50, "tell [name] [message]", std::bind(ConsoleTell, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("tell", 50, "tell [name] [message]", std::bind(ConsoleTell, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("unlock", 150, "unlock", std::bind(ConsoleUnlock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("unlock", 150, "unlock", std::bind(ConsoleUnlock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("uptime", 50, "uptime [zoneID#]", std::bind(ConsoleUptime, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("uptime", 50, "uptime [zone_server_id]", std::bind(ConsoleUptime, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("version", 50, "version", std::bind(ConsoleVersion, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("version", 50, "version", std::bind(ConsoleVersion, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("who", 50, "who", std::bind(ConsoleWho, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("who", 50, "who", std::bind(ConsoleWho, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("whoami", 50, "whoami", std::bind(ConsoleWhoami, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("whoami", 50, "whoami", std::bind(ConsoleWhoami, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("worldshutdown", 200, "worldshutdown", std::bind(ConsoleWorldShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("worldshutdown", 200, "worldshutdown", std::bind(ConsoleWorldShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("zonebootup", 150, "zonebootup [ZoneServerID] [zonename]", std::bind(ConsoleZoneBootup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("zonebootup", 150, "zonebootup [zone_server_id] [zone_short_name]", std::bind(ConsoleZoneBootup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("zonelock", 150, "zonelock [list|lock|unlock] [zonename]", std::bind(ConsoleZoneLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("zonelock", 150, "zonelock [list|lock|unlock] [zone_short_name]", std::bind(ConsoleZoneLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("zoneshutdown", 150, "zoneshutdown [zonename or ZoneServerID]", std::bind(ConsoleZoneShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("zoneshutdown", 150, "zoneshutdown [zone_short_name or zone_server_id]", std::bind(ConsoleZoneShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("zonestatus", 50, "zonestatus", std::bind(ConsoleZoneStatus, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));console->RegisterCall("ping", 50, "ping", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("zonestatus", 50, "zonestatus", std::bind(ConsoleZoneStatus, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));console->RegisterCall("ping", 50, "ping", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("quit", 50, "quit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("quit", 50, "quit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
console->RegisterCall("exit", 50, "exit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
console->RegisterCall("exit", 50, "exit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
|||||||
@@ -415,6 +415,7 @@ int main(int argc, char** argv) {
|
|||||||
RegisterConsoleFunctions(console);
|
RegisterConsoleFunctions(console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zoneserver_list.Init();
|
||||||
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
||||||
server_connection.reset(new EQ::Net::ServertalkServer());
|
server_connection.reset(new EQ::Net::ServertalkServer());
|
||||||
|
|
||||||
|
|||||||
+29
-10
@@ -6,29 +6,38 @@
|
|||||||
#include "../common/misc_functions.h"
|
#include "../common/misc_functions.h"
|
||||||
#include "../common/md5.h"
|
#include "../common/md5.h"
|
||||||
#include "../common/packet_dump.h"
|
#include "../common/packet_dump.h"
|
||||||
|
#include "../common/event/timer.h"
|
||||||
|
|
||||||
UCSConnection::UCSConnection()
|
UCSConnection::UCSConnection()
|
||||||
{
|
{
|
||||||
Stream = 0;
|
connection = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSConnection::SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> inStream)
|
void UCSConnection::SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> inStream)
|
||||||
{
|
{
|
||||||
if (Stream && Stream->Handle())
|
if (inStream && connection && connection->Handle()) {
|
||||||
{
|
|
||||||
LogInfo("Incoming UCS Connection while we were already connected to a UCS");
|
LogInfo("Incoming UCS Connection while we were already connected to a UCS");
|
||||||
Stream->Handle()->Disconnect();
|
connection->Handle()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream = inStream;
|
connection = inStream;
|
||||||
if (Stream) {
|
if (connection) {
|
||||||
Stream->OnMessage(std::bind(&UCSConnection::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
|
connection->OnMessage(
|
||||||
|
std::bind(
|
||||||
|
&UCSConnection::ProcessPacket,
|
||||||
|
this,
|
||||||
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_keepalive.reset(new EQ::Timer(5000, true, std::bind(&UCSConnection::OnKeepAlive, this, std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSConnection::ProcessPacket(uint16 opcode, EQ::Net::Packet &p)
|
void UCSConnection::ProcessPacket(uint16 opcode, EQ::Net::Packet &p)
|
||||||
{
|
{
|
||||||
if (!Stream)
|
if (!connection)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ServerPacket tpack(opcode, p);
|
ServerPacket tpack(opcode, p);
|
||||||
@@ -60,10 +69,10 @@ void UCSConnection::ProcessPacket(uint16 opcode, EQ::Net::Packet &p)
|
|||||||
|
|
||||||
void UCSConnection::SendPacket(ServerPacket* pack)
|
void UCSConnection::SendPacket(ServerPacket* pack)
|
||||||
{
|
{
|
||||||
if (!Stream)
|
if (!connection)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Stream->SendPacket(pack);
|
connection->SendPacket(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSConnection::SendMessage(const char *From, const char *Message)
|
void UCSConnection::SendMessage(const char *From, const char *Message)
|
||||||
@@ -78,3 +87,13 @@ void UCSConnection::SendMessage(const char *From, const char *Message)
|
|||||||
SendPacket(pack);
|
SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UCSConnection::OnKeepAlive(EQ::Timer *t)
|
||||||
|
{
|
||||||
|
if (!connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPacket pack(ServerOP_KeepAlive, 0);
|
||||||
|
connection->SendPacket(&pack);
|
||||||
|
}
|
||||||
|
|||||||
+10
-3
@@ -4,6 +4,7 @@
|
|||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
#include "../common/net/servertalk_server_connection.h"
|
#include "../common/net/servertalk_server_connection.h"
|
||||||
#include "../common/servertalk.h"
|
#include "../common/servertalk.h"
|
||||||
|
#include "../common/event/timer.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class UCSConnection
|
class UCSConnection
|
||||||
@@ -13,11 +14,17 @@ public:
|
|||||||
void SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection);
|
void SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection);
|
||||||
void ProcessPacket(uint16 opcode, EQ::Net::Packet &p);
|
void ProcessPacket(uint16 opcode, EQ::Net::Packet &p);
|
||||||
void SendPacket(ServerPacket* pack);
|
void SendPacket(ServerPacket* pack);
|
||||||
void Disconnect() { if(Stream && Stream->Handle()) Stream->Handle()->Disconnect(); }
|
void Disconnect() { if(connection && connection->Handle()) connection->Handle()->Disconnect(); }
|
||||||
void SendMessage(const char *From, const char *Message);
|
void SendMessage(const char *From, const char *Message);
|
||||||
private:
|
private:
|
||||||
inline std::string GetIP() const { return (Stream && Stream->Handle()) ? Stream->Handle()->RemoteIP() : 0; }
|
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
|
||||||
std::shared_ptr<EQ::Net::ServertalkServerConnection> Stream;
|
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keepalive
|
||||||
|
*/
|
||||||
|
std::unique_ptr<EQ::Timer> m_keepalive;
|
||||||
|
void OnKeepAlive(EQ::Timer *t);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*UCS_H_*/
|
#endif /*UCS_H_*/
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "../common/version.h"
|
#include "../common/version.h"
|
||||||
#include "worlddb.h"
|
#include "worlddb.h"
|
||||||
#include "../common/database_schema.h"
|
#include "../common/database_schema.h"
|
||||||
|
#include "../common/database/database_dump_service.h"
|
||||||
|
|
||||||
namespace WorldserverCommandHandler {
|
namespace WorldserverCommandHandler {
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ namespace WorldserverCommandHandler {
|
|||||||
function_map["database:version"] = &WorldserverCommandHandler::DatabaseVersion;
|
function_map["database:version"] = &WorldserverCommandHandler::DatabaseVersion;
|
||||||
function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus;
|
function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus;
|
||||||
function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema;
|
function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema;
|
||||||
|
function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump;
|
||||||
|
|
||||||
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
|
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
|
||||||
}
|
}
|
||||||
@@ -202,4 +204,71 @@ namespace WorldserverCommandHandler {
|
|||||||
std::cout << payload.str() << std::endl;
|
std::cout << payload.str() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
* @param cmd
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
|
{
|
||||||
|
description = "Dumps server database tables";
|
||||||
|
|
||||||
|
if (cmd[{"-h", "--help"}]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> arguments = {};
|
||||||
|
std::vector<std::string> options = {
|
||||||
|
"--all",
|
||||||
|
"--content-tables",
|
||||||
|
"--login-tables",
|
||||||
|
"--player-tables",
|
||||||
|
"--state-tables",
|
||||||
|
"--system-tables",
|
||||||
|
"--query-serv-tables",
|
||||||
|
"--table-structure-only",
|
||||||
|
"--table-lock",
|
||||||
|
"--dump-path=",
|
||||||
|
"--dump-output-to-console",
|
||||||
|
"--drop-table-syntax-only",
|
||||||
|
"--compress"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto database_dump_service = new DatabaseDumpService();
|
||||||
|
bool dump_all = cmd[{"-a", "--all"}];
|
||||||
|
|
||||||
|
if (!cmd("--dump-path").str().empty()) {
|
||||||
|
database_dump_service->SetDumpPath(cmd("--dump-path").str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Option
|
||||||
|
*/
|
||||||
|
database_dump_service->SetDumpContentTables(cmd[{"--content-tables"}] || dump_all);
|
||||||
|
database_dump_service->SetDumpLoginServerTables(cmd[{"--login-tables"}] || dump_all);
|
||||||
|
database_dump_service->SetDumpPlayerTables(cmd[{"--player-tables"}] || dump_all);
|
||||||
|
database_dump_service->SetDumpStateTables(cmd[{"--state-tables"}] || dump_all);
|
||||||
|
database_dump_service->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all);
|
||||||
|
database_dump_service->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all);
|
||||||
|
database_dump_service->SetDumpAllTables(dump_all);
|
||||||
|
|
||||||
|
database_dump_service->SetDumpWithNoData(cmd[{"--table-structure-only"}]);
|
||||||
|
database_dump_service->SetDumpTableLock(cmd[{"--table-lock"}]);
|
||||||
|
database_dump_service->SetDumpWithCompression(cmd[{"--compress"}]);
|
||||||
|
database_dump_service->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]);
|
||||||
|
database_dump_service->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump
|
||||||
|
*/
|
||||||
|
database_dump_service->Dump();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -30,6 +30,7 @@ namespace WorldserverCommandHandler {
|
|||||||
void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
|
void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+18
-21
@@ -39,7 +39,6 @@ ZSList::ZSList()
|
|||||||
{
|
{
|
||||||
NextID = 1;
|
NextID = 1;
|
||||||
CurGroupID = 1;
|
CurGroupID = 1;
|
||||||
LastAllocatedPort = 0;
|
|
||||||
memset(pLockedZones, 0, sizeof(pLockedZones));
|
memset(pLockedZones, 0, sizeof(pLockedZones));
|
||||||
|
|
||||||
m_tick.reset(new EQ::Timer(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1)));
|
m_tick.reset(new EQ::Timer(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1)));
|
||||||
@@ -76,7 +75,12 @@ void ZSList::Remove(const std::string &uuid)
|
|||||||
auto iter = zone_server_list.begin();
|
auto iter = zone_server_list.begin();
|
||||||
while (iter != zone_server_list.end()) {
|
while (iter != zone_server_list.end()) {
|
||||||
if ((*iter)->GetUUID().compare(uuid) == 0) {
|
if ((*iter)->GetUUID().compare(uuid) == 0) {
|
||||||
|
auto port = (*iter)->GetCPort();
|
||||||
zone_server_list.erase(iter);
|
zone_server_list.erase(iter);
|
||||||
|
|
||||||
|
if (port != 0) {
|
||||||
|
m_ports_free.push_back(port);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
iter++;
|
iter++;
|
||||||
@@ -239,6 +243,14 @@ bool ZSList::SetLockedZone(uint16 iZoneID, bool iLock) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZSList::Init()
|
||||||
|
{
|
||||||
|
const WorldConfig* Config = WorldConfig::get();
|
||||||
|
for (uint16 i = Config->ZonePortLow; i <= Config->ZonePortHigh; ++i) {
|
||||||
|
m_ports_free.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ZSList::IsZoneLocked(uint16 iZoneID) {
|
bool ZSList::IsZoneLocked(uint16 iZoneID) {
|
||||||
for (auto &zone : pLockedZones) {
|
for (auto &zone : pLockedZones) {
|
||||||
if (zone == iZoneID)
|
if (zone == iZoneID)
|
||||||
@@ -579,28 +591,13 @@ void ZSList::RebootZone(const char* ip1, uint16 port, const char* ip2, uint32 sk
|
|||||||
|
|
||||||
uint16 ZSList::GetAvailableZonePort()
|
uint16 ZSList::GetAvailableZonePort()
|
||||||
{
|
{
|
||||||
const WorldConfig *Config = WorldConfig::get();
|
if (m_ports_free.empty()) {
|
||||||
int i;
|
return 0;
|
||||||
uint16 port = 0;
|
|
||||||
|
|
||||||
if (LastAllocatedPort == 0)
|
|
||||||
i = Config->ZonePortLow;
|
|
||||||
else
|
|
||||||
i = LastAllocatedPort + 1;
|
|
||||||
|
|
||||||
while (i != LastAllocatedPort && port == 0) {
|
|
||||||
if (i>Config->ZonePortHigh)
|
|
||||||
i = Config->ZonePortLow;
|
|
||||||
|
|
||||||
if (!FindByPort(i)) {
|
|
||||||
port = i;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
LastAllocatedPort = port;
|
|
||||||
|
|
||||||
return port;
|
auto first = m_ports_free.front();
|
||||||
|
m_ports_free.pop_front();
|
||||||
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ZSList::TriggerBootup(uint32 iZoneID, uint32 iInstanceID) {
|
uint32 ZSList::TriggerBootup(uint32 iZoneID, uint32 iInstanceID) {
|
||||||
|
|||||||
+3
-2
@@ -7,6 +7,7 @@
|
|||||||
#include "../common/event/timer.h"
|
#include "../common/event/timer.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
class WorldTCPConnection;
|
class WorldTCPConnection;
|
||||||
class ServerPacket;
|
class ServerPacket;
|
||||||
@@ -22,6 +23,7 @@ public:
|
|||||||
ZSList();
|
ZSList();
|
||||||
~ZSList();
|
~ZSList();
|
||||||
|
|
||||||
|
void Init();
|
||||||
bool IsZoneLocked(uint16 iZoneID);
|
bool IsZoneLocked(uint16 iZoneID);
|
||||||
bool SendPacket(ServerPacket *pack);
|
bool SendPacket(ServerPacket *pack);
|
||||||
bool SendPacket(uint32 zoneid, ServerPacket *pack);
|
bool SendPacket(uint32 zoneid, ServerPacket *pack);
|
||||||
@@ -73,8 +75,7 @@ private:
|
|||||||
uint32 NextID;
|
uint32 NextID;
|
||||||
uint16 pLockedZones[MaxLockedZones];
|
uint16 pLockedZones[MaxLockedZones];
|
||||||
uint32 CurGroupID;
|
uint32 CurGroupID;
|
||||||
uint16 LastAllocatedPort;
|
std::deque<uint16> m_ports_free;
|
||||||
|
|
||||||
std::unique_ptr<EQ::Timer> m_tick;
|
std::unique_ptr<EQ::Timer> m_tick;
|
||||||
std::unique_ptr<EQ::Timer> m_keepalive;
|
std::unique_ptr<EQ::Timer> m_keepalive;
|
||||||
|
|
||||||
|
|||||||
+27
-95
@@ -1057,110 +1057,42 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_Consent: {
|
case ServerOP_Consent: {
|
||||||
// Message string id's likely to be used here are:
|
zoneserver_list.SendPacket(pack); // update corpses in all zones
|
||||||
// CONSENT_YOURSELF = 399
|
|
||||||
// CONSENT_INVALID_NAME = 397
|
|
||||||
// TARGET_NOT_FOUND = 101
|
|
||||||
ZoneServer* zs;
|
|
||||||
ServerOP_Consent_Struct* s = (ServerOP_Consent_Struct*)pack->pBuffer;
|
|
||||||
ClientListEntry* cle = client_list.FindCharacter(s->grantname);
|
|
||||||
if (cle) {
|
|
||||||
if (cle->instance() != 0)
|
|
||||||
{
|
|
||||||
zs = zoneserver_list.FindByInstanceID(cle->instance());
|
|
||||||
if (zs) {
|
|
||||||
zs->SendPacket(pack);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
|
||||||
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
|
|
||||||
strcpy(scs->grantname, s->grantname);
|
|
||||||
strcpy(scs->ownername, s->ownername);
|
|
||||||
scs->permission = s->permission;
|
|
||||||
scs->zone_id = s->zone_id;
|
|
||||||
scs->instance_id = s->instance_id;
|
|
||||||
scs->message_string_id = 101;
|
|
||||||
zs = zoneserver_list.FindByInstanceID(s->instance_id);
|
|
||||||
if (zs) {
|
|
||||||
zs->SendPacket(pack);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogInfo("Unable to locate zone record for instance id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->instance_id);
|
|
||||||
}
|
|
||||||
safe_delete(pack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
zs = zoneserver_list.FindByZoneID(cle->zone());
|
|
||||||
if (zs) {
|
|
||||||
zs->SendPacket(pack);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// send target not found back to requester
|
|
||||||
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
|
||||||
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
|
|
||||||
strcpy(scs->grantname, s->grantname);
|
|
||||||
strcpy(scs->ownername, s->ownername);
|
|
||||||
scs->permission = s->permission;
|
|
||||||
scs->zone_id = s->zone_id;
|
|
||||||
scs->message_string_id = 101;
|
|
||||||
zs = zoneserver_list.FindByZoneID(s->zone_id);
|
|
||||||
if (zs) {
|
|
||||||
zs->SendPacket(pack);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogInfo("Unable to locate zone record for zone id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id);
|
|
||||||
}
|
|
||||||
safe_delete(pack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// send target not found back to requester
|
|
||||||
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
|
|
||||||
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
|
|
||||||
strcpy(scs->grantname, s->grantname);
|
|
||||||
strcpy(scs->ownername, s->ownername);
|
|
||||||
scs->permission = s->permission;
|
|
||||||
scs->zone_id = s->zone_id;
|
|
||||||
scs->message_string_id = 397;
|
|
||||||
zs = zoneserver_list.FindByZoneID(s->zone_id);
|
|
||||||
if (zs) {
|
|
||||||
zs->SendPacket(pack);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogInfo("Unable to locate zone record for zone id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id);
|
|
||||||
}
|
|
||||||
safe_delete(pack);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_Consent_Response: {
|
case ServerOP_Consent_Response: {
|
||||||
// Message string id's likely to be used here are:
|
|
||||||
// CONSENT_YOURSELF = 399
|
|
||||||
// CONSENT_INVALID_NAME = 397
|
|
||||||
// TARGET_NOT_FOUND = 101
|
|
||||||
ServerOP_Consent_Struct* s = (ServerOP_Consent_Struct*)pack->pBuffer;
|
ServerOP_Consent_Struct* s = (ServerOP_Consent_Struct*)pack->pBuffer;
|
||||||
if (s->instance_id != 0)
|
|
||||||
{
|
ZoneServer* owner_zs = nullptr;
|
||||||
ZoneServer* zs = zoneserver_list.FindByInstanceID(s->instance_id);
|
if (s->instance_id == 0) {
|
||||||
if (zs) {
|
owner_zs = zoneserver_list.FindByZoneID(s->zone_id);
|
||||||
zs->SendPacket(pack);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogInfo("Unable to locate zone record for instance id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->instance_id);
|
owner_zs = zoneserver_list.FindByInstanceID(s->instance_id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
if (owner_zs) {
|
||||||
{
|
owner_zs->SendPacket(pack);
|
||||||
ZoneServer* zs = zoneserver_list.FindByZoneID(s->zone_id);
|
|
||||||
if (zs) {
|
|
||||||
zs->SendPacket(pack);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogInfo("Unable to locate zone record for zone id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id);
|
LogInfo("Unable to locate zone record for zone id [{}] or instance id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id, s->instance_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->consent_type == EQEmu::consent::Normal) {
|
||||||
|
// send the message to the client being granted or denied permission
|
||||||
|
ClientListEntry* cle = client_list.FindCharacter(s->grantname);
|
||||||
|
if (cle) {
|
||||||
|
ZoneServer* granted_zs = nullptr;
|
||||||
|
if (cle->instance() == 0) {
|
||||||
|
granted_zs = zoneserver_list.FindByZoneID(cle->zone());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
granted_zs = zoneserver_list.FindByInstanceID(cle->instance());
|
||||||
|
}
|
||||||
|
// avoid sending twice if owner and granted are in same zone
|
||||||
|
if (granted_zs && granted_zs != owner_zs) {
|
||||||
|
granted_zs->SendPacket(pack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+3
-2
@@ -82,7 +82,6 @@ SET(zone_sources
|
|||||||
main.cpp
|
main.cpp
|
||||||
map.cpp
|
map.cpp
|
||||||
merc.cpp
|
merc.cpp
|
||||||
metric_event_types.cpp
|
|
||||||
mob.cpp
|
mob.cpp
|
||||||
mob_ai.cpp
|
mob_ai.cpp
|
||||||
mob_appearance.cpp
|
mob_appearance.cpp
|
||||||
@@ -142,6 +141,7 @@ SET(zone_sources
|
|||||||
zone.cpp
|
zone.cpp
|
||||||
zone_config.cpp
|
zone_config.cpp
|
||||||
zonedb.cpp
|
zonedb.cpp
|
||||||
|
zone_reload.cpp
|
||||||
zoning.cpp
|
zoning.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -248,7 +248,8 @@ SET(zone_headers
|
|||||||
zone.h
|
zone.h
|
||||||
zone_config.h
|
zone_config.h
|
||||||
zonedb.h
|
zonedb.h
|
||||||
zonedump.h)
|
zonedump.h
|
||||||
|
zone_reload.h )
|
||||||
|
|
||||||
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
|
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
|
||||||
|
|
||||||
|
|||||||
+21
-2
@@ -1023,6 +1023,24 @@ void Client::ResetAlternateAdvancementTimers() {
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::ResetOnDeathAlternateAdvancement() {
|
||||||
|
for (const auto &aa : aa_ranks) {
|
||||||
|
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first);
|
||||||
|
auto ability = ability_rank.first;
|
||||||
|
auto rank = ability_rank.second;
|
||||||
|
|
||||||
|
if (!ability)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!rank)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// since they're dying, we just need to clear the DB
|
||||||
|
if (ability->reset_on_death)
|
||||||
|
p_timers.Clear(&database, rank->spell_type + pTimerAAStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Client::PurchaseAlternateAdvancementRank(int rank_id) {
|
void Client::PurchaseAlternateAdvancementRank(int rank_id) {
|
||||||
AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id);
|
AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id);
|
||||||
if(!rank) {
|
if(!rank) {
|
||||||
@@ -1646,7 +1664,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
|
|||||||
LogInfo("Loading Alternate Advancement Abilities");
|
LogInfo("Loading Alternate Advancement Abilities");
|
||||||
abilities.clear();
|
abilities.clear();
|
||||||
std::string query = "SELECT id, name, category, classes, races, deities, drakkin_heritage, status, type, charges, "
|
std::string query = "SELECT id, name, category, classes, races, deities, drakkin_heritage, status, type, charges, "
|
||||||
"grant_only, first_rank_id FROM aa_ability WHERE enabled = 1";
|
"grant_only, reset_on_death, first_rank_id FROM aa_ability WHERE enabled = 1";
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if(results.Success()) {
|
if(results.Success()) {
|
||||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||||
@@ -1663,7 +1681,8 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
|
|||||||
ability->type = atoi(row[8]);
|
ability->type = atoi(row[8]);
|
||||||
ability->charges = atoi(row[9]);
|
ability->charges = atoi(row[9]);
|
||||||
ability->grant_only = atoi(row[10]) != 0 ? true : false;
|
ability->grant_only = atoi(row[10]) != 0 ? true : false;
|
||||||
ability->first_rank_id = atoi(row[11]);
|
ability->reset_on_death = atoi(row[11]) != 0 ? true : false;
|
||||||
|
ability->first_rank_id = atoi(row[12]);
|
||||||
ability->first = nullptr;
|
ability->first = nullptr;
|
||||||
|
|
||||||
abilities[ability->id] = std::unique_ptr<AA::Ability>(ability);
|
abilities[ability->id] = std::unique_ptr<AA::Ability>(ability);
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public:
|
|||||||
int drakkin_heritage;
|
int drakkin_heritage;
|
||||||
int status;
|
int status;
|
||||||
bool grant_only;
|
bool grant_only;
|
||||||
|
bool reset_on_death;
|
||||||
int type;
|
int type;
|
||||||
int charges;
|
int charges;
|
||||||
int first_rank_id;
|
int first_rank_id;
|
||||||
|
|||||||
+11
-3
@@ -32,6 +32,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "water_map.h"
|
||||||
|
|
||||||
extern Zone* zone;
|
extern Zone* zone;
|
||||||
//#define LOSDEBUG 6
|
//#define LOSDEBUG 6
|
||||||
@@ -139,7 +140,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
|
|||||||
|
|
||||||
if (RuleB(Aggro, UseLevelAggro))
|
if (RuleB(Aggro, UseLevelAggro))
|
||||||
{
|
{
|
||||||
if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3)
|
if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3 && !AlwaysAggro())
|
||||||
{
|
{
|
||||||
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2);
|
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2);
|
||||||
return;
|
return;
|
||||||
@@ -147,7 +148,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY ) {
|
if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY && !AlwaysAggro()) {
|
||||||
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(),
|
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(),
|
||||||
dist2, iAggroRange2);
|
dist2, iAggroRange2);
|
||||||
return;
|
return;
|
||||||
@@ -238,6 +239,11 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't want to aggro clients outside of water if we're water only.
|
||||||
|
if (mob->IsClient() && mob->CastToClient()->GetLastRegion() != RegionTypeWater && IsUnderwaterOnly()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pets shouldn't scan for aggro
|
* Pets shouldn't scan for aggro
|
||||||
*/
|
*/
|
||||||
@@ -318,7 +324,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
//old InZone check taken care of above by !mob->CastToClient()->Connected()
|
//old InZone check taken care of above by !mob->CastToClient()->Connected()
|
||||||
(
|
(
|
||||||
( GetLevel() >= RuleI(Aggro, MinAggroLevel))
|
( GetLevel() >= RuleI(Aggro, MinAggroLevel))
|
||||||
||(GetBodyType() == 3)
|
||(GetBodyType() == 3) || AlwaysAggro()
|
||||||
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
|
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
|
||||||
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
|
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
|
||||||
|
|
||||||
@@ -352,6 +358,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
//old InZone check taken care of above by !mob->CastToClient()->Connected()
|
//old InZone check taken care of above by !mob->CastToClient()->Connected()
|
||||||
(
|
(
|
||||||
( GetINT() <= RuleI(Aggro, IntAggroThreshold) )
|
( GetINT() <= RuleI(Aggro, IntAggroThreshold) )
|
||||||
|
|| AlwaysAggro()
|
||||||
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
|
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
|
||||||
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
|
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
|
||||||
|
|
||||||
@@ -383,6 +390,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
LogAggro("Dist^2: [{}]\n", dist2);
|
LogAggro("Dist^2: [{}]\n", dist2);
|
||||||
LogAggro("Range^2: [{}]\n", iAggroRange2);
|
LogAggro("Range^2: [{}]\n", iAggroRange2);
|
||||||
LogAggro("Faction: [{}]\n", fv);
|
LogAggro("Faction: [{}]\n", fv);
|
||||||
|
LogAggro("AlwaysAggroFlag: [{}]\n", AlwaysAggro());
|
||||||
LogAggro("Int: [{}]\n", GetINT());
|
LogAggro("Int: [{}]\n", GetINT());
|
||||||
LogAggro("Con: [{}]\n", GetLevelCon(mob->GetLevel()));
|
LogAggro("Con: [{}]\n", GetLevelCon(mob->GetLevel()));
|
||||||
|
|
||||||
|
|||||||
+20
-9
@@ -724,20 +724,20 @@ int Mob::GetClassRaceACBonus()
|
|||||||
hardcap = 32;
|
hardcap = 32;
|
||||||
softcap = 15;
|
softcap = 15;
|
||||||
}
|
}
|
||||||
int weight = IsClient() ? CastToClient()->CalcCurrentWeight() : 0;
|
int weight = IsClient() ? CastToClient()->CalcCurrentWeight()/10 : 0;
|
||||||
if (weight < hardcap - 1) {
|
if (weight < hardcap - 1) {
|
||||||
int temp = level + 5;
|
double temp = level + 5;
|
||||||
if (weight > softcap) {
|
if (weight > softcap) {
|
||||||
double redux = (weight - softcap) * 6.66667;
|
double redux = static_cast<double>(weight - softcap) * 6.66667;
|
||||||
redux = (100.0 - std::min(100.0, redux)) * 0.01;
|
redux = (100.0 - std::min(100.0, redux)) * 0.01;
|
||||||
temp = std::max(0, static_cast<int>(temp * redux));
|
temp = std::max(0.0, temp * redux);
|
||||||
}
|
}
|
||||||
ac_bonus = (4 * temp) / 3;
|
ac_bonus = static_cast<int>((4.0 * temp) / 3.0);
|
||||||
}
|
}
|
||||||
else if (weight > hardcap + 1) {
|
else if (weight > hardcap + 1) {
|
||||||
int temp = level + 5;
|
double temp = level + 5;
|
||||||
double multiplier = std::min(1.0, (weight - (hardcap - 10.0)) / 100.0);
|
double multiplier = std::min(1.0, (weight - (static_cast<double>(hardcap) - 10.0)) / 100.0);
|
||||||
temp = (4 * temp) / 3;
|
temp = (4.0 * temp) / 3.0;
|
||||||
ac_bonus -= static_cast<int>(temp * multiplier);
|
ac_bonus -= static_cast<int>(temp * multiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -799,7 +799,7 @@ int Mob::ACSum()
|
|||||||
// EQ math
|
// EQ math
|
||||||
ac = (ac * 4) / 3;
|
ac = (ac * 4) / 3;
|
||||||
// anti-twink
|
// anti-twink
|
||||||
if (IsClient() && GetLevel() < 50)
|
if (IsClient() && GetLevel() < RuleI(Combat, LevelToStopACTwinkControl))
|
||||||
ac = std::min(ac, 25 + 6 * GetLevel());
|
ac = std::min(ac, 25 + 6 * GetLevel());
|
||||||
ac = std::max(0, ac + GetClassRaceACBonus());
|
ac = std::max(0, ac + GetClassRaceACBonus());
|
||||||
if (IsNPC()) {
|
if (IsNPC()) {
|
||||||
@@ -1852,6 +1852,17 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk
|
|||||||
BuffFadeDetrimental();
|
BuffFadeDetrimental();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reset AA reuse timers that need to be, live-like this is only Lay on Hands
|
||||||
|
*/
|
||||||
|
ResetOnDeathAlternateAdvancement();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reset reuse timer for classic skill based Lay on Hands (For tit I guess)
|
||||||
|
*/
|
||||||
|
if (GetClass() == PALADIN) // we could check if it's not expired I guess, but should be fine not to
|
||||||
|
p_timers.Clear(&database, pTimerLayHands);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Finally, send em home
|
Finally, send em home
|
||||||
|
|
||||||
|
|||||||
+365
-176
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -73,7 +73,7 @@ private:
|
|||||||
int m_owner;
|
int m_owner;
|
||||||
int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell
|
int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell
|
||||||
int spell_id; // spell we cast
|
int spell_id; // spell we cast
|
||||||
int distance; // distance we remove
|
float distance; // distance we remove
|
||||||
Timer remove_timer; // when we depop
|
Timer remove_timer; // when we depop
|
||||||
Timer process_timer; // rate limit process calls
|
Timer process_timer; // rate limit process calls
|
||||||
Timer cast_timer; // some auras pulse
|
Timer cast_timer; // some auras pulse
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ Beacon::Beacon(Mob *at_mob, int lifetime)
|
|||||||
:Mob
|
:Mob
|
||||||
(
|
(
|
||||||
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0,
|
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false
|
||||||
),
|
),
|
||||||
remove_timer(lifetime),
|
remove_timer(lifetime),
|
||||||
spell_timer(0)
|
spell_timer(0)
|
||||||
|
|||||||
+158
-35
@@ -6421,32 +6421,52 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
|||||||
|
|
||||||
bool taunt_time = taunt_timer.Check();
|
bool taunt_time = taunt_timer.Check();
|
||||||
bool ca_time = classattack_timer.Check(false);
|
bool ca_time = classattack_timer.Check(false);
|
||||||
|
bool ma_time = monkattack_timer.Check(false);
|
||||||
bool ka_time = knightattack_timer.Check(false);
|
bool ka_time = knightattack_timer.Check(false);
|
||||||
if((taunt_time || ca_time || ka_time) && !IsAttackAllowed(target))
|
|
||||||
|
if (taunt_time) {
|
||||||
|
|
||||||
|
// Bots without this skill shouldn't be 'checking' on this timer..let's just disable it and avoid the extra IsAttackAllowed() checks
|
||||||
|
// Note: this is done here instead of NPC::ctor() because taunt skill can be acquired during level ups (the timer is re-enabled in CalcBotStats())
|
||||||
|
if (!GetSkill(EQEmu::skills::SkillTaunt)) {
|
||||||
|
|
||||||
|
taunt_timer.Disable();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsAttackAllowed(target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ca_time || ma_time || ka_time) && !IsAttackAllowed(target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(ka_time){
|
if(ka_time){
|
||||||
int knightreuse = 1000;
|
|
||||||
switch(GetClass()){
|
switch(GetClass()){
|
||||||
case SHADOWKNIGHT:
|
case SHADOWKNIGHT: {
|
||||||
case SHADOWKNIGHTGM: {
|
|
||||||
CastSpell(SPELL_NPC_HARM_TOUCH, target->GetID());
|
CastSpell(SPELL_NPC_HARM_TOUCH, target->GetID());
|
||||||
knightreuse = (HarmTouchReuseTime * 1000);
|
knightattack_timer.Start(HarmTouchReuseTime * 1000);
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PALADIN:
|
|
||||||
case PALADINGM: {
|
|
||||||
if(GetHPRatio() < 20) {
|
|
||||||
CastSpell(SPELL_LAY_ON_HANDS, GetID());
|
|
||||||
knightreuse = (LayOnHandsReuseTime * 1000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
knightreuse = 2000;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PALADIN: {
|
||||||
|
if(GetHPRatio() < 20) {
|
||||||
|
CastSpell(SPELL_LAY_ON_HANDS, GetID());
|
||||||
|
knightattack_timer.Start(LayOnHandsReuseTime * 1000);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
knightattack_timer.Start(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
knightattack_timer.Start(knightreuse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(taunting && target && target->IsNPC() && taunt_time) {
|
if(taunting && target && target->IsNPC() && taunt_time) {
|
||||||
@@ -6457,8 +6477,66 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ca_time)
|
if (ma_time) {
|
||||||
|
switch (GetClass()) {
|
||||||
|
case MONK: {
|
||||||
|
int reuse = (MonkSpecialAttack(target, EQEmu::skills::SkillTigerClaw) - 1);
|
||||||
|
|
||||||
|
// Live AA - Technique of Master Wu
|
||||||
|
int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack;
|
||||||
|
|
||||||
|
if (wuchance) {
|
||||||
|
const int MonkSPA[5] = {
|
||||||
|
EQEmu::skills::SkillFlyingKick,
|
||||||
|
EQEmu::skills::SkillDragonPunch,
|
||||||
|
EQEmu::skills::SkillEagleStrike,
|
||||||
|
EQEmu::skills::SkillTigerClaw,
|
||||||
|
EQEmu::skills::SkillRoundKick
|
||||||
|
};
|
||||||
|
int extra = 0;
|
||||||
|
// always 1/4 of the double attack chance, 25% at rank 5 (100/4)
|
||||||
|
while (wuchance > 0) {
|
||||||
|
if (zone->random.Roll(wuchance)) {
|
||||||
|
++extra;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wuchance /= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mob* bo = GetBotOwner();
|
||||||
|
if (bo && bo->IsClient() && bo->CastToClient()->GetBotOption(Client::booMonkWuMessage)) {
|
||||||
|
|
||||||
|
bo->Message(
|
||||||
|
GENERIC_EMOTE,
|
||||||
|
"The spirit of Master Wu fills %s! %s gains %d additional attack(s).",
|
||||||
|
GetCleanName(),
|
||||||
|
GetCleanName(),
|
||||||
|
extra
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto classic = RuleB(Combat, ClassicMasterWu);
|
||||||
|
while (extra) {
|
||||||
|
MonkSpecialAttack(GetTarget(), (classic ? MonkSPA[zone->random.Int(0, 4)] : EQEmu::skills::SkillTigerClaw));
|
||||||
|
--extra;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float HasteModifier = (GetHaste() * 0.01f);
|
||||||
|
monkattack_timer.Start((reuse * 1000) / HasteModifier);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ca_time) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
float HasteModifier = (GetHaste() * 0.01f);
|
float HasteModifier = (GetHaste() * 0.01f);
|
||||||
uint16 skill_to_use = -1;
|
uint16 skill_to_use = -1;
|
||||||
@@ -6493,18 +6571,22 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MONK:
|
case MONK:
|
||||||
if(GetLevel() >= 30)
|
if (GetLevel() >= 30) {
|
||||||
skill_to_use = EQEmu::skills::SkillFlyingKick;
|
skill_to_use = EQEmu::skills::SkillFlyingKick;
|
||||||
else if(GetLevel() >= 25)
|
}
|
||||||
|
else if (GetLevel() >= 25) {
|
||||||
skill_to_use = EQEmu::skills::SkillDragonPunch;
|
skill_to_use = EQEmu::skills::SkillDragonPunch;
|
||||||
else if(GetLevel() >= 20)
|
}
|
||||||
|
else if (GetLevel() >= 20) {
|
||||||
skill_to_use = EQEmu::skills::SkillEagleStrike;
|
skill_to_use = EQEmu::skills::SkillEagleStrike;
|
||||||
else if(GetLevel() >= 10)
|
}
|
||||||
skill_to_use = EQEmu::skills::SkillTigerClaw;
|
else if (GetLevel() >= 5) {
|
||||||
else if(GetLevel() >= 5)
|
|
||||||
skill_to_use = EQEmu::skills::SkillRoundKick;
|
skill_to_use = EQEmu::skills::SkillRoundKick;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
skill_to_use = EQEmu::skills::SkillKick;
|
skill_to_use = EQEmu::skills::SkillKick;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ROGUE:
|
case ROGUE:
|
||||||
skill_to_use = EQEmu::skills::SkillBackstab;
|
skill_to_use = EQEmu::skills::SkillBackstab;
|
||||||
@@ -6555,19 +6637,54 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skill_to_use == EQEmu::skills::SkillFlyingKick || skill_to_use == EQEmu::skills::SkillDragonPunch || skill_to_use == EQEmu::skills::SkillEagleStrike || skill_to_use == EQEmu::skills::SkillTigerClaw || skill_to_use == EQEmu::skills::SkillRoundKick) {
|
if (
|
||||||
|
skill_to_use == EQEmu::skills::SkillFlyingKick ||
|
||||||
|
skill_to_use == EQEmu::skills::SkillDragonPunch ||
|
||||||
|
skill_to_use == EQEmu::skills::SkillEagleStrike ||
|
||||||
|
skill_to_use == EQEmu::skills::SkillRoundKick
|
||||||
|
) {
|
||||||
reuse = (MonkSpecialAttack(target, skill_to_use) - 1);
|
reuse = (MonkSpecialAttack(target, skill_to_use) - 1);
|
||||||
MonkSpecialAttack(target, skill_to_use);
|
|
||||||
uint32 bDoubleSpecialAttack = (itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack);
|
|
||||||
if(bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0, 100))) {
|
|
||||||
int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick };
|
|
||||||
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]);
|
|
||||||
int TripleChance = 25;
|
|
||||||
if (bDoubleSpecialAttack > 100)
|
|
||||||
TripleChance += (TripleChance * (100 - bDoubleSpecialAttack) / 100);
|
|
||||||
|
|
||||||
if(TripleChance > zone->random.Int(0,100))
|
// Live AA - Technique of Master Wu
|
||||||
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]);
|
int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack;
|
||||||
|
|
||||||
|
if (wuchance) {
|
||||||
|
const int MonkSPA[5] = {
|
||||||
|
EQEmu::skills::SkillFlyingKick,
|
||||||
|
EQEmu::skills::SkillDragonPunch,
|
||||||
|
EQEmu::skills::SkillEagleStrike,
|
||||||
|
EQEmu::skills::SkillTigerClaw,
|
||||||
|
EQEmu::skills::SkillRoundKick
|
||||||
|
};
|
||||||
|
int extra = 0;
|
||||||
|
// always 1/4 of the double attack chance, 25% at rank 5 (100/4)
|
||||||
|
while (wuchance > 0) {
|
||||||
|
if (zone->random.Roll(wuchance)) {
|
||||||
|
++extra;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wuchance /= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mob* bo = GetBotOwner();
|
||||||
|
if (bo && bo->IsClient() && bo->CastToClient()->GetBotOption(Client::booMonkWuMessage)) {
|
||||||
|
|
||||||
|
bo->Message(
|
||||||
|
GENERIC_EMOTE,
|
||||||
|
"The spirit of Master Wu fills %s! %s gains %d additional attack(s).",
|
||||||
|
GetCleanName(),
|
||||||
|
GetCleanName(),
|
||||||
|
extra
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto classic = RuleB(Combat, ClassicMasterWu);
|
||||||
|
while (extra) {
|
||||||
|
MonkSpecialAttack(GetTarget(), (classic ? MonkSPA[zone->random.Int(0, 4)] : skill_to_use));
|
||||||
|
--extra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reuse *= 1000;
|
reuse *= 1000;
|
||||||
@@ -8966,6 +9083,12 @@ void Bot::CalcBotStats(bool showtext) {
|
|||||||
skills[sindex] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)sindex, GetLevel());
|
skills[sindex] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)sindex, GetLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
taunt_timer.Start(1000);
|
||||||
|
|
||||||
|
if (GetClass() == MONK && GetLevel() >= 10) {
|
||||||
|
monkattack_timer.Start(1000);
|
||||||
|
}
|
||||||
|
|
||||||
LoadAAs();
|
LoadAAs();
|
||||||
GenerateSpecialAttacks();
|
GenerateSpecialAttacks();
|
||||||
|
|
||||||
|
|||||||
+29
-1
@@ -3928,6 +3928,16 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
|
|||||||
"<td><c \"#00CCCC\">null</td>"
|
"<td><c \"#00CCCC\">null</td>"
|
||||||
"<td><c \"#888888\">(toggles)</td>"
|
"<td><c \"#888888\">(toggles)</td>"
|
||||||
"</tr>"
|
"</tr>"
|
||||||
|
"<tr>"
|
||||||
|
"<td><c \"#CCCCCC\">monkwumessage</td>"
|
||||||
|
"<td><c \"#00CC00\">enable <c \"#CCCCCC\">| <c \"#00CC00\">disable</td>"
|
||||||
|
"<td><c \"#888888\">displays monk wu trigger messages</td>"
|
||||||
|
"</tr>"
|
||||||
|
"<tr>"
|
||||||
|
"<td></td>"
|
||||||
|
"<td><c \"#00CCCC\">null</td>"
|
||||||
|
"<td><c \"#888888\">(toggles)</td>"
|
||||||
|
"</tr>"
|
||||||
"<tr>"
|
"<tr>"
|
||||||
"<td><c \"#CCCCCC\">current</td>"
|
"<td><c \"#CCCCCC\">current</td>"
|
||||||
"<td></td>"
|
"<td></td>"
|
||||||
@@ -4103,6 +4113,22 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
c->Message(m_action, "Bot 'buff counter' is now %s.", (c->GetBotOption(Client::booBuffCounter) == true ? "enabled" : "disabled"));
|
c->Message(m_action, "Bot 'buff counter' is now %s.", (c->GetBotOption(Client::booBuffCounter) == true ? "enabled" : "disabled"));
|
||||||
}
|
}
|
||||||
|
else if (!owner_option.compare("monkwumessage")) {
|
||||||
|
|
||||||
|
if (!argument.compare("enable")) {
|
||||||
|
c->SetBotOption(Client::booMonkWuMessage, true);
|
||||||
|
}
|
||||||
|
else if (!argument.compare("disable")) {
|
||||||
|
c->SetBotOption(Client::booMonkWuMessage, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c->SetBotOption(Client::booMonkWuMessage, !c->GetBotOption(Client::booMonkWuMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
database.botdb.SaveOwnerOption(c->CharacterID(), Client::booMonkWuMessage, c->GetBotOption(Client::booMonkWuMessage));
|
||||||
|
|
||||||
|
c->Message(m_action, "Bot 'monk wu message' is now %s.", (c->GetBotOption(Client::booMonkWuMessage) == true ? "enabled" : "disabled"));
|
||||||
|
}
|
||||||
else if (!owner_option.compare("current")) {
|
else if (!owner_option.compare("current")) {
|
||||||
|
|
||||||
std::string window_title = "Current Bot Owner Options Settings";
|
std::string window_title = "Current Bot Owner Options Settings";
|
||||||
@@ -4119,6 +4145,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
|
|||||||
"<tr>" "<td><c \"#CCCCCC\">altcombat</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
|
"<tr>" "<td><c \"#CCCCCC\">altcombat</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
|
||||||
"<tr>" "<td><c \"#CCCCCC\">autodefend</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
|
"<tr>" "<td><c \"#CCCCCC\">autodefend</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
|
||||||
"<tr>" "<td><c \"#CCCCCC\">buffcounter</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
|
"<tr>" "<td><c \"#CCCCCC\">buffcounter</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
|
||||||
|
"<tr>" "<td><c \"#CCCCCC\">monkwumessage</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
|
||||||
"</table>",
|
"</table>",
|
||||||
(c->GetBotOption(Client::booDeathMarquee) ? "enabled" : "disabled"),
|
(c->GetBotOption(Client::booDeathMarquee) ? "enabled" : "disabled"),
|
||||||
(c->GetBotOption(Client::booStatsUpdate) ? "enabled" : "disabled"),
|
(c->GetBotOption(Client::booStatsUpdate) ? "enabled" : "disabled"),
|
||||||
@@ -4126,7 +4153,8 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
|
|||||||
(c->GetBotOption(Client::booSpawnMessageClassSpecific) ? "class" : "default"),
|
(c->GetBotOption(Client::booSpawnMessageClassSpecific) ? "class" : "default"),
|
||||||
(RuleB(Bots, AllowOwnerOptionAltCombat) ? (c->GetBotOption(Client::booAltCombat) ? "enabled" : "disabled") : "restricted"),
|
(RuleB(Bots, AllowOwnerOptionAltCombat) ? (c->GetBotOption(Client::booAltCombat) ? "enabled" : "disabled") : "restricted"),
|
||||||
(RuleB(Bots, AllowOwnerOptionAutoDefend) ? (c->GetBotOption(Client::booAutoDefend) ? "enabled" : "disabled") : "restricted"),
|
(RuleB(Bots, AllowOwnerOptionAutoDefend) ? (c->GetBotOption(Client::booAutoDefend) ? "enabled" : "disabled") : "restricted"),
|
||||||
(c->GetBotOption(Client::booBuffCounter) ? "enabled" : "disabled")
|
(c->GetBotOption(Client::booBuffCounter) ? "enabled" : "disabled"),
|
||||||
|
(c->GetBotOption(Client::booMonkWuMessage) ? "enabled" : "disabled")
|
||||||
);
|
);
|
||||||
|
|
||||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
||||||
|
|||||||
@@ -2257,6 +2257,7 @@ bool BotDatabase::SaveOwnerOption(const uint32 owner_id, size_t type, const bool
|
|||||||
case Client::booAltCombat:
|
case Client::booAltCombat:
|
||||||
case Client::booAutoDefend:
|
case Client::booAutoDefend:
|
||||||
case Client::booBuffCounter:
|
case Client::booBuffCounter:
|
||||||
|
case Client::booMonkWuMessage:
|
||||||
{
|
{
|
||||||
query = fmt::format(
|
query = fmt::format(
|
||||||
"REPLACE INTO `bot_owner_options`(`owner_id`, `option_type`, `option_value`) VALUES ('{}', '{}', '{}')",
|
"REPLACE INTO `bot_owner_options`(`owner_id`, `option_type`, `option_value`) VALUES ('{}', '{}', '{}')",
|
||||||
|
|||||||
+135
-4
@@ -121,7 +121,8 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0
|
0,
|
||||||
|
false
|
||||||
),
|
),
|
||||||
hpupdate_timer(2000),
|
hpupdate_timer(2000),
|
||||||
camp_timer(29000),
|
camp_timer(29000),
|
||||||
@@ -165,6 +166,7 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
hp_self_update_throttle_timer(300),
|
hp_self_update_throttle_timer(300),
|
||||||
hp_other_update_throttle_timer(500),
|
hp_other_update_throttle_timer(500),
|
||||||
position_update_timer(10000),
|
position_update_timer(10000),
|
||||||
|
consent_throttle_timer(2000),
|
||||||
tmSitting(0)
|
tmSitting(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -254,6 +256,7 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
TotalSecondsPlayed = 0;
|
TotalSecondsPlayed = 0;
|
||||||
keyring.clear();
|
keyring.clear();
|
||||||
bind_sight_target = nullptr;
|
bind_sight_target = nullptr;
|
||||||
|
p_raid_instance = nullptr;
|
||||||
mercid = 0;
|
mercid = 0;
|
||||||
mercSlot = 0;
|
mercSlot = 0;
|
||||||
InitializeMercInfo();
|
InitializeMercInfo();
|
||||||
@@ -357,6 +360,7 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
bot_owner_options[booAltCombat] = RuleB(Bots, AllowOwnerOptionAltCombat);
|
bot_owner_options[booAltCombat] = RuleB(Bots, AllowOwnerOptionAltCombat);
|
||||||
bot_owner_options[booAutoDefend] = RuleB(Bots, AllowOwnerOptionAutoDefend);
|
bot_owner_options[booAutoDefend] = RuleB(Bots, AllowOwnerOptionAutoDefend);
|
||||||
bot_owner_options[booBuffCounter] = false;
|
bot_owner_options[booBuffCounter] = false;
|
||||||
|
bot_owner_options[booMonkWuMessage] = false;
|
||||||
|
|
||||||
SetBotPulling(false);
|
SetBotPulling(false);
|
||||||
SetBotPrecombat(false);
|
SetBotPrecombat(false);
|
||||||
@@ -6254,6 +6258,52 @@ void Client::DragCorpses()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::ConsentCorpses(std::string consent_name, bool deny)
|
||||||
|
{
|
||||||
|
if (strcasecmp(consent_name.c_str(), GetName()) == 0) {
|
||||||
|
MessageString(Chat::Red, CONSENT_YOURSELF);
|
||||||
|
}
|
||||||
|
else if (!consent_throttle_timer.Check()) {
|
||||||
|
MessageString(Chat::Red, CONSENT_WAIT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto pack = new ServerPacket(ServerOP_Consent, sizeof(ServerOP_Consent_Struct));
|
||||||
|
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
|
||||||
|
strn0cpy(scs->grantname, consent_name.c_str(), sizeof(scs->grantname));
|
||||||
|
strn0cpy(scs->ownername, GetName(), sizeof(scs->ownername));
|
||||||
|
strn0cpy(scs->zonename, "Unknown", sizeof(scs->zonename));
|
||||||
|
scs->permission = deny ? 0 : 1;
|
||||||
|
scs->zone_id = zone->GetZoneID();
|
||||||
|
scs->instance_id = zone->GetInstanceID();
|
||||||
|
scs->consent_type = EQEmu::consent::Normal;
|
||||||
|
scs->consent_id = 0;
|
||||||
|
if (strcasecmp(scs->grantname, "group") == 0) {
|
||||||
|
if (!deny) {
|
||||||
|
Group* grp = GetGroup();
|
||||||
|
scs->consent_id = grp ? grp->GetID() : 0;
|
||||||
|
}
|
||||||
|
scs->consent_type = EQEmu::consent::Group;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(scs->grantname, "raid") == 0) {
|
||||||
|
if (!deny) {
|
||||||
|
Raid* raid = GetRaid();
|
||||||
|
scs->consent_id = raid ? raid->GetID() : 0;
|
||||||
|
}
|
||||||
|
scs->consent_type = EQEmu::consent::Raid;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(scs->grantname, "guild") == 0) {
|
||||||
|
if (!deny) {
|
||||||
|
scs->consent_id = GuildID();
|
||||||
|
}
|
||||||
|
scs->consent_type = EQEmu::consent::Guild;
|
||||||
|
// update all corpses in db so buried/unloaded corpses see new consent id
|
||||||
|
database.UpdateCharacterCorpseConsent(CharacterID(), scs->consent_id);
|
||||||
|
}
|
||||||
|
worldserver.SendPacket(pack);
|
||||||
|
safe_delete(pack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration)
|
void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration)
|
||||||
{
|
{
|
||||||
if(!target || !IsValidSpell(spell_id) || this->GetID() == target->GetID())
|
if(!target || !IsValidSpell(spell_id) || this->GetID() == target->GetID())
|
||||||
@@ -7748,6 +7798,8 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra
|
|||||||
// few optimizations
|
// few optimizations
|
||||||
if (GetFeigned())
|
if (GetFeigned())
|
||||||
return FACTION_INDIFFERENT;
|
return FACTION_INDIFFERENT;
|
||||||
|
if(!zone->CanDoCombat())
|
||||||
|
return FACTION_INDIFFERENT;
|
||||||
if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead())
|
if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead())
|
||||||
return FACTION_INDIFFERENT;
|
return FACTION_INDIFFERENT;
|
||||||
if (IsInvisible(tnpc))
|
if (IsInvisible(tnpc))
|
||||||
@@ -8533,13 +8585,13 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
|
|||||||
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
|
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
|
||||||
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
|
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
|
||||||
|
|
||||||
qr->mob_id = target->GetID(); // Entity ID for the from mob name
|
qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name
|
||||||
qr->target_id = GetID(); // The Client ID (this)
|
qr->target_id = GetID(); // The Client ID (this)
|
||||||
qr->copper = copper;
|
qr->copper = copper;
|
||||||
qr->silver = silver;
|
qr->silver = silver;
|
||||||
qr->gold = gold;
|
qr->gold = gold;
|
||||||
qr->platinum = platinum;
|
qr->platinum = platinum;
|
||||||
qr->item_id = itemid;
|
qr->item_id[0] = itemid;
|
||||||
qr->exp_reward = exp;
|
qr->exp_reward = exp;
|
||||||
|
|
||||||
if (copper > 0 || silver > 0 || gold > 0 || platinum > 0)
|
if (copper > 0 || silver > 0 || gold > 0 || platinum > 0)
|
||||||
@@ -8550,7 +8602,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
|
|||||||
|
|
||||||
if (faction)
|
if (faction)
|
||||||
{
|
{
|
||||||
if (target->IsNPC())
|
if (target && target->IsNPC())
|
||||||
{
|
{
|
||||||
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
|
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
|
||||||
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
|
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
|
||||||
@@ -8566,6 +8618,42 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction)
|
||||||
|
{
|
||||||
|
auto outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct));
|
||||||
|
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
|
||||||
|
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
|
||||||
|
|
||||||
|
memcpy(qr, &reward, sizeof(QuestReward_Struct));
|
||||||
|
|
||||||
|
// not set in caller because reasons
|
||||||
|
qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name
|
||||||
|
|
||||||
|
if (reward.copper > 0 || reward.silver > 0 || reward.gold > 0 || reward.platinum > 0)
|
||||||
|
AddMoneyToPP(reward.copper, reward.silver, reward.gold, reward.platinum, false);
|
||||||
|
|
||||||
|
for (int i = 0; i < QUESTREWARD_COUNT; ++i)
|
||||||
|
if (reward.item_id[i] > 0)
|
||||||
|
SummonItem(reward.item_id[i], 0, 0, 0, 0, 0, 0, false, EQEmu::invslot::slotCursor);
|
||||||
|
|
||||||
|
if (faction)
|
||||||
|
{
|
||||||
|
if (target && target->IsNPC())
|
||||||
|
{
|
||||||
|
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
|
||||||
|
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
|
||||||
|
qr->faction = target->CastToNPC()->GetPrimaryFaction();
|
||||||
|
qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reward.exp_reward> 0)
|
||||||
|
AddEXP(reward.exp_reward);
|
||||||
|
|
||||||
|
QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
|
||||||
void Client::SendHPUpdateMarquee(){
|
void Client::SendHPUpdateMarquee(){
|
||||||
if (!this || !this->IsClient() || !this->current_hp || !this->max_hp)
|
if (!this || !this->IsClient() || !this->current_hp || !this->max_hp)
|
||||||
return;
|
return;
|
||||||
@@ -8670,6 +8758,11 @@ void Client::CheckRegionTypeChanges()
|
|||||||
if (last_region_type == new_region)
|
if (last_region_type == new_region)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// If we got out of water clear any water aggro for water only npcs
|
||||||
|
if (last_region_type == RegionTypeWater) {
|
||||||
|
entity_list.ClearWaterAggro(this);
|
||||||
|
}
|
||||||
|
|
||||||
// region type changed
|
// region type changed
|
||||||
last_region_type = new_region;
|
last_region_type = new_region;
|
||||||
|
|
||||||
@@ -9200,3 +9293,41 @@ void Client::SetBotOption(BotOwnerOption boo, bool flag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void Client::SendToGuildHall()
|
||||||
|
{
|
||||||
|
std::string zone_short_name = "guildhall";
|
||||||
|
uint32 zone_id = database.GetZoneID(zone_short_name.c_str());
|
||||||
|
if (zone_id == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 expiration_time = (RuleI(Instances, GuildHallExpirationDays) * 86400);
|
||||||
|
uint16 instance_id = 0;
|
||||||
|
std::string guild_hall_instance_key = fmt::format("guild-hall-instance-{}", GuildID());
|
||||||
|
std::string instance_data = DataBucket::GetData(guild_hall_instance_key);
|
||||||
|
if (!instance_data.empty() && std::stoi(instance_data) > 0) {
|
||||||
|
instance_id = std::stoi(instance_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance_id <= 0) {
|
||||||
|
if (!database.GetUnusedInstanceID(instance_id)) {
|
||||||
|
Message(Chat::Red, "Server was unable to find a free instance id.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!database.CreateInstance(instance_id, zone_id, 1, expiration_time)) {
|
||||||
|
Message(Chat::Red, "Server was unable to create a new instance.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBucket::SetData(
|
||||||
|
guild_hall_instance_key,
|
||||||
|
std::to_string(instance_id),
|
||||||
|
std::to_string(expiration_time)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignToInstance(instance_id);
|
||||||
|
MovePC(345, instance_id, -1.00, -1.00, 3.34, 0, 1);
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user