mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-28 09:45:45 +00:00
Compare commits
295 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 | |||
| daa9c04e89 | |||
| a9ef2474d4 | |||
| e1408ede6b | |||
| 4241fba7e2 | |||
| 139b6c34e5 | |||
| baf4cc62eb | |||
| 14402c9c41 | |||
| e4c4e5edb2 | |||
| e6a14beb2e | |||
| 945ca1278c | |||
| a307747c29 | |||
| 099da513ff | |||
| 607379110b | |||
| 7ce88b30ad | |||
| 28b0526857 | |||
| d5067c4c3a | |||
| 79db824a3c | |||
| 331032f4f4 | |||
| 61790ef195 | |||
| 9bdb70b2f0 | |||
| c438819ed6 | |||
| 7a791dda3c | |||
| 6366a3fa38 | |||
| 306a08b9ac | |||
| 467f8d7867 | |||
| 6c2100a650 | |||
| 9dacd0bd7a | |||
| 3c6cdd0905 | |||
| d1fb74ff5f | |||
| f81b9d8244 | |||
| b9e87abb3c | |||
| 451b0180c9 | |||
| 77ae4f0c3f | |||
| 852d951b65 | |||
| 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}"
|
||||
}
|
||||
}
|
||||
+19
-1
@@ -17,6 +17,8 @@
|
||||
*.out
|
||||
*.app
|
||||
|
||||
.bash_history
|
||||
|
||||
# CMake
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
@@ -35,4 +37,20 @@ perl/
|
||||
submodules/*
|
||||
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"]
|
||||
path = submodules/recastnavigation
|
||||
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
|
||||
compiler: gcc
|
||||
dist: trusty
|
||||
dist: bionic
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update -qq
|
||||
- mkdir $HOME/usr
|
||||
- export PATH="$HOME/usr/bin:$PATH"
|
||||
- wget https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.sh
|
||||
- chmod +x cmake-3.11.2-Linux-x86_64.sh
|
||||
- ./cmake-3.11.2-Linux-x86_64.sh --prefix=$HOME/usr --exclude-subdir --skip-license
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libmysqlclient-dev
|
||||
- libperl-dev
|
||||
- libboost-dev
|
||||
- liblua5.1-0-dev
|
||||
- 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:
|
||||
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
|
||||
- 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 "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
|
||||
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/libuv/include" )
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 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**|||
|
||||
### > 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
|
||||
* 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
|
||||
- [EQEmulator Forums](http://www.eqemulator.org/forums)
|
||||
- [EQEmulator Wiki](https://github.com/EQEmu/Server/wiki)
|
||||
- [EQEmulator Wiki](https://eqemu.gitbook.io/)
|
||||
|
||||
## Related Repositories
|
||||
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
|
||||
|
||||
@@ -9,6 +9,7 @@ SET(common_sources
|
||||
crash.cpp
|
||||
crc16.cpp
|
||||
crc32.cpp
|
||||
database/database_dump_service.cpp
|
||||
database.cpp
|
||||
database_conversions.cpp
|
||||
database_instances.cpp
|
||||
@@ -31,6 +32,7 @@ SET(common_sources
|
||||
event_sub.cpp
|
||||
extprofile.cpp
|
||||
faction.cpp
|
||||
file_util.cpp
|
||||
guild_base.cpp
|
||||
guilds.cpp
|
||||
inventory_profile.cpp
|
||||
@@ -120,6 +122,7 @@ SET(common_headers
|
||||
cli/argh.h
|
||||
cli/eqemu_command_handler.h
|
||||
cli/terminal_color.hpp
|
||||
database/database_dump_service.h
|
||||
data_verification.h
|
||||
database.h
|
||||
database_schema.h
|
||||
@@ -148,8 +151,10 @@ SET(common_headers
|
||||
eqtime.h
|
||||
errmsg.h
|
||||
event_sub.h
|
||||
expected.h
|
||||
extprofile.h
|
||||
faction.h
|
||||
file_util.h
|
||||
features.h
|
||||
fixed_memory_hash_set.h
|
||||
fixed_memory_variable_hash_set.h
|
||||
@@ -263,6 +268,13 @@ SET(common_headers
|
||||
patches/uf_limits.h
|
||||
patches/uf_ops.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
|
||||
util/memory_stream.h
|
||||
util/directory.h
|
||||
@@ -361,6 +373,16 @@ SOURCE_GROUP(Patches FILES
|
||||
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
|
||||
StackWalker/StackWalker.h
|
||||
StackWalker/StackWalker.cpp
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace EQEmuCommand {
|
||||
"\nCommand" <<
|
||||
termcolor::reset << "\n\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;
|
||||
|
||||
std::cout << command_string.str() << std::endl;
|
||||
|
||||
+135
-52
@@ -45,6 +45,7 @@
|
||||
#include "eq_packet_structs.h"
|
||||
#include "extprofile.h"
|
||||
#include "string_util.h"
|
||||
#include "database_schema.h"
|
||||
|
||||
extern Client client;
|
||||
|
||||
@@ -338,70 +339,81 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
||||
query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name);
|
||||
results = QueryDatabase(query);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
Delete the character with the name "name"
|
||||
returns false on failure, true otherwise
|
||||
*/
|
||||
bool Database::DeleteCharacter(char *name) {
|
||||
uint32 charid = 0;
|
||||
if(!name || !strlen(name)) {
|
||||
/**
|
||||
* @param character_name
|
||||
* @return
|
||||
*/
|
||||
bool Database::DeleteCharacter(char *character_name) {
|
||||
uint32 character_id = 0;
|
||||
if(!character_name || !strlen(character_name)) {
|
||||
LogInfo("DeleteCharacter: request to delete without a name (empty char slot)");
|
||||
return false;
|
||||
}
|
||||
LogInfo("Database::DeleteCharacter name : [{}]", name);
|
||||
|
||||
/* Get id from character_data before deleting record so we can clean up the rest of the tables */
|
||||
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name);
|
||||
auto results = QueryDatabase(query);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); }
|
||||
if (charid <= 0){
|
||||
LogError("Database::DeleteCharacter :: Character ({}) not found, stopping delete...", name);
|
||||
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", character_name);
|
||||
auto results = QueryDatabase(query);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
character_id = atoi(row[0]);
|
||||
}
|
||||
|
||||
if (character_id <= 0) {
|
||||
LogError("DeleteCharacter | Invalid Character ID [{}]", character_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_tasks` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
|
||||
std::string delete_type = "hard-deleted";
|
||||
if (RuleB(Character, SoftDeletes)) {
|
||||
delete_type = "soft-deleted";
|
||||
std::string query = fmt::format(
|
||||
SQL(
|
||||
UPDATE
|
||||
character_data
|
||||
SET
|
||||
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64),
|
||||
deleted_at = NOW()
|
||||
WHERE
|
||||
id = '{}'
|
||||
),
|
||||
character_id
|
||||
);
|
||||
|
||||
QueryDatabase(query);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
|
||||
|
||||
for (const auto& iter : DatabaseSchema::GetCharacterTables()) {
|
||||
std::string table_name = iter.first;
|
||||
std::string character_id_column_name = iter.second;
|
||||
|
||||
QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id));
|
||||
}
|
||||
|
||||
#ifdef BOTS
|
||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); // note: only use of GetMobTypeById()
|
||||
#else
|
||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid);
|
||||
#endif
|
||||
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
|
||||
QueryDatabase(query);
|
||||
#endif
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -913,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() {
|
||||
auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache.last_update));
|
||||
|
||||
@@ -2146,6 +2190,44 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
|
||||
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
|
||||
*/
|
||||
@@ -2323,3 +2405,4 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+9
-5
@@ -107,7 +107,7 @@ public:
|
||||
|
||||
bool AddToNameFilter(const char* name);
|
||||
bool CreateCharacter(uint32 account_id, char* name, uint16 gender, uint16 race, uint16 class_, uint8 str, uint8 sta, uint8 cha, uint8 dex, uint8 int_, uint8 agi, uint8 wis, uint8 face);
|
||||
bool DeleteCharacter(char* name);
|
||||
bool DeleteCharacter(char* character_name);
|
||||
bool MoveCharacterToZone(const char* charname, const char* zonename);
|
||||
bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid);
|
||||
bool MoveCharacterToZone(uint32 iCharID, const char* iZonename);
|
||||
@@ -133,9 +133,13 @@ public:
|
||||
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 GetGuildIDByCharID(uint32 char_id);
|
||||
uint32 GetGroupIDByCharID(uint32 char_id);
|
||||
uint32 GetRaidIDByCharID(uint32 char_id);
|
||||
|
||||
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
|
||||
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);
|
||||
|
||||
/* Instancing */
|
||||
@@ -192,19 +196,19 @@ public:
|
||||
|
||||
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
||||
void SetAgreementFlag(uint32 acctid);
|
||||
|
||||
|
||||
int GetIPExemption(std::string account_ip);
|
||||
|
||||
int GetInstanceID(uint32 char_id, uint32 zone_id);
|
||||
|
||||
|
||||
/* Groups */
|
||||
|
||||
|
||||
char* GetGroupLeaderForLogin(const char* name,char* leaderbuf);
|
||||
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
|
||||
|
||||
|
||||
uint32 GetGroupID(const char* name);
|
||||
|
||||
|
||||
void ClearGroup(uint32 gid = 0);
|
||||
void ClearGroupLeader(uint32 gid = 0);
|
||||
void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false);
|
||||
|
||||
@@ -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
|
||||
@@ -97,42 +97,53 @@ bool Database::CheckInstanceExists(uint16 instance_id) {
|
||||
bool Database::CheckInstanceExpired(uint16 instance_id)
|
||||
{
|
||||
|
||||
int32 start_time = 0;
|
||||
int32 duration = 0;
|
||||
int32 start_time = 0;
|
||||
int32 duration = 0;
|
||||
uint32 never_expires = 0;
|
||||
|
||||
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
|
||||
std::string query = StringFormat(
|
||||
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
|
||||
instance_id
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
if (!results.Success()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
if (results.RowCount() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
start_time = atoi(row[0]);
|
||||
duration = atoi(row[1]);
|
||||
start_time = atoi(row[0]);
|
||||
duration = atoi(row[1]);
|
||||
never_expires = atoi(row[2]);
|
||||
|
||||
if (never_expires == 1)
|
||||
if (never_expires == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
timeval tv;
|
||||
timeval tv{};
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
if ((start_time + duration) <= tv.tv_sec)
|
||||
return true;
|
||||
return (start_time + duration) <= tv.tv_sec;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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)"
|
||||
" values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)",
|
||||
(unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration);
|
||||
std::string query = StringFormat(
|
||||
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
|
||||
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
|
||||
instance_id,
|
||||
zone_id,
|
||||
version,
|
||||
duration
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
@@ -140,66 +151,84 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
|
||||
|
||||
bool Database::GetUnusedInstanceID(uint16 &instance_id)
|
||||
{
|
||||
uint32 count = RuleI(Zone, ReservedInstances);
|
||||
uint32 max = 65535;
|
||||
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
|
||||
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);
|
||||
|
||||
if (!results.Success())
|
||||
{
|
||||
if (!results.Success()) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
{
|
||||
instance_id = 0;
|
||||
return false;
|
||||
if (results.RowCount() == 0) {
|
||||
instance_id = max_reserved_instance_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
if (atoi(row[0]) <= max)
|
||||
{
|
||||
if (atoi(row[0]) <= max) {
|
||||
instance_id = atoi(row[0]);
|
||||
|
||||
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);
|
||||
|
||||
if (!results.Success())
|
||||
{
|
||||
if (!results.Success()) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
{
|
||||
if (results.RowCount() == 0) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
count++;
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
if (count < atoi(row[0]))
|
||||
{
|
||||
instance_id = count;
|
||||
max_reserved_instance_id++;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (max_reserved_instance_id < atoi(row[0])) {
|
||||
instance_id = max_reserved_instance_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (count > max)
|
||||
{
|
||||
if (max_reserved_instance_id > max) {
|
||||
instance_id = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
count++;
|
||||
max_reserved_instance_id++;
|
||||
}
|
||||
|
||||
instance_id = count;
|
||||
instance_id = max_reserved_instance_id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -548,17 +577,36 @@ void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &ch
|
||||
|
||||
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);
|
||||
|
||||
if (!results.Success())
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
if (results.RowCount() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
DeleteInstance(atoi(row[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||
@@ -566,4 +614,4 @@ void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||
std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), "
|
||||
"duration=%u WHERE id=%u", new_duration, instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
+107
-34
@@ -22,18 +22,77 @@
|
||||
#define EQEMU_DATABASE_SCHEMA_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
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
|
||||
*/
|
||||
static std::vector<std::string> GetPlayerTables()
|
||||
{
|
||||
std::vector<std::string> tables = {
|
||||
"aa_timers",
|
||||
return {
|
||||
"account",
|
||||
"account_ip",
|
||||
"account_flags",
|
||||
@@ -71,6 +130,7 @@ namespace DatabaseSchema {
|
||||
"character_tribute",
|
||||
"completed_tasks",
|
||||
"data_buckets",
|
||||
"discovered_items",
|
||||
"faction_values",
|
||||
"friends",
|
||||
"guild_bank",
|
||||
@@ -83,17 +143,18 @@ namespace DatabaseSchema {
|
||||
"inventory_snapshots",
|
||||
"keyring",
|
||||
"mail",
|
||||
"petitions",
|
||||
"player_titlesets",
|
||||
"quest_globals",
|
||||
"sharedbank",
|
||||
"spell_buckets",
|
||||
"spell_globals",
|
||||
"timers",
|
||||
"titles",
|
||||
"trader",
|
||||
"trader_audit",
|
||||
"zone_flags"
|
||||
};
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +164,7 @@ namespace DatabaseSchema {
|
||||
*/
|
||||
static std::vector<std::string> GetContentTables()
|
||||
{
|
||||
std::vector<std::string> tables = {
|
||||
return {
|
||||
"aa_ability",
|
||||
"aa_actions",
|
||||
"aa_effects",
|
||||
@@ -177,7 +238,6 @@ namespace DatabaseSchema {
|
||||
"task_activities",
|
||||
"tasks",
|
||||
"tasksets",
|
||||
"titles",
|
||||
"tradeskill_recipe",
|
||||
"tradeskill_recipe_entries",
|
||||
"traps",
|
||||
@@ -189,8 +249,6 @@ namespace DatabaseSchema {
|
||||
"zone_server",
|
||||
"zoneserver_auth",
|
||||
};
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,34 +258,48 @@ namespace DatabaseSchema {
|
||||
*/
|
||||
static std::vector<std::string> GetServerTables()
|
||||
{
|
||||
std::vector<std::string> tables = {
|
||||
"banned_ips",
|
||||
"bugs",
|
||||
"bug_reports",
|
||||
return {
|
||||
"chatchannels",
|
||||
"command_settings",
|
||||
"db_str",
|
||||
"discovered_items",
|
||||
"eqtime",
|
||||
"eventlog",
|
||||
"gm_ips",
|
||||
"hackers",
|
||||
"ip_exemptions",
|
||||
"launcher",
|
||||
"launcher_zones",
|
||||
"level_exp_mods",
|
||||
"logsys_categories",
|
||||
"name_filter",
|
||||
"perl_event_export_settings",
|
||||
"petitions",
|
||||
"profanity_list",
|
||||
"reports",
|
||||
"rule_sets",
|
||||
"rule_values",
|
||||
"saylink",
|
||||
"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",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,11 +310,17 @@ namespace DatabaseSchema {
|
||||
*/
|
||||
static std::vector<std::string> GetStateTables()
|
||||
{
|
||||
std::vector<std::string> tables = {
|
||||
return {
|
||||
"adventure_members",
|
||||
"chatchannels",
|
||||
"banned_ips",
|
||||
"bug_reports",
|
||||
"bugs",
|
||||
"eventlog",
|
||||
"gm_ips",
|
||||
"group_id",
|
||||
"group_leaders",
|
||||
"hackers",
|
||||
"ip_exemptions",
|
||||
"item_tick",
|
||||
"lfguild",
|
||||
"merchantlist_temp",
|
||||
@@ -250,12 +328,11 @@ namespace DatabaseSchema {
|
||||
"raid_details",
|
||||
"raid_leaders",
|
||||
"raid_members",
|
||||
"reports",
|
||||
"respawn_times",
|
||||
"spell_buckets",
|
||||
"spell_globals",
|
||||
};
|
||||
"saylink",
|
||||
|
||||
return tables;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,15 +342,13 @@ namespace DatabaseSchema {
|
||||
*/
|
||||
static std::vector<std::string> GetLoginTables()
|
||||
{
|
||||
std::vector<std::string> tables = {
|
||||
return {
|
||||
"login_accounts",
|
||||
"login_api_tokens",
|
||||
"login_server_admins",
|
||||
"login_server_list_types",
|
||||
"login_world_servers",
|
||||
};
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,12 +358,10 @@ namespace DatabaseSchema {
|
||||
*/
|
||||
static std::vector<std::string> GetVersionTables()
|
||||
{
|
||||
std::vector<std::string> tables = {
|
||||
return {
|
||||
"db_version",
|
||||
"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];
|
||||
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 (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)
|
||||
Log(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||
}
|
||||
|
||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer);
|
||||
|
||||
}
|
||||
|
||||
// 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 ((strncasecmp(query, "select", 6) == 0)) {
|
||||
LogF(
|
||||
Logs::General,
|
||||
Logs::MySQLQuery,
|
||||
LogMySQLQuery(
|
||||
"{0} ({1} row{2} returned) ({3}s)",
|
||||
query,
|
||||
requestResult.RowCount(),
|
||||
@@ -154,9 +152,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
);
|
||||
}
|
||||
else {
|
||||
LogF(
|
||||
Logs::General,
|
||||
Logs::MySQLQuery,
|
||||
LogMySQLQuery(
|
||||
"{0} ({1} row{2} affected) ({3}s)",
|
||||
query,
|
||||
requestResult.RowsAffected(),
|
||||
|
||||
@@ -317,6 +317,15 @@ namespace EQEmu
|
||||
QuestControlGrid = -1
|
||||
};
|
||||
|
||||
namespace consent {
|
||||
enum eConsentType : uint8 {
|
||||
Normal = 0,
|
||||
Group,
|
||||
Raid,
|
||||
Guild
|
||||
};
|
||||
}; // namespace consent
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
#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_STANCES = 10;
|
||||
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
|
||||
/*028*/ uint32 gold; // Gives gold to the client
|
||||
/*032*/ uint32 platinum; // Gives platinum to the client
|
||||
/*036*/ uint32 item_id;
|
||||
/*040*/ uint32 unknown040;
|
||||
/*044*/ uint32 unknown044;
|
||||
/*048*/ uint32 unknown048;
|
||||
/*052*/ uint32 unknown052;
|
||||
/*056*/ uint32 unknown056;
|
||||
/*060*/ uint32 unknown060;
|
||||
/*064*/ uint32 unknown064;
|
||||
/*036*/ int32 item_id[QUESTREWARD_COUNT]; // -1 for nothing
|
||||
/*068*/
|
||||
};
|
||||
|
||||
@@ -2972,6 +2967,12 @@ struct ItemViewRequest_Struct {
|
||||
/*046*/ char unknown046[2];
|
||||
};
|
||||
|
||||
struct ItemAdvancedLoreText_Struct {
|
||||
int32 item_id;
|
||||
char item_name[64];
|
||||
char advanced_lore[ADVANCED_LORE_LENGTH];
|
||||
};
|
||||
|
||||
struct LDONItemViewRequest_Struct {
|
||||
uint32 item_id;
|
||||
uint8 unknown004[4];
|
||||
|
||||
@@ -165,7 +165,7 @@ class EQEmuConfig
|
||||
fconfig >> _config->_root;
|
||||
_config->parse_config();
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -124,6 +124,8 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
|
||||
|
||||
/**
|
||||
* RFC 5424
|
||||
|
||||
@@ -113,6 +113,8 @@ namespace Logs {
|
||||
AoeCast,
|
||||
EntityManagement,
|
||||
Flee,
|
||||
Aura,
|
||||
HotReload,
|
||||
MaxCategoryID /* Don't Remove this */
|
||||
};
|
||||
|
||||
@@ -185,6 +187,8 @@ namespace Logs {
|
||||
"AOE Cast",
|
||||
"Entity Management",
|
||||
"Flee",
|
||||
"Aura",
|
||||
"HotReload",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -551,6 +551,26 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} 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 {\
|
||||
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
||||
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
@@ -842,6 +862,54 @@
|
||||
#define LogStatusDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIScanClose(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIScanCloseDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIYellForHelp(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAIYellForHelpDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAICastBeneficialClose(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAICastBeneficialCloseDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAoeCast(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAoeCastDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogEntityManagement(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogEntityManagementDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFlee(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogFleeDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAura(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogAuraDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHotReload(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHotReloadDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define Log(debug_level, log_category, message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@ namespace EQ
|
||||
uv_run(&m_loop, UV_RUN_DEFAULT);
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
uv_stop(&m_loop);
|
||||
}
|
||||
|
||||
uv_loop_t* Handle() { return &m_loop; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* 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 <tl/expected.hpp>
|
||||
|
||||
namespace eq
|
||||
{
|
||||
using tl::expected;
|
||||
using tl::make_unexpected;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
//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);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
@@ -941,7 +941,7 @@ bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) {
|
||||
m_db->DoEscapeString(esc, char_name, nl);
|
||||
|
||||
//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);
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
@@ -969,9 +969,9 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
|
||||
//load up the rank info for each guild.
|
||||
std::string query;
|
||||
#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
|
||||
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
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
|
||||
@@ -32,7 +32,7 @@ EQ::JsonConfigFile EQ::JsonConfigFile::Load(
|
||||
try {
|
||||
ifs >> ret.m_root;
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ std::string EQ::JsonConfigFile::GetVariableString(
|
||||
return m_root[title][parameter].asString();
|
||||
}
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ int EQ::JsonConfigFile::GetVariableInt(
|
||||
return m_root[title][parameter].asInt();
|
||||
}
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ bool EQ::JsonConfigFile::GetVariableBool(
|
||||
return m_root[title][parameter].asBool();
|
||||
}
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ double EQ::JsonConfigFile::GetVariableDouble(
|
||||
return m_root[title][parameter].asDouble();
|
||||
}
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,12 +278,6 @@ void LinkedListIterator<TYPE>::Replace(const TYPE& new_data)
|
||||
template<class TYPE>
|
||||
void LinkedListIterator<TYPE>::Reset()
|
||||
{
|
||||
if (!(&list))
|
||||
{
|
||||
current_element=0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dir == FORWARD)
|
||||
{
|
||||
current_element = list.first;
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
#include "types.h"
|
||||
#include <cstring>
|
||||
|
||||
#define ENC(c) (((c) & 0x3f) + ' ')
|
||||
#define DEC(c) (((c) - ' ') & 0x3f)
|
||||
|
||||
std::map<int,std::string> DBFieldNames;
|
||||
|
||||
#ifndef WIN32
|
||||
@@ -333,64 +330,6 @@ void LoadItemDBFieldNames() {
|
||||
DBFieldNames[113]="unknown115"; // ? (end quote)
|
||||
}
|
||||
|
||||
void encode_length(unsigned long length, char *out)
|
||||
{
|
||||
char buf[4];
|
||||
memcpy(buf,&length,sizeof(unsigned long));
|
||||
encode_chunk(buf,3,out);
|
||||
}
|
||||
|
||||
unsigned long encode(char *in, unsigned long length, char *out)
|
||||
{
|
||||
unsigned long used=0,len=0;
|
||||
while(used<length) {
|
||||
encode_chunk(in+used,length-used,out+len);
|
||||
used+=3;
|
||||
len+=4;
|
||||
}
|
||||
*(out+len)=0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned long decode_length(char *in)
|
||||
{
|
||||
int length;
|
||||
char buf[4];
|
||||
decode_chunk(in,&buf[0]);
|
||||
buf[3]=0;
|
||||
memcpy(&length,buf,sizeof(unsigned long));
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void decode(char *in, char *out)
|
||||
{
|
||||
char *ptr=in;
|
||||
char *outptr=out;
|
||||
while(*ptr) {
|
||||
decode_chunk(ptr,outptr);
|
||||
ptr+=4;
|
||||
outptr+=3;
|
||||
}
|
||||
*outptr=0;
|
||||
}
|
||||
|
||||
void encode_chunk(char *in, int len, char *out)
|
||||
{
|
||||
*out=ENC(in[0] >> 2);
|
||||
*(out+1)=ENC((in[0] << 4)|(((len<2 ? 0 : in[1]) >> 4) & 0xF));
|
||||
*(out+2)=ENC(((len<2 ? 0 : in[1]) << 2)|(((len<3 ? 0 : in[2]) >> 6) & 0x3));
|
||||
*(out+3)=ENC((len<3 ? 0 : in[2]));
|
||||
}
|
||||
|
||||
void decode_chunk(char *in, char *out)
|
||||
{
|
||||
*out = DEC(*in) << 2 | DEC(in[1]) >> 4;
|
||||
*(out+1) = DEC(in[1]) << 4 | DEC(in[2]) >> 2;
|
||||
*(out+2) = DEC(in[2]) << 6 | DEC(in[3]);
|
||||
}
|
||||
|
||||
void dump_message_column(unsigned char *buffer, unsigned long length, std::string leader, FILE *to)
|
||||
{
|
||||
unsigned long i,j;
|
||||
|
||||
@@ -17,13 +17,6 @@ int Tokenize(std::string s, std::map<int,std::string> & tokens, char delim='|');
|
||||
|
||||
void LoadItemDBFieldNames();
|
||||
|
||||
void encode_length(unsigned long length, char *out);
|
||||
unsigned long decode_length(char *in);
|
||||
unsigned long encode(char *in, unsigned long length, char *out);
|
||||
void decode(char *in, char *out);
|
||||
void encode_chunk(char *in, int len, char *out);
|
||||
void decode_chunk(char *in, char *out);
|
||||
|
||||
#ifndef WIN32
|
||||
int print_stacktrace();
|
||||
#endif
|
||||
|
||||
@@ -116,17 +116,21 @@ bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMes
|
||||
}
|
||||
|
||||
switch (scm->chan_num) {
|
||||
if (RuleB(Chat, ServerWideAuction)) {
|
||||
case 4: {
|
||||
case 4: {
|
||||
if (RuleB(Chat, ServerWideAuction)) {
|
||||
QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
|
||||
break;
|
||||
} else { // I think we want default action in this case?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (RuleB(Chat, ServerWideOOC)) {
|
||||
case 5: {
|
||||
case 5: {
|
||||
if (RuleB(Chat, ServerWideOOC)) {
|
||||
QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
|
||||
break;
|
||||
} else { // I think we want default action in this case?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -399,7 +399,7 @@ void EQ::Net::DaybreakConnection::Process()
|
||||
|
||||
ProcessQueue();
|
||||
}
|
||||
catch (std::exception ex) {
|
||||
catch (std::exception &ex) {
|
||||
if (m_owner->m_on_error_message) {
|
||||
m_owner->m_on_error_message(fmt::format("Error processing connection: {0}", ex.what()));
|
||||
}
|
||||
@@ -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 *buffer = (uint8_t*)p.Data() + offset;
|
||||
uint32_t new_length = 0;
|
||||
bool send_uncompressed = true;
|
||||
|
||||
if (length > 30) {
|
||||
new_length = Deflate(buffer, (uint32_t)length, new_buffer + 1, 2048) + 1;
|
||||
new_buffer[0] = 0x5a;
|
||||
send_uncompressed = (new_length > length);
|
||||
}
|
||||
else {
|
||||
if (send_uncompressed) {
|
||||
memcpy(new_buffer + 1, buffer, length);
|
||||
new_buffer[0] = 0xa5;
|
||||
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 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();
|
||||
if (length > max_raw_size) {
|
||||
DaybreakReliableFragmentHeader first_header;
|
||||
|
||||
+4
-4
@@ -89,9 +89,9 @@ namespace EQ {
|
||||
public:
|
||||
StaticPacket(void *data, size_t size) { m_data = data; m_data_length = size; m_max_data_length = size; }
|
||||
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(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 void *Data() { return m_data; }
|
||||
@@ -112,7 +112,7 @@ namespace EQ {
|
||||
public:
|
||||
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& operator=(const DynamicPacket &o) { m_data = o.m_data; return *this; }
|
||||
|
||||
@@ -127,4 +127,4 @@ namespace EQ {
|
||||
std::vector<char> m_data;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ EQ::Net::WebsocketServer::WebsocketServer(const std::string &addr, int port)
|
||||
auto &connection = iter->second;
|
||||
connection->GetWebsocketConnection()->ping("keepalive");
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
iter->second->GetTCPConnection()->Disconnect();
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ void EQ::Net::WebsocketServer::DispatchEvent(WebsocketSubscriptionEvent evt, Jso
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connectio
|
||||
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
throw WebsocketException("Unable to process login request");
|
||||
}
|
||||
}
|
||||
@@ -212,7 +212,7 @@ Json::Value EQ::Net::WebsocketServer::Subscribe(WebsocketServerConnection *conne
|
||||
catch (WebsocketException &ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
throw WebsocketException("Unable to process unsubscribe request");
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,7 @@ Json::Value EQ::Net::WebsocketServer::Unsubscribe(WebsocketServerConnection *con
|
||||
catch (WebsocketException &ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
throw WebsocketException("Unable to process unsubscribe request");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <sstream>
|
||||
#include <numeric>
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
|
||||
|
||||
namespace RoF2
|
||||
@@ -3548,7 +3549,7 @@ namespace RoF2
|
||||
{
|
||||
eq->items[i].Unknown18 = 0;
|
||||
if (i < 80) {
|
||||
snprintf(eq->items[i].SerialNumber, sizeof(eq->items[i].SerialNumber), "%016d", emu->SerialNumber[i]);
|
||||
snprintf(eq->items[i].SerialNumber, sizeof(eq->items[i].SerialNumber), "%016" PRId64, emu->SerialNumber[i]);
|
||||
eq->ItemCost[i] = emu->ItemCost[i];
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -4401,7 +4401,7 @@ struct SendAA_Struct {
|
||||
/*0104*/ uint32 special_category;
|
||||
/*0108*/ uint8 shroud;
|
||||
/*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;
|
||||
/*0112*/ uint32 total_abilities;
|
||||
/*0116*/ AA_Ability abilities[0];
|
||||
|
||||
@@ -4341,7 +4341,7 @@ struct SendAA_Struct {
|
||||
/*0104*/ uint32 special_category;
|
||||
/*0108*/ uint8 shroud;
|
||||
/*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;
|
||||
/*0112*/ uint32 total_abilities;
|
||||
/*0116*/ AA_Ability abilities[0];
|
||||
|
||||
@@ -3780,7 +3780,7 @@ struct SendAA_Struct {
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*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;
|
||||
/*0100*/ uint32 total_abilities;
|
||||
/*0104*/ AA_Ability abilities[0];
|
||||
|
||||
@@ -3704,7 +3704,7 @@ struct SendAA_Struct {
|
||||
/*0088*/ uint32 aa_expansion;
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*0097*/ uint8 unknown97;
|
||||
/*0097*/ uint8 reset_on_death; // timer is reset on death -- guess
|
||||
/*0098*/ uint32 total_abilities;
|
||||
/*0102*/ AA_Ability abilities[0];
|
||||
};
|
||||
|
||||
@@ -3835,7 +3835,7 @@ struct SendAA_Struct {
|
||||
/*0092*/ uint32 special_category;
|
||||
/*0096*/ uint8 shroud;
|
||||
/*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;
|
||||
/*0100*/ uint32 total_abilities;
|
||||
/*0104*/ AA_Ability abilities[0];
|
||||
|
||||
@@ -190,10 +190,6 @@ bool PersistentTimer::Clear(Database *db) {
|
||||
|
||||
/* This function checks if the timer triggered */
|
||||
bool PersistentTimer::Expired(Database *db, bool iReset) {
|
||||
if (this == nullptr) {
|
||||
LogError("Null timer during ->Check()!?\n");
|
||||
return(true);
|
||||
}
|
||||
uint32 current_time = get_current_time();
|
||||
if (current_time-start_time >= timer_time) {
|
||||
if (enabled && iReset) {
|
||||
|
||||
+21
-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_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, 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_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")
|
||||
@@ -158,6 +159,9 @@ RULE_BOOL(Character, AllowCrossClassTrainers, false, "")
|
||||
RULE_BOOL(Character, PetsUseReagents, true, "Pets use reagent on spells")
|
||||
RULE_BOOL(Character, DismountWater, true, "Dismount horses when entering water")
|
||||
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_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(Mercs)
|
||||
@@ -194,6 +198,7 @@ RULE_INT(Skills, SwimmingStartValue, 100, "")
|
||||
RULE_BOOL(Skills, TrainSenseHeading, false, "")
|
||||
RULE_INT(Skills, SenseHeadingStartValue, 200, "")
|
||||
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(Pets)
|
||||
@@ -265,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_BOOL(Zone, UsePEQZoneDebuffs, true, "Will determine if #peqzone will debuff players or not when used")
|
||||
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, RadiantCrystalItemID, 40903, "")
|
||||
RULE_BOOL(Zone, LevelBasedEXPMods, false, "Allows you to use the level_exp_mods table in consideration to your players EXP hits")
|
||||
@@ -293,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_REAL(Pathing, NavmeshStepSize, 100.0f, "")
|
||||
RULE_REAL(Pathing, ShortMovementUpdateRange, 130.0f, "")
|
||||
RULE_INT(Pathing, MaxNavmeshNodes, 4092, "Max navmesh nodes in a traversable path")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Watermap)
|
||||
@@ -491,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, 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, 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, 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")
|
||||
@@ -518,10 +524,11 @@ RULE_INT(NPC, NPCToNPCAggroTimerMin, 500, "")
|
||||
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000, "")
|
||||
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_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_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, 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_CATEGORY_END()
|
||||
|
||||
@@ -761,6 +768,18 @@ RULE_CATEGORY(Logging)
|
||||
RULE_BOOL(Logging, PrintFileFunctionAndLine, false, "Ex: [World Server] [net.cpp::main:309] Loading variables...")
|
||||
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_INT
|
||||
#undef RULE_REAL
|
||||
|
||||
+14
-7
@@ -197,7 +197,11 @@
|
||||
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
||||
#define ServerOP_UCSServerStatusRequest 0x4013
|
||||
#define ServerOP_UCSServerStatusReply 0x4014
|
||||
/* Query Server OP Codes */
|
||||
#define ServerOP_HotReloadQuests 0x4015
|
||||
|
||||
/**
|
||||
* QueryServer
|
||||
*/
|
||||
#define ServerOP_QSPlayerLogTrades 0x5010
|
||||
#define ServerOP_QSPlayerLogHandins 0x5011
|
||||
#define ServerOP_QSPlayerLogNPCKills 0x5012
|
||||
@@ -262,9 +266,6 @@ public:
|
||||
}
|
||||
|
||||
ServerPacket* Copy() {
|
||||
if (this == 0) {
|
||||
return 0;
|
||||
}
|
||||
ServerPacket* ret = new ServerPacket(this->opcode, this->size);
|
||||
if (this->size)
|
||||
memcpy(ret->pBuffer, this->pBuffer, this->size);
|
||||
@@ -869,10 +870,12 @@ struct SpawnPlayerCorpse_Struct {
|
||||
struct ServerOP_Consent_Struct {
|
||||
char grantname[64];
|
||||
char ownername[64];
|
||||
char zonename[32];
|
||||
uint8 permission;
|
||||
uint32 zone_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 {
|
||||
@@ -1352,12 +1355,16 @@ struct CZSetEntVarByClientName_Struct {
|
||||
char m_var[256];
|
||||
};
|
||||
|
||||
struct ReloadWorld_Struct{
|
||||
struct ReloadWorld_Struct {
|
||||
uint32 Option;
|
||||
};
|
||||
|
||||
struct HotReloadQuestsStruct {
|
||||
char zone_short_name[200];
|
||||
};
|
||||
|
||||
struct ServerRequestTellQueue_Struct {
|
||||
char name[64];
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct UCSServerStatus_Struct {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* 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
|
||||
|
||||
namespace eq
|
||||
{
|
||||
namespace shared
|
||||
{
|
||||
enum class shared_memory_error
|
||||
{
|
||||
no_error,
|
||||
error_mapping_memory,
|
||||
error_alloc
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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>());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+139
-141
@@ -1656,21 +1656,19 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill
|
||||
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 "
|
||||
"AND `spellid` <= %i", iMaxSpellID);
|
||||
std::string query = StringFormat("SELECT `type` FROM `damageshieldtypes` WHERE `spellid` = %i", spell_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
int spellID = atoi(row[0]);
|
||||
if((spellID > 0) && (spellID <= iMaxSpellID))
|
||||
sp[spellID].DamageShieldType = atoi(row[1]);
|
||||
for(auto &row : results) {
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) {
|
||||
@@ -1689,6 +1687,18 @@ int SharedDatabase::GetMaxSpellID() {
|
||||
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) {
|
||||
spells_mmf.reset(nullptr);
|
||||
|
||||
@@ -1710,175 +1720,163 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
*(uint32*)data = max_spells;
|
||||
SPDat_Spell_Struct *sp = reinterpret_cast<SPDat_Spell_Struct*>((char*)data + sizeof(uint32));
|
||||
|
||||
void SharedDatabase::LoadSpells(std::function<void(const SPDat_Spell_Struct & sp)> on_load) {
|
||||
const std::string query = "SELECT * FROM spells_new ORDER BY id ASC";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(results.ColumnCount() <= SPELL_LOAD_FIELD_COUNT) {
|
||||
LogSpells("Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT([{}])", SPELL_LOAD_FIELD_COUNT);
|
||||
return;
|
||||
}
|
||||
|
||||
int tempid = 0;
|
||||
int counter = 0;
|
||||
for (auto &row : results) {
|
||||
SPDat_Spell_Struct sp;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
tempid = atoi(row[0]);
|
||||
if(tempid >= max_spells) {
|
||||
LogSpells("Non fatal error: spell.id >= max_spells, ignoring");
|
||||
continue;
|
||||
}
|
||||
sp.id = atoi(row[0]);
|
||||
strn0cpy(sp.name, row[1], sizeof(sp.name));
|
||||
strn0cpy(sp.player_1, row[2], sizeof(sp.player_1));
|
||||
strn0cpy(sp.teleport_zone, row[3], sizeof(sp.teleport_zone));
|
||||
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[tempid].id = tempid;
|
||||
strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name));
|
||||
strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1));
|
||||
strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone));
|
||||
strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast));
|
||||
strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts));
|
||||
strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you));
|
||||
strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other));
|
||||
strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades));
|
||||
sp.range = static_cast<float>(atof(row[9]));
|
||||
sp.aoerange = static_cast<float>(atof(row[10]));
|
||||
sp.pushback = static_cast<float>(atof(row[11]));
|
||||
sp.pushup = static_cast<float>(atof(row[12]));
|
||||
sp.cast_time = atoi(row[13]);
|
||||
sp.recovery_time = atoi(row[14]);
|
||||
sp.recast_time = atoi(row[15]);
|
||||
sp.buffdurationformula = atoi(row[16]);
|
||||
sp.buffduration = atoi(row[17]);
|
||||
sp.AEDuration = atoi(row[18]);
|
||||
sp.mana = atoi(row[19]);
|
||||
|
||||
sp[tempid].range=static_cast<float>(atof(row[9]));
|
||||
sp[tempid].aoerange=static_cast<float>(atof(row[10]));
|
||||
sp[tempid].pushback=static_cast<float>(atof(row[11]));
|
||||
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++)
|
||||
sp.base[y] = atoi(row[20 + y]); // effect_base_value
|
||||
|
||||
int y=0;
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].base[y]=atoi(row[20+y]); // effect_base_value
|
||||
for (y = 0; y < EFFECT_COUNT; y++)
|
||||
sp.base2[y] = atoi(row[32 + y]); // effect_limit_value
|
||||
|
||||
for(y=0; y < EFFECT_COUNT; y++)
|
||||
sp[tempid].base2[y]=atoi(row[32+y]); // effect_limit_value
|
||||
for (y = 0; y < EFFECT_COUNT; y++)
|
||||
sp.max[y] = atoi(row[44 + y]);
|
||||
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].max[y]=atoi(row[44+y]);
|
||||
for (y = 0; y < 4; y++)
|
||||
sp.components[y] = atoi(row[58 + y]);
|
||||
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].components[y]=atoi(row[58+y]);
|
||||
for (y = 0; y < 4; y++)
|
||||
sp.component_counts[y] = atoi(row[62 + y]);
|
||||
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].component_counts[y]=atoi(row[62+y]);
|
||||
for (y = 0; y < 4; y++)
|
||||
sp.NoexpendReagent[y] = atoi(row[66 + y]);
|
||||
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].NoexpendReagent[y]=atoi(row[66+y]);
|
||||
for (y = 0; y < EFFECT_COUNT; y++)
|
||||
sp.formula[y] = atoi(row[70 + y]);
|
||||
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].formula[y]=atoi(row[70+y]);
|
||||
sp.goodEffect = atoi(row[83]);
|
||||
sp.Activated = atoi(row[84]);
|
||||
sp.resisttype = atoi(row[85]);
|
||||
|
||||
sp[tempid].goodEffect=atoi(row[83]);
|
||||
sp[tempid].Activated=atoi(row[84]);
|
||||
sp[tempid].resisttype=atoi(row[85]);
|
||||
for (y = 0; y < EFFECT_COUNT; y++)
|
||||
sp.effectid[y] = atoi(row[86 + y]);
|
||||
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].effectid[y]=atoi(row[86+y]);
|
||||
|
||||
sp[tempid].targettype = (SpellTargetType) atoi(row[98]);
|
||||
sp[tempid].basediff=atoi(row[99]);
|
||||
sp.targettype = (SpellTargetType)atoi(row[98]);
|
||||
sp.basediff = atoi(row[99]);
|
||||
|
||||
int tmp_skill = atoi(row[100]);;
|
||||
|
||||
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
|
||||
else
|
||||
sp[tempid].skill = (EQEmu::skills::SkillType) tmp_skill;
|
||||
sp.skill = EQEmu::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated
|
||||
else
|
||||
sp.skill = (EQEmu::skills::SkillType) tmp_skill;
|
||||
|
||||
sp[tempid].zonetype=atoi(row[101]);
|
||||
sp[tempid].EnvironmentType=atoi(row[102]);
|
||||
sp[tempid].TimeOfDay=atoi(row[103]);
|
||||
sp.zonetype = atoi(row[101]);
|
||||
sp.EnvironmentType = atoi(row[102]);
|
||||
sp.TimeOfDay = atoi(row[103]);
|
||||
|
||||
for(y=0; y < PLAYER_CLASS_COUNT;y++)
|
||||
sp[tempid].classes[y]=atoi(row[104+y]);
|
||||
for (y = 0; y < PLAYER_CLASS_COUNT; y++)
|
||||
sp.classes[y] = atoi(row[104 + y]);
|
||||
|
||||
sp[tempid].CastingAnim=atoi(row[120]);
|
||||
sp[tempid].SpellAffectIndex=atoi(row[123]);
|
||||
sp[tempid].disallow_sit=atoi(row[124]);
|
||||
sp[tempid].diety_agnostic=atoi(row[125]);
|
||||
sp.CastingAnim = atoi(row[120]);
|
||||
sp.SpellAffectIndex = atoi(row[123]);
|
||||
sp.disallow_sit = atoi(row[124]);
|
||||
sp.diety_agnostic = atoi(row[125]);
|
||||
|
||||
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[tempid].uninterruptable=atoi(row[146]) != 0;
|
||||
sp[tempid].ResistDiff=atoi(row[147]);
|
||||
sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0;
|
||||
sp[tempid].RecourseLink = atoi(row[150]);
|
||||
sp[tempid].no_partial_resist = atoi(row[151]) != 0;
|
||||
sp.new_icon = atoi(row[144]);
|
||||
sp.uninterruptable = atoi(row[146]) != 0;
|
||||
sp.ResistDiff = atoi(row[147]);
|
||||
sp.dot_stacking_exempt = atoi(row[148]) != 0;
|
||||
sp.RecourseLink = atoi(row[150]);
|
||||
sp.no_partial_resist = atoi(row[151]) != 0;
|
||||
|
||||
sp[tempid].short_buff_box = atoi(row[154]);
|
||||
sp[tempid].descnum = atoi(row[155]);
|
||||
sp[tempid].typedescnum = atoi(row[156]);
|
||||
sp[tempid].effectdescnum = atoi(row[157]);
|
||||
sp.short_buff_box = atoi(row[154]);
|
||||
sp.descnum = atoi(row[155]);
|
||||
sp.typedescnum = atoi(row[156]);
|
||||
sp.effectdescnum = atoi(row[157]);
|
||||
|
||||
sp[tempid].npc_no_los = atoi(row[159]) != 0;
|
||||
sp[tempid].reflectable = atoi(row[161]) != 0;
|
||||
sp[tempid].bonushate=atoi(row[162]);
|
||||
sp.npc_no_los = atoi(row[159]) != 0;
|
||||
sp.reflectable = atoi(row[161]) != 0;
|
||||
sp.bonushate = atoi(row[162]);
|
||||
|
||||
sp[tempid].ldon_trap = atoi(row[165]) != 0;
|
||||
sp[tempid].EndurCost=atoi(row[166]);
|
||||
sp[tempid].EndurTimerIndex=atoi(row[167]);
|
||||
sp[tempid].IsDisciplineBuff = atoi(row[168]) != 0;
|
||||
sp[tempid].HateAdded=atoi(row[173]);
|
||||
sp[tempid].EndurUpkeep=atoi(row[174]);
|
||||
sp[tempid].numhitstype = atoi(row[175]);
|
||||
sp[tempid].numhits = atoi(row[176]);
|
||||
sp[tempid].pvpresistbase=atoi(row[177]);
|
||||
sp[tempid].pvpresistcalc=atoi(row[178]);
|
||||
sp[tempid].pvpresistcap=atoi(row[179]);
|
||||
sp[tempid].spell_category=atoi(row[180]);
|
||||
sp[tempid].pcnpc_only_flag=atoi(row[183]);
|
||||
sp[tempid].cast_not_standing = atoi(row[184]) != 0;
|
||||
sp[tempid].can_mgb=atoi(row[185]);
|
||||
sp[tempid].dispel_flag = atoi(row[186]);
|
||||
sp[tempid].MinResist = atoi(row[189]);
|
||||
sp[tempid].MaxResist = atoi(row[190]);
|
||||
sp[tempid].viral_targets = atoi(row[191]);
|
||||
sp[tempid].viral_timer = atoi(row[192]);
|
||||
sp[tempid].NimbusEffect = atoi(row[193]);
|
||||
sp[tempid].directional_start = static_cast<float>(atoi(row[194]));
|
||||
sp[tempid].directional_end = static_cast<float>(atoi(row[195]));
|
||||
sp[tempid].sneak = atoi(row[196]) != 0;
|
||||
sp[tempid].not_focusable = atoi(row[197]) != 0;
|
||||
sp[tempid].no_detrimental_spell_aggro = atoi(row[198]) != 0;
|
||||
sp[tempid].suspendable = atoi(row[200]) != 0;
|
||||
sp[tempid].viral_range = atoi(row[201]);
|
||||
sp[tempid].songcap = atoi(row[202]);
|
||||
sp[tempid].no_block = atoi(row[205]);
|
||||
sp[tempid].spellgroup=atoi(row[207]);
|
||||
sp[tempid].rank = atoi(row[208]);
|
||||
sp[tempid].no_resist=atoi(row[209]);
|
||||
sp[tempid].CastRestriction = atoi(row[211]);
|
||||
sp[tempid].AllowRest = atoi(row[212]) != 0;
|
||||
sp[tempid].InCombat = atoi(row[213]) != 0;
|
||||
sp[tempid].OutofCombat = atoi(row[214]) != 0;
|
||||
sp[tempid].override_crit_chance = atoi(row[217]);
|
||||
sp[tempid].aemaxtargets = atoi(row[218]);
|
||||
sp[tempid].no_heal_damage_item_mod = atoi(row[219]);
|
||||
sp[tempid].persistdeath = atoi(row[224]) != 0;
|
||||
sp[tempid].min_dist = atof(row[227]);
|
||||
sp[tempid].min_dist_mod = atof(row[228]);
|
||||
sp[tempid].max_dist = atof(row[229]);
|
||||
sp[tempid].max_dist_mod = atof(row[230]);
|
||||
sp[tempid].min_range = static_cast<float>(atoi(row[231]));
|
||||
sp[tempid].no_remove = atoi(row[232]) != 0;
|
||||
sp[tempid].DamageShieldType = 0;
|
||||
sp.ldon_trap = atoi(row[165]) != 0;
|
||||
sp.EndurCost = atoi(row[166]);
|
||||
sp.EndurTimerIndex = atoi(row[167]);
|
||||
sp.IsDisciplineBuff = atoi(row[168]) != 0;
|
||||
sp.HateAdded = atoi(row[173]);
|
||||
sp.EndurUpkeep = atoi(row[174]);
|
||||
sp.numhitstype = atoi(row[175]);
|
||||
sp.numhits = atoi(row[176]);
|
||||
sp.pvpresistbase = atoi(row[177]);
|
||||
sp.pvpresistcalc = atoi(row[178]);
|
||||
sp.pvpresistcap = atoi(row[179]);
|
||||
sp.spell_category = atoi(row[180]);
|
||||
sp.pcnpc_only_flag = atoi(row[183]);
|
||||
sp.cast_not_standing = atoi(row[184]) != 0;
|
||||
sp.can_mgb = atoi(row[185]);
|
||||
sp.dispel_flag = atoi(row[186]);
|
||||
sp.MinResist = atoi(row[189]);
|
||||
sp.MaxResist = atoi(row[190]);
|
||||
sp.viral_targets = atoi(row[191]);
|
||||
sp.viral_timer = atoi(row[192]);
|
||||
sp.NimbusEffect = atoi(row[193]);
|
||||
sp.directional_start = static_cast<float>(atoi(row[194]));
|
||||
sp.directional_end = static_cast<float>(atoi(row[195]));
|
||||
sp.sneak = atoi(row[196]) != 0;
|
||||
sp.not_focusable = atoi(row[197]) != 0;
|
||||
sp.no_detrimental_spell_aggro = atoi(row[198]) != 0;
|
||||
sp.suspendable = atoi(row[200]) != 0;
|
||||
sp.viral_range = atoi(row[201]);
|
||||
sp.songcap = atoi(row[202]);
|
||||
sp.no_block = atoi(row[205]);
|
||||
sp.spellgroup = atoi(row[207]);
|
||||
sp.rank = atoi(row[208]);
|
||||
sp.no_resist = atoi(row[209]);
|
||||
sp.CastRestriction = atoi(row[211]);
|
||||
sp.AllowRest = atoi(row[212]) != 0;
|
||||
sp.InCombat = atoi(row[213]) != 0;
|
||||
sp.OutofCombat = atoi(row[214]) != 0;
|
||||
sp.override_crit_chance = atoi(row[217]);
|
||||
sp.aemaxtargets = atoi(row[218]);
|
||||
sp.no_heal_damage_item_mod = atoi(row[219]);
|
||||
sp.persistdeath = atoi(row[224]) != 0;
|
||||
sp.min_dist = atof(row[227]);
|
||||
sp.min_dist_mod = atof(row[228]);
|
||||
sp.max_dist = atof(row[229]);
|
||||
sp.max_dist_mod = atof(row[230]);
|
||||
sp.min_range = static_cast<float>(atoi(row[231]));
|
||||
sp.no_remove = atoi(row[232]) != 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() {
|
||||
|
||||
+3
-2
@@ -140,9 +140,10 @@ class SharedDatabase : public Database
|
||||
uint8 GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level);
|
||||
|
||||
int GetMaxSpellID();
|
||||
int GetSpellCount();
|
||||
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
|
||||
void LoadSpells(void *data, int max_spells);
|
||||
void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID);
|
||||
void LoadSpells(std::function<void(const SPDat_Spell_Struct & sp)> on_load);
|
||||
int LoadDamageShieldType(int spell_id);
|
||||
|
||||
int GetMaxBaseDataLevel();
|
||||
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_CastOnCurer 386 // implemented - Casts a spell on the person curing
|
||||
#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_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
|
||||
#define SE_LimitManaMax 391 // implemented
|
||||
|
||||
@@ -222,7 +222,7 @@ bool StringIsNumber(const std::string &s) {
|
||||
auto r = stod(s);
|
||||
return true;
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -129,13 +129,17 @@ void Timer::SetTimer(uint32 set_timer_time) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Timer::GetRemainingTime() const {
|
||||
uint32 Timer::GetRemainingTime() const
|
||||
{
|
||||
if (enabled) {
|
||||
if (current_time - start_time > timer_time)
|
||||
if (current_time - start_time > timer_time) {
|
||||
return 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
return (start_time + timer_time) - current_time;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,10 +34,10 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9145
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9152
|
||||
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027
|
||||
#else
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||
#endif
|
||||
|
||||
+23
-16
@@ -19,28 +19,35 @@
|
||||
#include "spells.h"
|
||||
#include "../common/global_define.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/shared/shared_memory.h"
|
||||
#include "../common/shared/shared_memory_map.h"
|
||||
|
||||
namespace eqs = eq::shared;
|
||||
|
||||
void LoadSpells(SharedDatabase *database, const std::string &prefix) {
|
||||
EQEmu::IPCMutex mutex("spells");
|
||||
mutex.Lock();
|
||||
int records = database->GetMaxSpellID() + 1;
|
||||
if(records == 0) {
|
||||
EQ_EXCEPT("Shared Memory", "Unable to get any spells from the database.");
|
||||
int records = database->GetSpellCount();
|
||||
int max_spell_id = database->GetMaxSpellID() + 1;
|
||||
auto size = records * sizeof(SPDat_Spell_Struct) * 125 / 100 + (64 * 1024);
|
||||
eqs::shared_memory shared("shared/spells", size);
|
||||
|
||||
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();
|
||||
std::string file_name = Config->SharedMemDir + prefix + std::string("spells");
|
||||
EQEmu::MemoryMappedFile mmf(file_name, size);
|
||||
mmf.ZeroFile();
|
||||
eqs::unordered_map<int, SPDat_Spell_Struct>& spells_shm = spells_result.value();
|
||||
int& max_spell_id_shm = max_spell_id_result.value();
|
||||
max_spell_id_shm = max_spell_id;
|
||||
|
||||
void *ptr = mmf.Get();
|
||||
database->LoadSpells(ptr, records);
|
||||
mutex.Unlock();
|
||||
database->LoadSpells([&spells_shm](const SPDat_Spell_Struct &spell) {
|
||||
spells_shm.insert_or_assign(spell.id, spell);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
LogInfo("New ChatChannel created: Name: [[{}]], Owner: [[{}]], Password: [[{}]], MinStatus: [{}]",
|
||||
Name.c_str(), Owner.c_str(), Password.c_str(), MinimumStatus);
|
||||
LogDebug(
|
||||
"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) {
|
||||
|
||||
LogInfo("RemoveChannel([{}])", Channel->GetName().c_str());
|
||||
LogDebug("RemoveChannel ([{}])", Channel->GetName().c_str());
|
||||
|
||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||
|
||||
@@ -175,7 +180,7 @@ void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
|
||||
|
||||
void ChatChannelList::RemoveAllChannels() {
|
||||
|
||||
LogInfo("RemoveAllChannels");
|
||||
LogDebug("RemoveAllChannels");
|
||||
|
||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||
|
||||
@@ -242,7 +247,7 @@ void ChatChannel::AddClient(Client *c) {
|
||||
|
||||
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);
|
||||
|
||||
@@ -267,7 +272,7 @@ bool ChatChannel::RemoveClient(Client *c) {
|
||||
|
||||
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();
|
||||
|
||||
@@ -304,7 +309,7 @@ bool ChatChannel::RemoveClient(Client *c) {
|
||||
if((Password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0))
|
||||
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);
|
||||
}
|
||||
@@ -402,7 +407,7 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
|
||||
|
||||
if(ChannelClient)
|
||||
{
|
||||
LogInfo("Sending message to [{}] from [{}]",
|
||||
LogDebug("Sending message to [{}] from [{}]",
|
||||
ChannelClient->GetName().c_str(), Sender->GetName().c_str());
|
||||
|
||||
if (cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())].length() == 0) {
|
||||
@@ -505,7 +510,7 @@ ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client
|
||||
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);
|
||||
|
||||
@@ -581,7 +586,7 @@ void ChatChannelList::Process() {
|
||||
|
||||
if(CurrentChannel && CurrentChannel->ReadyToDelete()) {
|
||||
|
||||
LogInfo("Empty temporary password protected channel [{}] being destroyed",
|
||||
LogDebug("Empty temporary password protected channel [{}] being destroyed",
|
||||
CurrentChannel->GetName().c_str());
|
||||
|
||||
RemoveChannel(CurrentChannel);
|
||||
@@ -597,7 +602,7 @@ void ChatChannel::AddInvitee(const std::string &Invitee)
|
||||
if (!IsInvitee(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)) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-16
@@ -235,7 +235,7 @@ std::vector<std::string> ParseRecipients(std::string RecipientString) {
|
||||
|
||||
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;
|
||||
|
||||
@@ -304,7 +304,7 @@ static void ProcessMailTo(Client *c, std::string MailMessage) {
|
||||
|
||||
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());
|
||||
|
||||
int PacketLength = 10 + Recipient.length() + Subject.length();
|
||||
@@ -556,6 +556,17 @@ void Client::CloseConnection() {
|
||||
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) {
|
||||
|
||||
if (!c) return;
|
||||
@@ -634,10 +645,12 @@ void Clientlist::Process()
|
||||
//
|
||||
std::string::size_type LastPeriod = MailBoxString.find_last_of(".");
|
||||
|
||||
if (LastPeriod == std::string::npos)
|
||||
if (LastPeriod == std::string::npos) {
|
||||
CharacterName = MailBoxString;
|
||||
else
|
||||
}
|
||||
else {
|
||||
CharacterName = MailBoxString.substr(LastPeriod + 1);
|
||||
}
|
||||
|
||||
LogInfo("Received login for user [{}] with key [{}]",
|
||||
MailBox, Key);
|
||||
@@ -652,8 +665,9 @@ void Clientlist::Process()
|
||||
|
||||
database.GetAccountStatus((*it));
|
||||
|
||||
if ((*it)->GetConnectionType() == ConnectionTypeCombined)
|
||||
if ((*it)->GetConnectionType() == ConnectionTypeCombined) {
|
||||
(*it)->SendFriends();
|
||||
}
|
||||
|
||||
(*it)->SendMailBoxes();
|
||||
|
||||
@@ -865,7 +879,9 @@ void Clientlist::CloseAllConnections() {
|
||||
void Client::AddCharacter(int CharID, const char *CharacterName, int Level) {
|
||||
|
||||
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;
|
||||
NewCharacter.CharID = CharID;
|
||||
NewCharacter.Name = CharacterName;
|
||||
@@ -874,6 +890,10 @@ void Client::AddCharacter(int CharID, const char *CharacterName, int Level) {
|
||||
Characters.push_back(NewCharacter);
|
||||
}
|
||||
|
||||
void Client::SendKeepAlive() {
|
||||
QueuePacket(new EQApplicationPacket(OP_SessionReady, 0));
|
||||
}
|
||||
|
||||
void Client::SendMailBoxes() {
|
||||
|
||||
int Count = Characters.size();
|
||||
@@ -930,7 +950,7 @@ void Client::AddToChannelList(ChatChannel *JoinedChannel) {
|
||||
for (int i = 0; i < MAX_JOINED_CHANNELS; i++)
|
||||
if (JoinedChannels[i] == nullptr) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -2346,18 +2366,17 @@ void Client::SendFriends() {
|
||||
}
|
||||
}
|
||||
|
||||
std::string Client::MailBoxName() {
|
||||
std::string Client::MailBoxName()
|
||||
{
|
||||
if ((Characters.empty()) || (CurrentMailBox > (Characters.size() - 1))) {
|
||||
LogDebug("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
||||
CurrentMailBox, Characters.size());
|
||||
|
||||
if ((Characters.empty()) || (CurrentMailBox > (Characters.size() - 1)))
|
||||
{
|
||||
LogInfo("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
||||
CurrentMailBox, Characters.size());
|
||||
|
||||
return "";
|
||||
return std::string();
|
||||
}
|
||||
|
||||
LogInfo("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
||||
CurrentMailBox, Characters.size());
|
||||
LogDebug("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
|
||||
CurrentMailBox, Characters.size());
|
||||
|
||||
return Characters[CurrentMailBox].Name;
|
||||
|
||||
|
||||
+3
-1
@@ -143,7 +143,7 @@ public:
|
||||
void SetConnectionType(char c);
|
||||
ConnectionType GetConnectionType() { return TypeOfConnection; }
|
||||
EQEmu::versions::ClientVersion GetClientVersion() { return ClientVersion_; }
|
||||
|
||||
|
||||
inline bool IsMailConnection() { return (TypeOfConnection == ConnectionTypeMail) || (TypeOfConnection == ConnectionTypeCombined); }
|
||||
void SendNotification(int MailBoxNumber, std::string From, std::string Subject, int MessageID);
|
||||
void ChangeMailBox(int NewMailBox);
|
||||
@@ -151,6 +151,7 @@ public:
|
||||
void SendFriends();
|
||||
int GetCharID();
|
||||
void SendUptime();
|
||||
void SendKeepAlive();
|
||||
|
||||
private:
|
||||
unsigned int CurrentMailBox;
|
||||
@@ -183,6 +184,7 @@ public:
|
||||
void Process();
|
||||
void CloseAllConnections();
|
||||
Client *FindCharacter(std::string CharacterName);
|
||||
void CheckForStaleConnectionsAll();
|
||||
void CheckForStaleConnections(Client *c);
|
||||
Client *IsCharacterOnline(std::string CharacterName);
|
||||
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
||||
|
||||
+3
-3
@@ -108,7 +108,7 @@ void Database::GetAccountStatus(Client *client)
|
||||
{
|
||||
|
||||
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()
|
||||
);
|
||||
|
||||
@@ -173,7 +173,7 @@ int Database::FindAccount(const char *characterName, Client *client)
|
||||
|
||||
query = StringFormat(
|
||||
"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
|
||||
);
|
||||
|
||||
@@ -320,7 +320,7 @@ void Database::SendHeaders(Client *client)
|
||||
int unknownField3 = 1;
|
||||
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) {
|
||||
return;
|
||||
|
||||
+16
-8
@@ -70,17 +70,18 @@ int main() {
|
||||
// Check every minute for unused channels we can delete
|
||||
//
|
||||
Timer ChannelListProcessTimer(60000);
|
||||
Timer ClientConnectionPruneTimer(60000);
|
||||
|
||||
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
|
||||
|
||||
LogInfo("Starting EQEmu Universal Chat Server");
|
||||
|
||||
if (!ucsconfig::LoadConfig()) {
|
||||
LogInfo("Loading server configuration failed");
|
||||
if (!ucsconfig::LoadConfig()) {
|
||||
LogInfo("Loading server configuration failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Config = ucsconfig::get();
|
||||
Config = ucsconfig::get();
|
||||
|
||||
WorldShortName = Config->ShortName;
|
||||
|
||||
@@ -144,19 +145,26 @@ int main() {
|
||||
|
||||
worldserver = new WorldServer;
|
||||
|
||||
while(RunLoops) {
|
||||
auto loop_fn = [&](EQ::Timer* t) {
|
||||
|
||||
Timer::SetCurrentTime();
|
||||
|
||||
g_Clientlist->Process();
|
||||
|
||||
if(ChannelListProcessTimer.Check())
|
||||
if (ChannelListProcessTimer.Check()) {
|
||||
ChannelList->Process();
|
||||
}
|
||||
|
||||
EQ::EventLoop::Get().Process();
|
||||
if (ClientConnectionPruneTimer.Check()) {
|
||||
g_Clientlist->CheckForStaleConnectionsAll();
|
||||
}
|
||||
|
||||
Sleep(5);
|
||||
}
|
||||
};
|
||||
|
||||
EQ::Timer process_timer(loop_fn);
|
||||
process_timer.Start(32, true);
|
||||
|
||||
EQ::EventLoop::Get().Run();
|
||||
|
||||
ChannelList->RemoveAllChannels();
|
||||
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
|
||||
ServerPacket tpack(opcode, p);
|
||||
ServerPacket *pack = &tpack;
|
||||
|
||||
LogInfo("Received Opcode: {:#04x}", opcode);
|
||||
LogNetcode("Received Opcode: {:#04x}", opcode);
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
|
||||
@@ -331,7 +331,7 @@ OP_LDoNButton=0x596e
|
||||
OP_SetStartCity=0x7936 # Was 0x2d1b
|
||||
OP_VoiceMacroIn=0x202e
|
||||
OP_VoiceMacroOut=0x3920
|
||||
OP_ItemViewUnknown=0x0b64
|
||||
OP_ItemAdvancedLoreText=0x0b64
|
||||
OP_VetRewardsAvaliable=0x05d9
|
||||
OP_VetClaimRequest=0xcdde
|
||||
OP_VetClaimReply=0x361b
|
||||
|
||||
@@ -448,6 +448,8 @@ OP_FinishWindow2=0x40ef
|
||||
OP_ItemVerifyRequest=0x189c
|
||||
OP_ItemVerifyReply=0x097b
|
||||
|
||||
OP_ItemAdvancedLoreText=0x023b
|
||||
|
||||
# merchant stuff
|
||||
OP_ShopPlayerSell=0x791b
|
||||
OP_ShopRequest=0x4fed
|
||||
|
||||
@@ -327,7 +327,7 @@ OP_LDoNButton=0x41b5 # C
|
||||
OP_SetStartCity=0x7bf6 # C
|
||||
OP_VoiceMacroIn=0x31b1 # C
|
||||
OP_VoiceMacroOut=0x7880 # C
|
||||
OP_ItemViewUnknown=0x21c7 # C
|
||||
OP_ItemAdvancedLoreText=0x21c7 # C
|
||||
OP_VetRewardsAvaliable=0x4e4e # C
|
||||
OP_VetClaimRequest=0x771f # 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
|
||||
OP_LoginUnknown1=0x22cf
|
||||
OP_LoginUnknown2=0x43ba
|
||||
OP_ItemViewUnknown=0x4db4
|
||||
OP_ItemAdvancedLoreText=0x4db4
|
||||
|
||||
#Petition Opcodes
|
||||
OP_PetitionSearch=0x0000 #search term for petition
|
||||
|
||||
@@ -336,7 +336,7 @@ OP_LDoNButton=0x1031 # C
|
||||
OP_SetStartCity=0x68f0 # C
|
||||
OP_VoiceMacroIn=0x1524 # C
|
||||
OP_VoiceMacroOut=0x1d99 # C
|
||||
OP_ItemViewUnknown=0x4eb3 # C
|
||||
OP_ItemAdvancedLoreText=0x4eb3 # C
|
||||
OP_VetRewardsAvaliable=0x0baa # C Mispelled?
|
||||
OP_VetClaimRequest=0x34f8 # C
|
||||
OP_VetClaimReply=0x6a5d # C
|
||||
|
||||
+218
-263
@@ -52,6 +52,10 @@ if (-e "eqemu_server_skip_update.txt") {
|
||||
$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_xml_to_json_conversion() if $ARGV[0] eq "convert_xml";
|
||||
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);
|
||||
}
|
||||
|
||||
map_files_fetch_bulk();
|
||||
map_files_fetch_bulk() if !$skip_self_maps_update_check;
|
||||
opcodes_fetch();
|
||||
plugins_fetch();
|
||||
quest_files_fetch();
|
||||
@@ -493,9 +497,7 @@ sub do_installer_routines {
|
||||
|
||||
#::: Download PEQ latest
|
||||
fetch_peq_db_full();
|
||||
print "[Database] Fetching Latest Database Updates...\n";
|
||||
main_db_management();
|
||||
print "[Database] Applying Latest Database Updates...\n";
|
||||
print "[Database] Fetching and Applying Latest Database Updates...\n";
|
||||
main_db_management();
|
||||
|
||||
remove_duplicate_rule_values();
|
||||
@@ -531,35 +533,14 @@ sub check_for_world_bootup_database_update {
|
||||
}
|
||||
|
||||
$binary_database_version = trim($db_version[1]);
|
||||
$local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
|
||||
|
||||
#::: 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";
|
||||
}
|
||||
}
|
||||
$local_database_version = get_main_db_version();
|
||||
|
||||
if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") {
|
||||
print "[Update] Database up to date...\n";
|
||||
exit;
|
||||
if (trim($db_version[2]) == 0) {
|
||||
print "[Update] Continuing bootup\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
||||
@@ -567,22 +548,61 @@ sub check_for_world_bootup_database_update {
|
||||
print "[Update] Database not up to date with binaries... Automatically updating...\n";
|
||||
print "[Update] Issuing database backup first...\n";
|
||||
database_dump_compress();
|
||||
$db_already_backed_up = 1;
|
||||
print "[Update] Updating database...\n";
|
||||
sleep(1);
|
||||
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;
|
||||
}
|
||||
|
||||
#::: Make sure that we didn't pass any arugments to the script
|
||||
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"; }
|
||||
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 {
|
||||
@@ -629,7 +649,7 @@ sub do_self_update_check_routine {
|
||||
|
||||
#::: Check for internet connection before updating
|
||||
if (!$has_internet_connection) {
|
||||
print "[Update] Cannot check update without internet connection...\n";
|
||||
print "[Update] Cannot check self-update without internet connection...\n";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -813,15 +833,14 @@ sub fetch_utility_scripts {
|
||||
|
||||
sub setup_bots {
|
||||
if ($OS eq "Windows") {
|
||||
fetch_latest_windows_binaries_bots();
|
||||
fetch_latest_windows_appveyor_bots();
|
||||
}
|
||||
if ($OS eq "Linux") {
|
||||
build_linux_source("bots");
|
||||
}
|
||||
bots_db_management();
|
||||
run_database_check();
|
||||
|
||||
print "Bots should be setup, run your server and the #bot command should be available in-game\n";
|
||||
print "Bots should be setup, run your server and the bot command should be available in-game (type '^help')\n";
|
||||
}
|
||||
|
||||
sub show_menu_prompt {
|
||||
@@ -953,13 +972,11 @@ sub show_menu_prompt {
|
||||
$dc = 1;
|
||||
}
|
||||
elsif ($input eq "check_db_updates") {
|
||||
main_db_management();
|
||||
main_db_management();
|
||||
$dc = 1;
|
||||
}
|
||||
elsif ($input eq "check_bot_db_updates") {
|
||||
bots_db_management();
|
||||
run_database_check();
|
||||
$dc = 1;
|
||||
}
|
||||
elsif ($input eq "setup_loginserver") {
|
||||
@@ -1400,6 +1417,7 @@ sub remove_duplicate_rule_values {
|
||||
sub copy_file {
|
||||
$l_source_file = $_[0];
|
||||
$l_destination_file = $_[1];
|
||||
|
||||
if ($l_destination_file =~ /\//i) {
|
||||
my @directory_path = split('/', $l_destination_file);
|
||||
$build_path = "";
|
||||
@@ -1418,6 +1436,7 @@ sub copy_file {
|
||||
$directory_index++;
|
||||
}
|
||||
}
|
||||
|
||||
copy $l_source_file, $l_destination_file;
|
||||
}
|
||||
|
||||
@@ -1693,26 +1712,22 @@ sub fetch_server_dlls {
|
||||
|
||||
sub fetch_peq_db_full {
|
||||
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";
|
||||
unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/');
|
||||
my $start_dir = "updates_staged/peq_db";
|
||||
unzip('updates_staged/peq-latest.zip', 'updates_staged/peq_db/');
|
||||
my $start_dir = "updates_staged/peq_db/peq-dump";
|
||||
find(
|
||||
sub { push @files, $File::Find::name unless -d; },
|
||||
$start_dir
|
||||
);
|
||||
for my $file (@files) {
|
||||
$destination_file = $file;
|
||||
$destination_file =~ s/updates_staged\/peq_db\///g;
|
||||
if ($file =~ /peqbeta|player_tables/i) {
|
||||
$destination_file =~ s/updates_staged\/peq_db\/peq-dump\///g;
|
||||
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";
|
||||
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 {
|
||||
@@ -2001,15 +2016,6 @@ sub do_bots_db_schema_drop {
|
||||
print get_mysql_result_from_file("db_update/drop_bots.sql");
|
||||
|
||||
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) {
|
||||
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`);");
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
#::: Check if bots_version column exists...
|
||||
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 "[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"));
|
||||
return $bots_local_db_version;
|
||||
}
|
||||
|
||||
#::: Safe for call from world startup or menu option
|
||||
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 ($db_run_stage > 0 && $bots_db_management == 0) {
|
||||
clear_database_runs();
|
||||
}
|
||||
|
||||
|
||||
#::: Main Binary Database version
|
||||
$binary_database_version = trim($db_version[2]);
|
||||
if ($binary_database_version == 0) {
|
||||
print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$local_database_version = get_bots_db_version();
|
||||
|
||||
#::: Set on flag for running bot updates...
|
||||
$bots_db_management = 1;
|
||||
|
||||
$bots_local_db_version = get_bots_db_version();
|
||||
|
||||
$local_database_version = $bots_local_db_version;
|
||||
|
||||
|
||||
if ($local_database_version > $binary_database_version) {
|
||||
print "[Update] Bots database version is ahead of current binaries...\n";
|
||||
return;
|
||||
}
|
||||
|
||||
run_database_check();
|
||||
}
|
||||
|
||||
#::: Safe for call from world startup or menu option
|
||||
sub main_db_management {
|
||||
#::: If we have stale data from bots db run
|
||||
if ($db_run_stage > 0 && $bots_db_management == 1) {
|
||||
@@ -2254,8 +2198,15 @@ sub main_db_management {
|
||||
|
||||
#::: Main Binary Database version
|
||||
$binary_database_version = trim($db_version[1]);
|
||||
$local_database_version = get_main_db_version();
|
||||
|
||||
$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();
|
||||
}
|
||||
|
||||
@@ -2265,148 +2216,70 @@ sub clear_database_runs {
|
||||
%m_d = ();
|
||||
#::: Clear updates...
|
||||
@total_updates = ();
|
||||
#::: Clear stage
|
||||
$db_run_stage = 0;
|
||||
}
|
||||
|
||||
#::: Responsible for Database Upgrade Routines
|
||||
sub run_database_check {
|
||||
|
||||
|
||||
if (!$db) {
|
||||
print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!@total_updates) {
|
||||
#::: Pull down bots database manifest
|
||||
if ($bots_db_management == 1) {
|
||||
print "[Database] Retrieving latest bots database manifest...\n";
|
||||
get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt");
|
||||
}
|
||||
#::: Pull down mainstream database manifest
|
||||
else {
|
||||
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");
|
||||
}
|
||||
|
||||
#::: Pull down bots database manifest
|
||||
if ($bots_db_management == 1) {
|
||||
print "[Database] Retrieving latest bots database manifest...\n";
|
||||
get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt");
|
||||
}
|
||||
|
||||
#::: Run 2 - Running pending updates...
|
||||
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...
|
||||
#::: Pull down mainstream database manifest
|
||||
else {
|
||||
print "[Database] Reading manifest...\n";
|
||||
|
||||
use Data::Dumper;
|
||||
open(FILE, "db_update/db_update_manifest.txt");
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
$o = $_;
|
||||
if ($o =~ /#/i) {
|
||||
next;
|
||||
}
|
||||
|
||||
@manifest = split('\|', $o);
|
||||
$m_d{$manifest[0]} = [ @manifest ];
|
||||
}
|
||||
#::: Setting Manifest stage...
|
||||
$db_run_stage = 1;
|
||||
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");
|
||||
}
|
||||
|
||||
@total_updates = ();
|
||||
|
||||
|
||||
#::: Parse manifest
|
||||
print "[Database] Reading manifest...\n";
|
||||
|
||||
use Data::Dumper;
|
||||
open(FILE, "db_update/db_update_manifest.txt");
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
$o = $_;
|
||||
if ($o =~ /#/i) {
|
||||
next;
|
||||
}
|
||||
|
||||
@manifest = split('\|', $o);
|
||||
$m_d{$manifest[0]} = [ @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) {
|
||||
$revision_check = $local_database_version;
|
||||
$revision_check = $local_database_version + 1;
|
||||
}
|
||||
else {
|
||||
#::: This does not negatively affect bots
|
||||
$revision_check = 1000;
|
||||
if (get_mysql_result("SHOW TABLES LIKE 'character_data'") ne "") {
|
||||
$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++) {
|
||||
if (!defined($m_d{$i}[0])) {
|
||||
next;
|
||||
}
|
||||
|
||||
$file_name = trim($m_d{$i}[1]);
|
||||
$query_check = trim($m_d{$i}[2]);
|
||||
$match_type = trim($m_d{$i}[3]);
|
||||
$match_text = trim($m_d{$i}[4]);
|
||||
|
||||
#::: Match type update
|
||||
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();
|
||||
}
|
||||
|
||||
$file_name = trim($m_d{$i}[1]);
|
||||
print "[Database] fetching update: " . $i . " '" . $file_name . "' \n";
|
||||
fetch_missing_db_update($i, $file_name);
|
||||
push(@total_updates, $i);
|
||||
}
|
||||
print "\n";
|
||||
|
||||
if (scalar(@total_updates) == 0 && $db_run_stage == 2) {
|
||||
|
||||
if (scalar(@total_updates) == 0) {
|
||||
print "[Database] No updates need to be run...\n";
|
||||
if ($bots_db_management == 1) {
|
||||
print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n";
|
||||
@@ -2416,24 +2289,106 @@ sub run_database_check {
|
||||
print "[Database] Setting Database to Binary Version (" . $binary_database_version . ") if not already...\n\n";
|
||||
get_mysql_result("UPDATE db_version SET version = $binary_database_version ");
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
$db_update = $_[0];
|
||||
$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 . "");
|
||||
}
|
||||
else {
|
||||
}
|
||||
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) {
|
||||
get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . "");
|
||||
elsif ($db_update >= 5000 && $db_update <= 9000) {
|
||||
get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
adventure_stats
|
||||
char_recipe_list
|
||||
character_auras
|
||||
character_activities
|
||||
character_alt_currency
|
||||
character_alternate_abilities
|
||||
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_inventory
|
||||
character_potionbelt
|
||||
character_skills
|
||||
character_spells
|
||||
character_tribute
|
||||
completed_tasks
|
||||
faction_values
|
||||
friends
|
||||
guild_members
|
||||
instance_list_player
|
||||
inventory
|
||||
inventory_snapshots
|
||||
keyring
|
||||
mail
|
||||
player_titlesets
|
||||
quest_globals
|
||||
timers
|
||||
titles
|
||||
zone_flags
|
||||
@@ -1,6 +0,0 @@
|
||||
command_settings
|
||||
inventory_versions
|
||||
launcher
|
||||
rule_sets
|
||||
rule_values
|
||||
variables
|
||||
@@ -399,6 +399,13 @@
|
||||
9143|2019_09_16_account_table_changes.sql|SHOW COLUMNS FROM `account` LIKE 'ls_id'|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|
|
||||
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:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
9020|2018_08_13_bots_inventory_update.sql|SELECT * FROM `inventory_versions` WHERE `version` = 2 and `bot_step` = 0|not_empty|
|
||||
9021|2018_10_09_bots_owner_options.sql|SHOW TABLES LIKE 'bot_owner_options'|empty|
|
||||
9022|2019_02_07_bots_stance_type_update.sql|SELECT * FROM `bot_spell_casting_chances` WHERE `spell_type_index` = '255' AND `class_id` = '255' AND `stance_index` = '0'|not_empty|
|
||||
9023|2019_06_22_bots_owner_option_stats_update.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'stats_update'|empty|
|
||||
9023|2019_06_22_bots_owner_option_stats_update.sql|SELECT * FROM db_version WHERE bots_version >= 9023|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|SHOW COLUMNS FROM `bot_owner_options` LIKE 'spawn_message_enabled'|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|
|
||||
9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# 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 @@
|
||||
ALTER TABLE `character_data` ADD COLUMN `deleted_at` datetime NULL DEFAULT NULL;
|
||||
@@ -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
|
||||
@@ -2119,102 +2119,3 @@ void AdventureManager::Save()
|
||||
}
|
||||
}
|
||||
|
||||
void AdventureManager::Load()
|
||||
{
|
||||
//disabled for now
|
||||
return;
|
||||
|
||||
char *data = nullptr;
|
||||
FILE *f = fopen("adventure_state.dat", "r");
|
||||
if(f)
|
||||
{
|
||||
fseek(f, 0, SEEK_END);
|
||||
long length = ftell(f);
|
||||
if(length > 0)
|
||||
{
|
||||
data = new char[length];
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(data, length, 1, f);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if(data)
|
||||
{
|
||||
char *ptr = data;
|
||||
|
||||
int number_of_adventures = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
for(int i = 0; i < number_of_adventures; ++i)
|
||||
{
|
||||
int count = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
int a_count = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
int template_id = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
int status = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
int instance_id = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
int rem_time = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
int num_players = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
AdventureTemplate *t = GetAdventureTemplate(template_id);
|
||||
if(t)
|
||||
{
|
||||
auto adv =
|
||||
new Adventure(t, count, a_count, (AdventureStatus)status, instance_id, rem_time);
|
||||
for(int j = 0; j < num_players; ++j)
|
||||
{
|
||||
adv->AddPlayer((const char*)ptr, false);
|
||||
ptr += strlen((const char*)ptr);
|
||||
ptr += 1;
|
||||
}
|
||||
adventure_list.push_back(adv);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < num_players; ++j)
|
||||
{
|
||||
ptr += strlen((const char*)ptr);
|
||||
ptr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int number_of_finished = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
for(int k = 0; k < number_of_finished; ++k)
|
||||
{
|
||||
AdventureFinishEvent afe;
|
||||
afe.win = *((bool*)ptr);
|
||||
ptr += sizeof(bool);
|
||||
|
||||
afe.points = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
afe.theme = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
|
||||
afe.name = (const char*)ptr;
|
||||
ptr += strlen((const char*)ptr);
|
||||
ptr += 1;
|
||||
|
||||
finished_list.push_back(afe);
|
||||
}
|
||||
|
||||
safe_delete_array(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ public:
|
||||
void AddFinishedEvent(AdventureFinishEvent fe) { finished_list.push_back(fe); Save(); }
|
||||
bool PopFinishedEvent(const char *name, AdventureFinishEvent &fe);
|
||||
void Save();
|
||||
void Load();
|
||||
|
||||
Adventure **GetFinishedAdventures(const char *player, int &count);
|
||||
Adventure *GetActiveAdventure(const char *player);
|
||||
|
||||
+36
-7
@@ -802,9 +802,9 @@ void ConsoleIpLookup(
|
||||
const std::vector<std::string> &args
|
||||
)
|
||||
{
|
||||
if (args.size() > 0) {
|
||||
if (!args.empty()) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 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("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("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("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("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("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("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("zonelock", 150, "zonelock [list|lock|unlock] [zonename]", 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("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] [zone_short_name]", std::bind(ConsoleZoneLock, 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("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));
|
||||
|
||||
+1
-1
@@ -396,7 +396,6 @@ int main(int argc, char** argv) {
|
||||
LogInfo("Unable to load adventure templates");
|
||||
}
|
||||
|
||||
adventure_manager.Load();
|
||||
adventure_manager.LoadLeaderboardInfo();
|
||||
|
||||
LogInfo("Purging expired instances");
|
||||
@@ -416,6 +415,7 @@ int main(int argc, char** argv) {
|
||||
RegisterConsoleFunctions(console);
|
||||
}
|
||||
|
||||
zoneserver_list.Init();
|
||||
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
||||
server_connection.reset(new EQ::Net::ServertalkServer());
|
||||
|
||||
|
||||
+30
-11
@@ -6,29 +6,38 @@
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/md5.h"
|
||||
#include "../common/packet_dump.h"
|
||||
#include "../common/event/timer.h"
|
||||
|
||||
UCSConnection::UCSConnection()
|
||||
{
|
||||
Stream = 0;
|
||||
connection = 0;
|
||||
}
|
||||
|
||||
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");
|
||||
Stream->Handle()->Disconnect();
|
||||
connection->Handle()->Disconnect();
|
||||
}
|
||||
|
||||
connection = inStream;
|
||||
if (connection) {
|
||||
connection->OnMessage(
|
||||
std::bind(
|
||||
&UCSConnection::ProcessPacket,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Stream = inStream;
|
||||
if (Stream) {
|
||||
Stream->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)
|
||||
{
|
||||
if (!Stream)
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
ServerPacket tpack(opcode, p);
|
||||
@@ -60,10 +69,10 @@ void UCSConnection::ProcessPacket(uint16 opcode, EQ::Net::Packet &p)
|
||||
|
||||
void UCSConnection::SendPacket(ServerPacket* pack)
|
||||
{
|
||||
if (!Stream)
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
Stream->SendPacket(pack);
|
||||
connection->SendPacket(pack);
|
||||
}
|
||||
|
||||
void UCSConnection::SendMessage(const char *From, const char *Message)
|
||||
@@ -78,3 +87,13 @@ void UCSConnection::SendMessage(const char *From, const char *Message)
|
||||
SendPacket(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/net/servertalk_server_connection.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/event/timer.h"
|
||||
#include <memory>
|
||||
|
||||
class UCSConnection
|
||||
@@ -13,11 +14,17 @@ public:
|
||||
void SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection);
|
||||
void ProcessPacket(uint16 opcode, EQ::Net::Packet &p);
|
||||
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);
|
||||
private:
|
||||
inline std::string GetIP() const { return (Stream && Stream->Handle()) ? Stream->Handle()->RemoteIP() : 0; }
|
||||
std::shared_ptr<EQ::Net::ServertalkServerConnection> Stream;
|
||||
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
|
||||
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
|
||||
|
||||
/**
|
||||
* Keepalive
|
||||
*/
|
||||
std::unique_ptr<EQ::Timer> m_keepalive;
|
||||
void OnKeepAlive(EQ::Timer *t);
|
||||
};
|
||||
|
||||
#endif /*UCS_H_*/
|
||||
|
||||
@@ -24,7 +24,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
|
||||
std::stringstream ss(json_str);
|
||||
ss >> root;
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
SendError("Could not parse request");
|
||||
return;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
SendError("Invalid request: method not supplied");
|
||||
return;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
|
||||
try {
|
||||
params = root["params"];
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
params = nullptr;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
|
||||
try {
|
||||
id = root["id"].asString();
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
id = "";
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ void WebInterface::Send(const Json::Value &value)
|
||||
p.PutString(0, ss.str());
|
||||
m_connection->Send(ServerOP_WebInterfaceCall, p);
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
//Log error
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ void WebInterface::SendEvent(const Json::Value &value)
|
||||
p.PutString(0, ss.str());
|
||||
m_connection->Send(ServerOP_WebInterfaceEvent, p);
|
||||
}
|
||||
catch (std::exception) {
|
||||
catch (std::exception &) {
|
||||
//Log error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "../common/version.h"
|
||||
#include "worlddb.h"
|
||||
#include "../common/database_schema.h"
|
||||
#include "../common/database/database_dump_service.h"
|
||||
|
||||
namespace WorldserverCommandHandler {
|
||||
|
||||
@@ -51,6 +52,7 @@ namespace WorldserverCommandHandler {
|
||||
function_map["database:version"] = &WorldserverCommandHandler::DatabaseVersion;
|
||||
function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus;
|
||||
function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema;
|
||||
function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump;
|
||||
|
||||
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
|
||||
}
|
||||
@@ -145,7 +147,7 @@ namespace WorldserverCommandHandler {
|
||||
*/
|
||||
void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||
{
|
||||
description = "Displays server database schema";
|
||||
description = "Displays server database schema";
|
||||
|
||||
if (cmd[{"-h", "--help"}]) {
|
||||
return;
|
||||
@@ -202,4 +204,71 @@ namespace WorldserverCommandHandler {
|
||||
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 DatabaseSetAccountStatus(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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+194
-146
@@ -31,23 +31,27 @@ extern std::vector<RaceClassAllocation> character_create_allocations;
|
||||
extern std::vector<RaceClassCombos> character_create_race_class_combos;
|
||||
|
||||
|
||||
// the current stuff is at the bottom of this function
|
||||
void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit)
|
||||
/**
|
||||
* @param account_id
|
||||
* @param out_app
|
||||
* @param client_version_bit
|
||||
*/
|
||||
void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **out_app, uint32 client_version_bit)
|
||||
{
|
||||
/* Set Character Creation Limit */
|
||||
EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit);
|
||||
EQEmu::versions::ClientVersion
|
||||
client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(client_version_bit);
|
||||
size_t character_limit = EQEmu::constants::StaticLookup(client_version)->CharacterCreationLimit;
|
||||
|
||||
// Validate against absolute server max
|
||||
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT)
|
||||
|
||||
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) {
|
||||
character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT;
|
||||
}
|
||||
|
||||
// Force Titanium clients to use '8'
|
||||
if (client_version == EQEmu::versions::ClientVersion::Titanium)
|
||||
if (client_version == EQEmu::versions::ClientVersion::Titanium) {
|
||||
character_limit = 8;
|
||||
|
||||
/* Get Character Info */
|
||||
std::string cquery = StringFormat(
|
||||
}
|
||||
|
||||
std::string character_list_query = StringFormat(
|
||||
"SELECT "
|
||||
"`id`, " // 0
|
||||
"name, " // 1
|
||||
@@ -71,237 +75,281 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
|
||||
"zone_id " // 19
|
||||
"FROM "
|
||||
"character_data "
|
||||
"WHERE `account_id` = %i ORDER BY `name` LIMIT %u", accountID, character_limit);
|
||||
auto results = database.QueryDatabase(cquery);
|
||||
"WHERE `account_id` = %i AND deleted_at IS NULL ORDER BY `name` LIMIT %u",
|
||||
account_id,
|
||||
character_limit
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(character_list_query);
|
||||
|
||||
size_t character_count = results.RowCount();
|
||||
if (character_count == 0) {
|
||||
*outApp = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
|
||||
CharacterSelect_Struct *cs = (CharacterSelect_Struct *)(*outApp)->pBuffer;
|
||||
cs->CharCount = 0;
|
||||
*out_app = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
|
||||
CharacterSelect_Struct *cs = (CharacterSelect_Struct *) (*out_app)->pBuffer;
|
||||
cs->CharCount = 0;
|
||||
cs->TotalChars = character_limit;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t packet_size = sizeof(CharacterSelect_Struct) + (sizeof(CharacterSelectEntry_Struct) * character_count);
|
||||
*outApp = new EQApplicationPacket(OP_SendCharInfo, packet_size);
|
||||
*out_app = new EQApplicationPacket(OP_SendCharInfo, packet_size);
|
||||
|
||||
unsigned char *buff_ptr = (*outApp)->pBuffer;
|
||||
CharacterSelect_Struct *cs = (CharacterSelect_Struct *)buff_ptr;
|
||||
unsigned char *buff_ptr = (*out_app)->pBuffer;
|
||||
CharacterSelect_Struct *cs = (CharacterSelect_Struct *) buff_ptr;
|
||||
|
||||
cs->CharCount = character_count;
|
||||
cs->CharCount = character_count;
|
||||
cs->TotalChars = character_limit;
|
||||
|
||||
buff_ptr += sizeof(CharacterSelect_Struct);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr;
|
||||
PlayerProfile_Struct pp;
|
||||
EQEmu::InventoryProfile inv;
|
||||
CharacterSelectEntry_Struct *p_character_select_entry_struct = (CharacterSelectEntry_Struct *) buff_ptr;
|
||||
PlayerProfile_Struct player_profile_struct;
|
||||
EQEmu::InventoryProfile inventory_profile;
|
||||
|
||||
pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version));
|
||||
inv.SetInventoryVersion(client_version);
|
||||
inv.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support
|
||||
player_profile_struct.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version));
|
||||
inventory_profile.SetInventoryVersion(client_version);
|
||||
inventory_profile.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support
|
||||
|
||||
uint32 character_id = (uint32)atoi(row[0]);
|
||||
uint8 has_home = 0;
|
||||
uint8 has_bind = 0;
|
||||
uint32 character_id = (uint32) atoi(row[0]);
|
||||
uint8 has_home = 0;
|
||||
uint8 has_bind = 0;
|
||||
|
||||
memset(&pp, 0, sizeof(PlayerProfile_Struct));
|
||||
|
||||
/* Fill CharacterSelectEntry_Struct */
|
||||
memset(cse->Name, 0, sizeof(cse->Name));
|
||||
strcpy(cse->Name, row[1]);
|
||||
cse->Class = (uint8)atoi(row[4]);
|
||||
cse->Race = (uint32)atoi(row[3]);
|
||||
cse->Level = (uint8)atoi(row[5]);
|
||||
cse->ShroudClass = cse->Class;
|
||||
cse->ShroudRace = cse->Race;
|
||||
cse->Zone = (uint16)atoi(row[19]);
|
||||
cse->Instance = 0;
|
||||
cse->Gender = (uint8)atoi(row[2]);
|
||||
cse->Face = (uint8)atoi(row[15]);
|
||||
memset(&player_profile_struct, 0, sizeof(PlayerProfile_Struct));
|
||||
|
||||
for (uint32 matslot = 0; matslot < EQEmu::textures::materialCount; matslot++) { // Processed below
|
||||
cse->Equip[matslot].Material = 0;
|
||||
cse->Equip[matslot].Unknown1 = 0;
|
||||
cse->Equip[matslot].EliteModel = 0;
|
||||
cse->Equip[matslot].HerosForgeModel = 0;
|
||||
cse->Equip[matslot].Unknown2 = 0;
|
||||
cse->Equip[matslot].Color = 0;
|
||||
}
|
||||
memset(p_character_select_entry_struct->Name, 0, sizeof(p_character_select_entry_struct->Name));
|
||||
strcpy(p_character_select_entry_struct->Name, row[1]);
|
||||
p_character_select_entry_struct->Class = (uint8) atoi(row[4]);
|
||||
p_character_select_entry_struct->Race = (uint32) atoi(row[3]);
|
||||
p_character_select_entry_struct->Level = (uint8) atoi(row[5]);
|
||||
p_character_select_entry_struct->ShroudClass = p_character_select_entry_struct->Class;
|
||||
p_character_select_entry_struct->ShroudRace = p_character_select_entry_struct->Race;
|
||||
p_character_select_entry_struct->Zone = (uint16) atoi(row[19]);
|
||||
p_character_select_entry_struct->Instance = 0;
|
||||
p_character_select_entry_struct->Gender = (uint8) atoi(row[2]);
|
||||
p_character_select_entry_struct->Face = (uint8) atoi(row[15]);
|
||||
|
||||
cse->Unknown15 = 0xFF;
|
||||
cse->Unknown19 = 0xFF;
|
||||
cse->DrakkinTattoo = (uint32)atoi(row[17]);
|
||||
cse->DrakkinDetails = (uint32)atoi(row[18]);
|
||||
cse->Deity = (uint32)atoi(row[6]);
|
||||
cse->PrimaryIDFile = 0; // Processed Below
|
||||
cse->SecondaryIDFile = 0; // Processed Below
|
||||
cse->HairColor = (uint8)atoi(row[9]);
|
||||
cse->BeardColor = (uint8)atoi(row[10]);
|
||||
cse->EyeColor1 = (uint8)atoi(row[11]);
|
||||
cse->EyeColor2 = (uint8)atoi(row[12]);
|
||||
cse->HairStyle = (uint8)atoi(row[13]);
|
||||
cse->Beard = (uint8)atoi(row[14]);
|
||||
cse->GoHome = 0; // Processed Below
|
||||
cse->Tutorial = 0; // Processed Below
|
||||
cse->DrakkinHeritage = (uint32)atoi(row[16]);
|
||||
cse->Unknown1 = 0;
|
||||
cse->Enabled = 1;
|
||||
cse->LastLogin = (uint32)atoi(row[7]); // RoF2 value: 1212696584
|
||||
cse->Unknown2 = 0;
|
||||
/* Fill End */
|
||||
for (uint32 material_slot = 0; material_slot < EQEmu::textures::materialCount; material_slot++) {
|
||||
p_character_select_entry_struct->Equip[material_slot].Material = 0;
|
||||
p_character_select_entry_struct->Equip[material_slot].Unknown1 = 0;
|
||||
p_character_select_entry_struct->Equip[material_slot].EliteModel = 0;
|
||||
p_character_select_entry_struct->Equip[material_slot].HerosForgeModel = 0;
|
||||
p_character_select_entry_struct->Equip[material_slot].Unknown2 = 0;
|
||||
p_character_select_entry_struct->Equip[material_slot].Color = 0;
|
||||
}
|
||||
|
||||
p_character_select_entry_struct->Unknown15 = 0xFF;
|
||||
p_character_select_entry_struct->Unknown19 = 0xFF;
|
||||
p_character_select_entry_struct->DrakkinTattoo = (uint32) atoi(row[17]);
|
||||
p_character_select_entry_struct->DrakkinDetails = (uint32) atoi(row[18]);
|
||||
p_character_select_entry_struct->Deity = (uint32) atoi(row[6]);
|
||||
p_character_select_entry_struct->PrimaryIDFile = 0; // Processed Below
|
||||
p_character_select_entry_struct->SecondaryIDFile = 0; // Processed Below
|
||||
p_character_select_entry_struct->HairColor = (uint8) atoi(row[9]);
|
||||
p_character_select_entry_struct->BeardColor = (uint8) atoi(row[10]);
|
||||
p_character_select_entry_struct->EyeColor1 = (uint8) atoi(row[11]);
|
||||
p_character_select_entry_struct->EyeColor2 = (uint8) atoi(row[12]);
|
||||
p_character_select_entry_struct->HairStyle = (uint8) atoi(row[13]);
|
||||
p_character_select_entry_struct->Beard = (uint8) atoi(row[14]);
|
||||
p_character_select_entry_struct->GoHome = 0; // Processed Below
|
||||
p_character_select_entry_struct->Tutorial = 0; // Processed Below
|
||||
p_character_select_entry_struct->DrakkinHeritage = (uint32) atoi(row[16]);
|
||||
p_character_select_entry_struct->Unknown1 = 0;
|
||||
p_character_select_entry_struct->Enabled = 1;
|
||||
p_character_select_entry_struct->LastLogin = (uint32) atoi(row[7]); // RoF2 value: 1212696584
|
||||
p_character_select_entry_struct->Unknown2 = 0;
|
||||
|
||||
if (RuleB(World, EnableReturnHomeButton)) {
|
||||
int now = time(nullptr);
|
||||
if ((now - atoi(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome))
|
||||
cse->GoHome = 1;
|
||||
if ((now - atoi(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome)) {
|
||||
p_character_select_entry_struct->GoHome = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (RuleB(World, EnableTutorialButton) && (cse->Level <= RuleI(World, MaxLevelForTutorial))) {
|
||||
cse->Tutorial = 1;
|
||||
if (RuleB(World, EnableTutorialButton) && (p_character_select_entry_struct->Level <= RuleI(World, MaxLevelForTutorial))) {
|
||||
p_character_select_entry_struct->Tutorial = 1;
|
||||
}
|
||||
|
||||
/* Set Bind Point Data for any character that may possibly be missing it for any reason */
|
||||
cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5", character_id);
|
||||
auto results_bind = database.QueryDatabase(cquery);
|
||||
auto bind_count = results_bind.RowCount();
|
||||
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
|
||||
/**
|
||||
* Bind
|
||||
*/
|
||||
character_list_query = StringFormat(
|
||||
"SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5",
|
||||
character_id
|
||||
);
|
||||
auto results_bind = database.QueryDatabase(character_list_query);
|
||||
auto bind_count = results_bind.RowCount();
|
||||
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
|
||||
if (row_b[6] && atoi(row_b[6]) == 4) {
|
||||
has_home = 1;
|
||||
// If our bind count is less than 5, we need to actually make use of this data so lets parse it
|
||||
if (bind_count < 5) {
|
||||
pp.binds[4].zoneId = atoi(row_b[0]);
|
||||
pp.binds[4].instance_id = atoi(row_b[1]);
|
||||
pp.binds[4].x = atof(row_b[2]);
|
||||
pp.binds[4].y = atof(row_b[3]);
|
||||
pp.binds[4].z = atof(row_b[4]);
|
||||
pp.binds[4].heading = atof(row_b[5]);
|
||||
player_profile_struct.binds[4].zoneId = atoi(row_b[0]);
|
||||
player_profile_struct.binds[4].instance_id = atoi(row_b[1]);
|
||||
player_profile_struct.binds[4].x = atof(row_b[2]);
|
||||
player_profile_struct.binds[4].y = atof(row_b[3]);
|
||||
player_profile_struct.binds[4].z = atof(row_b[4]);
|
||||
player_profile_struct.binds[4].heading = atof(row_b[5]);
|
||||
}
|
||||
}
|
||||
if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
|
||||
if (row_b[6] && atoi(row_b[6]) == 0) { has_bind = 1; }
|
||||
}
|
||||
|
||||
if (has_home == 0 || has_bind == 0) {
|
||||
cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
|
||||
cse->Class, cse->Deity, cse->Race);
|
||||
auto results_bind = database.QueryDatabase(cquery);
|
||||
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
|
||||
character_list_query = StringFormat(
|
||||
"SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
|
||||
p_character_select_entry_struct->Class,
|
||||
p_character_select_entry_struct->Deity,
|
||||
p_character_select_entry_struct->Race
|
||||
);
|
||||
auto results_bind = database.QueryDatabase(character_list_query);
|
||||
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
|
||||
/* If a bind_id is specified, make them start there */
|
||||
if (atoi(row_d[1]) != 0) {
|
||||
pp.binds[4].zoneId = (uint32)atoi(row_d[1]);
|
||||
GetSafePoints(pp.binds[4].zoneId, 0, &pp.binds[4].x, &pp.binds[4].y, &pp.binds[4].z);
|
||||
player_profile_struct.binds[4].zoneId = (uint32) atoi(row_d[1]);
|
||||
GetSafePoints(player_profile_struct.binds[4].zoneId, 0, &player_profile_struct.binds[4].x, &player_profile_struct.binds[4].y, &player_profile_struct.binds[4].z);
|
||||
}
|
||||
/* Otherwise, use the zone and coordinates given */
|
||||
/* Otherwise, use the zone and coordinates given */
|
||||
else {
|
||||
pp.binds[4].zoneId = (uint32)atoi(row_d[0]);
|
||||
player_profile_struct.binds[4].zoneId = (uint32) atoi(row_d[0]);
|
||||
float x = atof(row_d[2]);
|
||||
float y = atof(row_d[3]);
|
||||
float z = atof(row_d[4]);
|
||||
if (x == 0 && y == 0 && z == 0){ GetSafePoints(pp.binds[4].zoneId, 0, &x, &y, &z); }
|
||||
pp.binds[4].x = x; pp.binds[4].y = y; pp.binds[4].z = z;
|
||||
if (x == 0 && y == 0 && z == 0) { GetSafePoints(player_profile_struct.binds[4].zoneId, 0, &x, &y, &z); }
|
||||
player_profile_struct.binds[4].x = x;
|
||||
player_profile_struct.binds[4].y = y;
|
||||
player_profile_struct.binds[4].z = z;
|
||||
}
|
||||
}
|
||||
pp.binds[0] = pp.binds[4];
|
||||
player_profile_struct.binds[0] = player_profile_struct.binds[4];
|
||||
/* If no home bind set, set it */
|
||||
if (has_home == 0) {
|
||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 4);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
character_id,
|
||||
player_profile_struct.binds[4].zoneId,
|
||||
0,
|
||||
player_profile_struct.binds[4].x,
|
||||
player_profile_struct.binds[4].y,
|
||||
player_profile_struct.binds[4].z,
|
||||
player_profile_struct.binds[4].heading,
|
||||
4
|
||||
);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
}
|
||||
/* If no regular bind set, set it */
|
||||
if (has_bind == 0) {
|
||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
character_id,
|
||||
player_profile_struct.binds[0].zoneId,
|
||||
0,
|
||||
player_profile_struct.binds[0].x,
|
||||
player_profile_struct.binds[0].y,
|
||||
player_profile_struct.binds[0].z,
|
||||
player_profile_struct.binds[0].heading,
|
||||
0
|
||||
);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
/* If our bind count is less than 5, then we have null data that needs to be filled in. */
|
||||
if (bind_count < 5) {
|
||||
// we know that home and main bind must be valid here, so we don't check those
|
||||
// we also use home to fill in the null data like live does.
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (pp.binds[i].zoneId != 0) // we assume 0 is the only invalid one ...
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (player_profile_struct.binds[i].zoneId != 0) { // we assume 0 is the only invalid one ...
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, i);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
character_id,
|
||||
player_profile_struct.binds[4].zoneId,
|
||||
0,
|
||||
player_profile_struct.binds[4].x,
|
||||
player_profile_struct.binds[4].y,
|
||||
player_profile_struct.binds[4].z,
|
||||
player_profile_struct.binds[4].heading,
|
||||
i
|
||||
);
|
||||
auto results_bset = QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
/* Bind End */
|
||||
|
||||
/* Load Character Material Data for Char Select */
|
||||
cquery = StringFormat("SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u", character_id);
|
||||
auto results_b = database.QueryDatabase(cquery); uint8 slot = 0;
|
||||
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
|
||||
character_list_query = StringFormat(
|
||||
"SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u",
|
||||
character_id
|
||||
);
|
||||
auto results_b = database.QueryDatabase(character_list_query);
|
||||
uint8 slot = 0;
|
||||
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
|
||||
slot = atoi(row_b[0]);
|
||||
pp.item_tint.Slot[slot].Red = atoi(row_b[1]);
|
||||
pp.item_tint.Slot[slot].Green = atoi(row_b[2]);
|
||||
pp.item_tint.Slot[slot].Blue = atoi(row_b[3]);
|
||||
pp.item_tint.Slot[slot].UseTint = atoi(row_b[4]);
|
||||
player_profile_struct.item_tint.Slot[slot].Red = atoi(row_b[1]);
|
||||
player_profile_struct.item_tint.Slot[slot].Green = atoi(row_b[2]);
|
||||
player_profile_struct.item_tint.Slot[slot].Blue = atoi(row_b[3]);
|
||||
player_profile_struct.item_tint.Slot[slot].UseTint = atoi(row_b[4]);
|
||||
}
|
||||
/* Character Material Data End */
|
||||
|
||||
/* Load Inventory */
|
||||
// If we ensure that the material data is updated appropriately, we can do away with inventory loads
|
||||
if (GetCharSelInventory(accountID, cse->Name, &inv)) {
|
||||
const EQEmu::ItemData* item = nullptr;
|
||||
const EQEmu::ItemInstance* inst = nullptr;
|
||||
int16 invslot = 0;
|
||||
if (GetCharSelInventory(account_id, p_character_select_entry_struct->Name, &inventory_profile)) {
|
||||
const EQEmu::ItemData *item = nullptr;
|
||||
const EQEmu::ItemInstance *inst = nullptr;
|
||||
int16 inventory_slot = 0;
|
||||
|
||||
for (uint32 matslot = EQEmu::textures::textureBegin; matslot < EQEmu::textures::materialCount; matslot++) {
|
||||
invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(matslot);
|
||||
if (invslot == INVALID_INDEX) { continue; }
|
||||
inst = inv.GetItem(invslot);
|
||||
if (inst == nullptr) { continue; }
|
||||
inventory_slot = EQEmu::InventoryProfile::CalcSlotFromMaterial(matslot);
|
||||
if (inventory_slot == INVALID_INDEX) { continue; }
|
||||
inst = inventory_profile.GetItem(inventory_slot);
|
||||
if (inst == nullptr) {
|
||||
continue;
|
||||
}
|
||||
item = inst->GetItem();
|
||||
if (item == nullptr) { continue; }
|
||||
if (item == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matslot > 6) {
|
||||
uint32 idfile = 0;
|
||||
uint32 item_id_file = 0;
|
||||
// Weapon Models
|
||||
if (inst->GetOrnamentationIDFile() != 0) {
|
||||
idfile = inst->GetOrnamentationIDFile();
|
||||
cse->Equip[matslot].Material = idfile;
|
||||
item_id_file = inst->GetOrnamentationIDFile();
|
||||
p_character_select_entry_struct->Equip[matslot].Material = item_id_file;
|
||||
}
|
||||
else {
|
||||
if (strlen(item->IDFile) > 2) {
|
||||
idfile = atoi(&item->IDFile[2]);
|
||||
cse->Equip[matslot].Material = idfile;
|
||||
item_id_file = atoi(&item->IDFile[2]);
|
||||
p_character_select_entry_struct->Equip[matslot].Material = item_id_file;
|
||||
}
|
||||
}
|
||||
if (matslot == EQEmu::textures::weaponPrimary) {
|
||||
cse->PrimaryIDFile = idfile;
|
||||
p_character_select_entry_struct->PrimaryIDFile = item_id_file;
|
||||
}
|
||||
else {
|
||||
cse->SecondaryIDFile = idfile;
|
||||
p_character_select_entry_struct->SecondaryIDFile = item_id_file;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32 color = 0;
|
||||
if (pp.item_tint.Slot[matslot].UseTint) {
|
||||
color = pp.item_tint.Slot[matslot].Color;
|
||||
if (player_profile_struct.item_tint.Slot[matslot].UseTint) {
|
||||
color = player_profile_struct.item_tint.Slot[matslot].Color;
|
||||
}
|
||||
else {
|
||||
color = inst->GetColor();
|
||||
}
|
||||
|
||||
// Armor Materials/Models
|
||||
cse->Equip[matslot].Material = item->Material;
|
||||
cse->Equip[matslot].EliteModel = item->EliteMaterial;
|
||||
cse->Equip[matslot].HerosForgeModel = inst->GetOrnamentHeroModel(matslot);
|
||||
cse->Equip[matslot].Color = color;
|
||||
p_character_select_entry_struct->Equip[matslot].Material = item->Material;
|
||||
p_character_select_entry_struct->Equip[matslot].EliteModel = item->EliteMaterial;
|
||||
p_character_select_entry_struct->Equip[matslot].HerosForgeModel = inst->GetOrnamentHeroModel(matslot);
|
||||
p_character_select_entry_struct->Equip[matslot].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Error loading inventory for %s\n", cse->Name);
|
||||
printf("Error loading inventory for %s\n", p_character_select_entry_struct->Name);
|
||||
}
|
||||
/* Load Inventory End */
|
||||
|
||||
buff_ptr += sizeof(CharacterSelectEntry_Struct);
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ struct CharacterSelect_Struct;
|
||||
class WorldDatabase : public SharedDatabase {
|
||||
public:
|
||||
bool GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc, bool isTitanium);
|
||||
void GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit);
|
||||
void GetCharSelectInfo(uint32 account_id, EQApplicationPacket **out_app, uint32 client_version_bit);
|
||||
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
|
||||
|
||||
void GetLauncherList(std::vector<std::string> &result);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user