Compare commits

..

6 Commits

Author SHA1 Message Date
Xackery cd01ed87df Added missed pet summons 2021-11-23 18:16:22 -08:00
Xackery 8a79994b4e Added more elixir error constants 2021-11-18 09:51:55 -08:00
Xackery 93a661a434 Removed debug line 2021-11-16 17:19:37 -08:00
Xackery 3e8796bb4c Added ElixirSpellCache, #elixircheck 2021-11-16 17:03:42 -08:00
Xackery c23fc4ade7 Added Elixir 2021-11-15 20:55:40 -08:00
Xackery 3b628c1ace Added tweaks to dev containers 2021-11-15 20:54:28 -08:00
1313 changed files with 140254 additions and 176789 deletions
+21
View File
@@ -0,0 +1,21 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.101.1/containers/ubuntu-18.04-git
{
"name": "Ubuntu 18.04 EQEMU",
// Moved from dockerfile to image so it builds faster
"image": "eqemu/devcontainer:0.0.2",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
// Add the IDs of extensions you want installed when the container is created.
"extensions": ["ms-vscode.cpptools", "ms-azuretools.vscode-docker"],
"mounts": ["source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"],
"remoteEnv": {
"HOST_PROJECT_PATH": "${localWorkspaceFolder}"
}
}
+6 -94
View File
@@ -1,104 +1,16 @@
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: Build Linux name: EQEmulator Server Linux CI
clone:
depth: 1
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores # Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency: concurrency:
limit: 1 limit: 1
volumes:
- name: cache
host:
path: /var/lib/cache-release
steps: steps:
- name: Build Linux X64 - name: server-build
image: akkadius/eqemu-server:v11 # Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20
environment: image: akkadius/eqemu-server:latest
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
commands: commands:
- ./utils/scripts/build/linux-build.sh - sudo chown eqemu:eqemu /drone/src/ * -R
volumes: - git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
- name: cache
path: /home/eqemu/.ccache/
---
kind: pipeline
type: exec
name: Build Windows
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency:
limit: 1
clone:
depth: 1
platform:
os: windows
arch: amd64
steps:
- name: Build Windows X64
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- .\utils\scripts\build\windows-build.ps1
---
kind: pipeline
type: docker
name: Publish Artifacts to Github
steps:
- name: Upload Artifacts
image: akkadius/eqemu-build-releaser:v3
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GH_RELEASE_GITHUB_API_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- ./utils/scripts/build/should-release/should-release
- rclone config create remote ftp env_auth true > /dev/null
- |
rclone copy remote: --include "eqemu-server*.zip" .
- gh-release --assets=eqemu-server-linux-x64.zip,eqemu-server-windows-x64.zip -y
- |
rclone delete remote: --include "eqemu-server*.zip"
trigger:
branch:
- master
event:
- push
depends_on:
- Build Windows
- Build Linux
-14
View File
@@ -54,17 +54,3 @@ bin/
/Win32 /Win32
/x64 /x64
/client_files/**/CMakeFiles/ /client_files/**/CMakeFiles/
.idea
# Clangd Generated Files.
compile_flags.txt
.cache/
# vscode generated settings
.vscode/
# Build pipeline
!utils/scripts/build/
!utils/scripts/build/should-release/should-release
!utils/scripts/build/should-release/should-release.exe
+19
View File
@@ -0,0 +1,19 @@
language: cpp
compiler: gcc
dist: bionic
addons:
apt:
packages:
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
- uuid-dev
- libssl-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
- make -j2
- ./bin/tests
+17
View File
@@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/mysql"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++17",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
+8
View File
@@ -0,0 +1,8 @@
{
"files.associations": {
"chrono": "cpp",
"xutility": "cpp",
"iterator": "cpp",
"*.ipp": "cpp"
}
}
+164
View File
@@ -0,0 +1,164 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "make",
"type": "shell",
"command": "mkdir -p build && cd build && make",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "make clean",
"type": "shell",
"command": "mkdir -p build && 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 && 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 && 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 && 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 && 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 assets && ./eqemu_server.pl lua_modules && ./eqemu_server.pl opcodes && ./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 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
}
},
{
"label": "ucs",
"type": "shell",
"command": "docker stop ucs | true && cd bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src -p 7778:7778 --name ucs --network=eqemu eqemu/server:0.0.3 gdb -ex run ./ucs",
"group": {
"kind": "test",
"isDefault": true
}
}
]
}
+2 -2
View File
@@ -40,14 +40,14 @@ Assuming it is starting in c:/projects/eqemu and the x64 dependencies were extra
mkdir build mkdir build
cd build cd build
cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" .. cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DEQEMU_ENABLE_BOTS=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" ..
##### Linux ##### Linux
Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator. Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator.
mkdir build mkdir build
cd build cd build
cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON .. cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON ..
### Building ### Building
-646
View File
@@ -1,646 +0,0 @@
## [22.1.2] - 01/24/2023
### CI/CD
* Build / Release Pipeline Changes ([#2788](https://github.com/EQEmu/Server/pull/2788)) ([Akkadius](https://github.com/Akkadius)) 2023-01-24
### Code Cleanup
* Cleanup #door Command. ([#2783](https://github.com/EQEmu/Server/pull/2783)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24
### Crash
* Fix rarer world crash issue where scheduler database was not available ([#2789](https://github.com/EQEmu/Server/pull/2789)) ([Akkadius](https://github.com/Akkadius)) 2023-01-24
### Fixes
* Fix nullptr spell in BCSpells::Load() ([#2790](https://github.com/EQEmu/Server/pull/2790)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24
* Remove duplicate logic in GetActSpellHealing reducing HOT criticals ([#2786](https://github.com/EQEmu/Server/pull/2786)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24
## [22.1.1] - 01/23/2023
### Fixes
* Fix botgrouplist to display unique entries. ([#2785](https://github.com/EQEmu/Server/pull/2785)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
* Fix scenario where dereferenced object could be null. ([#2784](https://github.com/EQEmu/Server/pull/2784)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
## [22.1.0] - 01/22/2023
This is a first release using the new build system. Changelog entry representative of last year. Subsequent releases will consist of incremental changes since the last release.
### AA
* Fix AA tables dump ([#2769](https://github.com/EQEmu/Server/pull/2769)) ([Akkadius](https://github.com/Akkadius)) 2023-01-22
### Appveyor
* Remove bots preprocessor ([Akkadius](https://github.com/Akkadius)) 2023-01-20
### Bot/Merc
* Cleanup methods, and virtual overrides. ([#2734](https://github.com/EQEmu/Server/pull/2734)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15
### Bots
* Add Bot Command Reloading ([#2773](https://github.com/EQEmu/Server/pull/2773)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Add Bot-specific Spell Settings. ([#2553](https://github.com/EQEmu/Server/pull/2553)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Add Buff support for Bards under AI_IdleCastChecks ([#2590](https://github.com/EQEmu/Server/pull/2590)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-28
* Add Data Bucket support to Bot Spell Entries. ([#2505](https://github.com/EQEmu/Server/pull/2505)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-06
* Add EVENT_TRADE Support to Bots. ([#2560](https://github.com/EQEmu/Server/pull/2560)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25
* Add Event_Trade Support for ^inventorygive Command ([#2628](https://github.com/EQEmu/Server/pull/2628)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-11
* Add Expansion Bitmask Quest APIs. ([#2523](https://github.com/EQEmu/Server/pull/2523)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add GetBotOwnerByBotID Method ([#2715](https://github.com/EQEmu/Server/pull/2715)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-11
* Add Melee Support for Casting, Cleanup Bot Casting Logic ([#2571](https://github.com/EQEmu/Server/pull/2571)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25
* Add Quest API Methods ([#2631](https://github.com/EQEmu/Server/pull/2631)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-12
* Add Quest API Support for Limits. ([#2522](https://github.com/EQEmu/Server/pull/2522)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Add Rule Allowing Bots to Equip Any Race Items ([#2578](https://github.com/EQEmu/Server/pull/2578)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-26
* Add Support for AA bonuses that were missing. ([#2764](https://github.com/EQEmu/Server/pull/2764)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20
* Add Support for Bots to receive Auras, and other AoE Buffs. ([#2586](https://github.com/EQEmu/Server/pull/2586)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27
* Add Virtual Override for Bot::Attack ([#2771](https://github.com/EQEmu/Server/pull/2771)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20
* Add give/remove saylinks to ^itemuse. ([#2503](https://github.com/EQEmu/Server/pull/2503)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Add support for Bot scripting. ([#2515](https://github.com/EQEmu/Server/pull/2515)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Apply Spells:IgnoreSpellDmgLvlRestriction to bots ([#2024](https://github.com/EQEmu/Server/pull/2024)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07
* Bot::PerformTradeWithClient Cleanup. ([#2084](https://github.com/EQEmu/Server/pull/2084)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-01
* Cleanup Bot Spell Functions, reduce reliance on NPC Functions/Attributes ([#2495](https://github.com/EQEmu/Server/pull/2495)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-29
* Cleanup Fast Rest Regen ([#2626](https://github.com/EQEmu/Server/pull/2626)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-07
* Cleanup Say Event Parse. ([#2557](https://github.com/EQEmu/Server/pull/2557)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20
* Cleanup Spell Settings Commands ([#2607](https://github.com/EQEmu/Server/pull/2607)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Cleanup ^inventoryremove, ^inventorylist, and ^list Commands and bot groups. ([#2273](https://github.com/EQEmu/Server/pull/2273)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-03
* Cleanup and remove preprocessors. ([#2757](https://github.com/EQEmu/Server/pull/2757)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-20
* Cleanup various Bot Spell Focus methods ([#2649](https://github.com/EQEmu/Server/pull/2649)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-16
* Convert Load, Save, SaveNew, and Delete to Repositories. ([#2614](https://github.com/EQEmu/Server/pull/2614)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Expanded Bot Spell Settings List. ([#2606](https://github.com/EQEmu/Server/pull/2606)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-03
* Fix Bot Spell Type "In Combat Buffs" ([#2711](https://github.com/EQEmu/Server/pull/2711)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-08
* Fix Gender not saving as GetBaseGender on BotSave ([#2639](https://github.com/EQEmu/Server/pull/2639)) ([nytmyr](https://github.com/nytmyr)) 2022-12-13
* Fix Slow Query in QueryNameAvailablity ([#2781](https://github.com/EQEmu/Server/pull/2781)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-22
* Fix ^dyearmor command math. ([#2081](https://github.com/EQEmu/Server/pull/2081)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30
* Fix bot spawn when bot id = char_id ([#1984](https://github.com/EQEmu/Server/pull/1984)) ([neckkola](https://github.com/neckkola)) 2022-03-07
* Hotfix for possible crash. ([#2539](https://github.com/EQEmu/Server/pull/2539)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Melee Bot Support for Spell Settings Commands ([#2599](https://github.com/EQEmu/Server/pull/2599)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-01
* Move Bot Spell Loading process to constructor from calcbotstats() ([#2583](https://github.com/EQEmu/Server/pull/2583)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27
* Optimize inventory loading. ([#2588](https://github.com/EQEmu/Server/pull/2588)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-28
* Post pre-processor fixes ([#2770](https://github.com/EQEmu/Server/pull/2770)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Resolve incorrect values on Bot Creation ([#2644](https://github.com/EQEmu/Server/pull/2644)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-14
* Restrict Bot Groups from spawning while Feigned. ([#2761](https://github.com/EQEmu/Server/pull/2761)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-19
* Save Bot Toggle Archer Setting between Loads. ([#2612](https://github.com/EQEmu/Server/pull/2612)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Update Bot Heal & Damage methods to more closely match Clients + Bugfixes ([#2045](https://github.com/EQEmu/Server/pull/2045)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-11
* Update Bot Logic to ignore ST_TargetsTarget when buffing ([#2584](https://github.com/EQEmu/Server/pull/2584)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27
### C++20
* Arithmetic on different enums is deprecated ([#2752](https://github.com/EQEmu/Server/pull/2752)) ([mackal](https://github.com/mackal)) 2023-01-17
* Enable C++20 + Fixes + FMT 9.1 ([#2664](https://github.com/EQEmu/Server/pull/2664)) ([Akkadius](https://github.com/Akkadius)) 2022-12-21
### Code
* Removed vscode setting ([#2753](https://github.com/EQEmu/Server/pull/2753)) ([xackery](https://github.com/xackery)) 2023-01-17
### Code Cleanup
* Add Validation to varchar number item fields. ([#2241](https://github.com/EQEmu/Server/pull/2241)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Cleanup #kick message. ([#2164](https://github.com/EQEmu/Server/pull/2164)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10
* Cleanup Haste references and Lua API calls for unsigned to signed. ([#2240](https://github.com/EQEmu/Server/pull/2240)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Cleanup code smells and compiler warnings in common/shareddb ([#2270](https://github.com/EQEmu/Server/pull/2270)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Cleanup magic numbers ([#2662](https://github.com/EQEmu/Server/pull/2662)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-20
* Cleanup spell and max level bucket logic. ([#2181](https://github.com/EQEmu/Server/pull/2181)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28
* Extra Space in NPC::AISpellsList(). ([#2555](https://github.com/EQEmu/Server/pull/2555)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20
* Fix unintended copies in zone/zonedb.cpp by changing auto to auto& ([#2271](https://github.com/EQEmu/Server/pull/2271)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Make use of std::abs where possible. ([#2739](https://github.com/EQEmu/Server/pull/2739)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Merge Client::Attack and Bot::Attack into Mob::Attack ([#2756](https://github.com/EQEmu/Server/pull/2756)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20
* Move Client::Undye() to client.cpp from #path Command. ([#2188](https://github.com/EQEmu/Server/pull/2188)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-21
* Possible issues with variable/parameter name equality. ([#2161](https://github.com/EQEmu/Server/pull/2161)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10
* Quest API push methods using invalid types. ([#2172](https://github.com/EQEmu/Server/pull/2172)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-16
* Remove Unused EQEMU_DEPOP_INVALIDATES_CACHE ([#2292](https://github.com/EQEmu/Server/pull/2292)) ([Akkadius](https://github.com/Akkadius)) 2022-07-14
* Remove this-> in code where its implied ([#2088](https://github.com/EQEmu/Server/pull/2088)) ([Akkadius](https://github.com/Akkadius)) 2022-05-01
* Remove unused basic_functions.h ([#2729](https://github.com/EQEmu/Server/pull/2729)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13
* Remove unused maxskill.h. ([#2728](https://github.com/EQEmu/Server/pull/2728)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13
* Remove unused methods. ([#2171](https://github.com/EQEmu/Server/pull/2171)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-15
* Remove unusued Max Item ID Constant ([#2528](https://github.com/EQEmu/Server/pull/2528)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-08
* Remove use of bzero since it is deprecated for memset ([#2295](https://github.com/EQEmu/Server/pull/2295)) ([Akkadius](https://github.com/Akkadius)) 2022-07-14
* Resharper Warnings ([#2235](https://github.com/EQEmu/Server/pull/2235)) ([Quintinon](https://github.com/Quintinon)) 2022-06-01
* Resolve some warnings in loginserver/world_server.cpp ([#2347](https://github.com/EQEmu/Server/pull/2347)) ([mackal](https://github.com/mackal)) 2022-07-31
* Rework Lua QuestReward to not use try/catch blocks ([#2417](https://github.com/EQEmu/Server/pull/2417)) ([mackal](https://github.com/mackal)) 2022-09-03
* Send eqstr message in AddAAPoints ([#2507](https://github.com/EQEmu/Server/pull/2507)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Update to EQEmu #2253 to clean up message strings ([#2279](https://github.com/EQEmu/Server/pull/2279)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03
* Zone Data Loading Refactor ([#2388](https://github.com/EQEmu/Server/pull/2388)) ([Akkadius](https://github.com/Akkadius)) 2022-09-01
### Commands
* #bind Typo. ([#2196](https://github.com/EQEmu/Server/pull/2196)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* #ginfo Cleanup. ([#1955](https://github.com/EQEmu/Server/pull/1955)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-03
* #reload Command Overhaul. ([#2162](https://github.com/EQEmu/Server/pull/2162)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10
* #reload level_mods could cause Non-Booted zones to crash. ([#2670](https://github.com/EQEmu/Server/pull/2670)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-24
* Add #bugs Command. ([#2559](https://github.com/EQEmu/Server/pull/2559)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add #feature Command. ([#2142](https://github.com/EQEmu/Server/pull/2142)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Add #findcharacter Command. ([#2692](https://github.com/EQEmu/Server/pull/2692)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03
* Add #findrecipe and #viewrecipe Commands. ([#2401](https://github.com/EQEmu/Server/pull/2401)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-31
* Add #setanon Command ([#2690](https://github.com/EQEmu/Server/pull/2690)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03
* Add #suspendmulti Command. ([#2619](https://github.com/EQEmu/Server/pull/2619)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Add BestZ and Region Data to #loc ([#2245](https://github.com/EQEmu/Server/pull/2245)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-05
* Add additional #peqzone functionality. ([#2085](https://github.com/EQEmu/Server/pull/2085)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-01
* Add max_hp back to #modifynpcstat command. ([#2638](https://github.com/EQEmu/Server/pull/2638)) ([nytmyr](https://github.com/nytmyr)) 2022-12-13
* Adding movespeed to #showstats output ([#2596](https://github.com/EQEmu/Server/pull/2596)) ([fryguy503](https://github.com/fryguy503)) 2022-11-30
* Bug fix for #logs command. ([#2008](https://github.com/EQEmu/Server/pull/2008)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-17
* Cleanup #ai Command. ([#1980](https://github.com/EQEmu/Server/pull/1980)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-11
* Cleanup #appearanceeffects Command. ([#2777](https://github.com/EQEmu/Server/pull/2777)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Cleanup #attack Command. ([#2103](https://github.com/EQEmu/Server/pull/2103)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Cleanup #ban, #ipban, #flag, #kick, #setlsinfo, and #setpass Commands. ([#2104](https://github.com/EQEmu/Server/pull/2104)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Cleanup #chat Command. ([#2581](https://github.com/EQEmu/Server/pull/2581)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Cleanup #corpsefix Command. ([#2197](https://github.com/EQEmu/Server/pull/2197)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #cvs Command. ([#2153](https://github.com/EQEmu/Server/pull/2153)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Cleanup #date Command. ([#2228](https://github.com/EQEmu/Server/pull/2228)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01
* Cleanup #dbspawn2 Command. ([#2493](https://github.com/EQEmu/Server/pull/2493)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Cleanup #delacct Command. ([#2567](https://github.com/EQEmu/Server/pull/2567)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #depop Command. ([#2536](https://github.com/EQEmu/Server/pull/2536)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #depopzone Command. ([#2537](https://github.com/EQEmu/Server/pull/2537)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #devtools Command. ([#2538](https://github.com/EQEmu/Server/pull/2538)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #doanim Command. ([#2540](https://github.com/EQEmu/Server/pull/2540)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #emote Command. ([#2535](https://github.com/EQEmu/Server/pull/2535)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #emotesearch and #emoteview Command. ([#2494](https://github.com/EQEmu/Server/pull/2494)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Cleanup #emptyinventory Command. ([#2219](https://github.com/EQEmu/Server/pull/2219)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-29
* Cleanup #findaliases and #help Commands. ([#2204](https://github.com/EQEmu/Server/pull/2204)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #findclass and #findrace Commands. ([#2211](https://github.com/EQEmu/Server/pull/2211)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #flagedit Command. ([#1968](https://github.com/EQEmu/Server/pull/1968)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #freeze and #unfreeze Commands. ([#2102](https://github.com/EQEmu/Server/pull/2102)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Cleanup #gassign Command. ([#2101](https://github.com/EQEmu/Server/pull/2101)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #gearup Command. ([#2589](https://github.com/EQEmu/Server/pull/2589)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Cleanup #getvariable Command. ([#2100](https://github.com/EQEmu/Server/pull/2100)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Cleanup #guild Command ([#2693](https://github.com/EQEmu/Server/pull/2693)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-04
* Cleanup #hatelist Command. ([#1976](https://github.com/EQEmu/Server/pull/1976)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #heromodel Command. ([#2566](https://github.com/EQEmu/Server/pull/2566)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #kill Command. ([#2195](https://github.com/EQEmu/Server/pull/2195)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Cleanup #level Command. ([#2203](https://github.com/EQEmu/Server/pull/2203)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #logs Command. ([#1969](https://github.com/EQEmu/Server/pull/1969)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #makepet Command. ([#2105](https://github.com/EQEmu/Server/pull/2105)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #modifynpcstat Command. ([#2499](https://github.com/EQEmu/Server/pull/2499)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30
* Cleanup #motd Command. ([#2190](https://github.com/EQEmu/Server/pull/2190)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Cleanup #name Command. ([#1977](https://github.com/EQEmu/Server/pull/1977)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #netstats Command. ([#1970](https://github.com/EQEmu/Server/pull/1970)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #npcedit Command. ([#2582](https://github.com/EQEmu/Server/pull/2582)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Cleanup #npcedit, #lastname, #title, and #titlesuffix Commands. ([#2215](https://github.com/EQEmu/Server/pull/2215)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28
* Cleanup #npceditmass command. ([#1957](https://github.com/EQEmu/Server/pull/1957)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-03
* Cleanup #npcemote Command. ([#2106](https://github.com/EQEmu/Server/pull/2106)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npcloot Command. ([#1974](https://github.com/EQEmu/Server/pull/1974)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-11
* Cleanup #npcsay and #npcshout Commands. ([#2107](https://github.com/EQEmu/Server/pull/2107)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npcspecialattk Command. ([#2108](https://github.com/EQEmu/Server/pull/2108)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npctype_cache Command. ([#2109](https://github.com/EQEmu/Server/pull/2109)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #npctypespawn Command. ([#2110](https://github.com/EQEmu/Server/pull/2110)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #nudge Command. ([#2220](https://github.com/EQEmu/Server/pull/2220)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-29
* Cleanup #oocmute Command. ([#2191](https://github.com/EQEmu/Server/pull/2191)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Cleanup #opcode Command. ([#2547](https://github.com/EQEmu/Server/pull/2547)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Cleanup #profanity Command. ([#2113](https://github.com/EQEmu/Server/pull/2113)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #push Command. ([#2114](https://github.com/EQEmu/Server/pull/2114)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #qglobal Command. ([#2115](https://github.com/EQEmu/Server/pull/2115)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #randomizefeatures Command. ([#2118](https://github.com/EQEmu/Server/pull/2118)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #refreshgroup Command. ([#2119](https://github.com/EQEmu/Server/pull/2119)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadaa Command. ([#2120](https://github.com/EQEmu/Server/pull/2120)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadallrules Command. ([#2121](https://github.com/EQEmu/Server/pull/2121)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadlevelmods Command. ([#2122](https://github.com/EQEmu/Server/pull/2122)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadmerchants Command. ([#2123](https://github.com/EQEmu/Server/pull/2123)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadperlexportsettings Command. ([#2124](https://github.com/EQEmu/Server/pull/2124)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadrulesworld Command. ([#2128](https://github.com/EQEmu/Server/pull/2128)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadstatic Command. ([#2130](https://github.com/EQEmu/Server/pull/2130)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadtitles Command. ([#2125](https://github.com/EQEmu/Server/pull/2125)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadtraps Command. ([#2126](https://github.com/EQEmu/Server/pull/2126)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadworld and #repop Command. ([#2127](https://github.com/EQEmu/Server/pull/2127)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #reloadzps Command. ([#2129](https://github.com/EQEmu/Server/pull/2129)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #resetaa Command. ([#2132](https://github.com/EQEmu/Server/pull/2132)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #resetaa_timer Command. ([#2131](https://github.com/EQEmu/Server/pull/2131)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #resetdisc_timer Command. ([#2133](https://github.com/EQEmu/Server/pull/2133)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #revoke Command. ([#2134](https://github.com/EQEmu/Server/pull/2134)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #roambox Command. ([#2135](https://github.com/EQEmu/Server/pull/2135)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #rules Command. ([#2593](https://github.com/EQEmu/Server/pull/2593)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-10
* Cleanup #save Command. ([#2136](https://github.com/EQEmu/Server/pull/2136)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #scale Command. ([#2591](https://github.com/EQEmu/Server/pull/2591)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-05
* Cleanup #scribespell and #scribespells Commands. ([#2534](https://github.com/EQEmu/Server/pull/2534)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Cleanup #sensetrap Command. ([#2137](https://github.com/EQEmu/Server/pull/2137)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #serverinfo Command. ([#2568](https://github.com/EQEmu/Server/pull/2568)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #serverrules Command. ([#2139](https://github.com/EQEmu/Server/pull/2139)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #setlanguage Command. ([#2464](https://github.com/EQEmu/Server/pull/2464)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-13
* Cleanup #setskillall Command. ([#1992](https://github.com/EQEmu/Server/pull/1992)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-15
* Cleanup #shownpcgloballoot and #showzonegloballoot Command. ([#2141](https://github.com/EQEmu/Server/pull/2141)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #showskills Command. ([#1994](https://github.com/EQEmu/Server/pull/1994)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-15
* Cleanup #spawneditmass Command. ([#2229](https://github.com/EQEmu/Server/pull/2229)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Cleanup #spawnfix Command. ([#2143](https://github.com/EQEmu/Server/pull/2143)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #spawnstatus Command. ([#2144](https://github.com/EQEmu/Server/pull/2144)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #summon Command. ([#2145](https://github.com/EQEmu/Server/pull/2145)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06
* Cleanup #summonburiedplayercorpse Command. ([#2146](https://github.com/EQEmu/Server/pull/2146)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #suspend Command. ([#2564](https://github.com/EQEmu/Server/pull/2564)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #task Command. ([#2071](https://github.com/EQEmu/Server/pull/2071)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-14
* Cleanup #time and #timezone Command. ([#2147](https://github.com/EQEmu/Server/pull/2147)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #timers Command. ([#2562](https://github.com/EQEmu/Server/pull/2562)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Cleanup #trapinfo Command. ([#2148](https://github.com/EQEmu/Server/pull/2148)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #ucs Command. ([#2149](https://github.com/EQEmu/Server/pull/2149)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Cleanup #undye and #undyeme Commands. ([#1966](https://github.com/EQEmu/Server/pull/1966)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #unscribespell Command. ([#1998](https://github.com/EQEmu/Server/pull/1998)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-16
* Cleanup #untraindisc Command. ([#1996](https://github.com/EQEmu/Server/pull/1996)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-16
* Cleanup #version Command. ([#1967](https://github.com/EQEmu/Server/pull/1967)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Cleanup #worldwide command. ([#2021](https://github.com/EQEmu/Server/pull/2021)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-01
* Cleanup #xtargets Command. ([#2545](https://github.com/EQEmu/Server/pull/2545)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Cleanup #zone and #zoneinstance Commands. ([#2202](https://github.com/EQEmu/Server/pull/2202)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Command Status Reload and Helper Method ([#2377](https://github.com/EQEmu/Server/pull/2377)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20
* Consolidate #lock and #unlock Commands into #serverlock. ([#2193](https://github.com/EQEmu/Server/pull/2193)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Fix #copycharacter command crash ([#2446](https://github.com/EQEmu/Server/pull/2446)) ([Akkadius](https://github.com/Akkadius)) 2022-09-25
* Fix #killallnpcs from crashing ([#2037](https://github.com/EQEmu/Server/pull/2037)) ([Akkadius](https://github.com/Akkadius)) 2022-03-07
* Fix Flymode Command Help Prompt ([#2669](https://github.com/EQEmu/Server/pull/2669)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-23
* Fix typos in #ban and #ipban Commands. ([#2209](https://github.com/EQEmu/Server/pull/2209)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-26
* Make #damage require a target ([#2426](https://github.com/EQEmu/Server/pull/2426)) ([hgtw](https://github.com/hgtw)) 2022-09-05
* Nested Command Aliases ([#2636](https://github.com/EQEmu/Server/pull/2636)) ([Akkadius](https://github.com/Akkadius)) 2022-12-15
* Remove #guildapprove, #guildcreate, and #guildlist Commands ([#2775](https://github.com/EQEmu/Server/pull/2775)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Remove #iteminfo Command. ([#2565](https://github.com/EQEmu/Server/pull/2565)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Remove #profiledump and #profilereset Commands. ([#2546](https://github.com/EQEmu/Server/pull/2546)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Remove #undyeme Command. ([#2776](https://github.com/EQEmu/Server/pull/2776)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Remove unused #bestz and #pf Commands. ([#2112](https://github.com/EQEmu/Server/pull/2112)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Remove unused/broken #deletegraveyard and #setgraveyard Commands. ([#2198](https://github.com/EQEmu/Server/pull/2198)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
### Diawind
* Plus sign markdown fix ([#2727](https://github.com/EQEmu/Server/pull/2727)) ([Akkadius](https://github.com/Akkadius)) 2023-01-12
### Feature
* AA Cap Limit ([#2423](https://github.com/EQEmu/Server/pull/2423)) ([fryguy503](https://github.com/fryguy503)) 2022-10-13
* Add "Keeps Sold Items" Flag to NPCs ([#2671](https://github.com/EQEmu/Server/pull/2671)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25
* Add Experience Gain Toggle. ([#2676](https://github.com/EQEmu/Server/pull/2676)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-30
* Add Guild Chat to Console. ([#2387](https://github.com/EQEmu/Server/pull/2387)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22
* Add Hate Override for Heals ([#2485](https://github.com/EQEmu/Server/pull/2485)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-14
* Add Rule to Disable Group EXP Modifier. ([#2741](https://github.com/EQEmu/Server/pull/2741)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Add Support for "Show Mine Only" Filters ([#2484](https://github.com/EQEmu/Server/pull/2484)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Add Type 49545 to Spell Resistrictions ([#2436](https://github.com/EQEmu/Server/pull/2436)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-20
* Add humanoid and non-wielded restrictions to pick pocket ([#2276](https://github.com/EQEmu/Server/pull/2276)) ([noudess](https://github.com/noudess)) 2022-07-03
* Add player /inspect quest event ([#2508](https://github.com/EQEmu/Server/pull/2508)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Add special ability to block /open ([#2506](https://github.com/EQEmu/Server/pull/2506)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Allow Focus Effects to be Filtered out. ([#2447](https://github.com/EQEmu/Server/pull/2447)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-25
* Allow pets to zone with permanent (buffdurationformula 50) buffs to maintain them through zone transitions ([#2035](https://github.com/EQEmu/Server/pull/2035)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07
* Bind Wound and Forage while mounted. ([#2257](https://github.com/EQEmu/Server/pull/2257)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03
* Change #scribespells to be aware of spellgroups & ranks ([#2501](https://github.com/EQEmu/Server/pull/2501)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-06
* Change GetSkillDmgAmt to int32 ([#2364](https://github.com/EQEmu/Server/pull/2364)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-10
* Change Lifetap Emotes to be filterable. ([#2454](https://github.com/EQEmu/Server/pull/2454)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-29
* Change Mana Costs to use Signed Int ([#2384](https://github.com/EQEmu/Server/pull/2384)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-21
* Change mana_used to int32 ([#2321](https://github.com/EQEmu/Server/pull/2321)) ([Aeadoin](https://github.com/Aeadoin)) 2022-07-30
* Client Checksum Verification (Resubmit old 1678) ([#1922](https://github.com/EQEmu/Server/pull/1922)) ([noudess](https://github.com/noudess)) 2022-03-07
* EQ2-style implied targeting for spells. ([#2032](https://github.com/EQEmu/Server/pull/2032)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07
* Faction Association ([#2408](https://github.com/EQEmu/Server/pull/2408)) ([mackal](https://github.com/mackal)) 2022-09-03
* GM State Change Persistance ([#2328](https://github.com/EQEmu/Server/pull/2328)) ([fryguy503](https://github.com/fryguy503)) 2022-07-31
* Implement Heroic Strikethrough to NPCs ([#2395](https://github.com/EQEmu/Server/pull/2395)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-31
* Implement OP_CashReward ([#2307](https://github.com/EQEmu/Server/pull/2307)) ([mackal](https://github.com/mackal)) 2022-07-15
* Instance Version Specific Experience Modifiers ([#2376](https://github.com/EQEmu/Server/pull/2376)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20
* NPCs with bows and arrows do ranged attacks ([#2322](https://github.com/EQEmu/Server/pull/2322)) ([mackal](https://github.com/mackal)) 2022-07-30
* Soft Delete Bots on Character Soft Delete ([#2467](https://github.com/EQEmu/Server/pull/2467)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Spell Ranks will now work with AllowSpellMemorizeFromItem Rule ([#2475](https://github.com/EQEmu/Server/pull/2475)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Update HateMod used by SPA 114 to Int32. ([#2428](https://github.com/EQEmu/Server/pull/2428)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-08
### Fixes
* #npcstats command displaying incorrect faction ([#2710](https://github.com/EQEmu/Server/pull/2710)) ([noudess](https://github.com/noudess)) 2023-01-08
* #peqzone no longer bypass Handle_OP_ZoneChange ([#2063](https://github.com/EQEmu/Server/pull/2063)) ([Natedog2012](https://github.com/Natedog2012)) 2022-03-19
* #scribespells triggered error on mysql keyword rank ([#2779](https://github.com/EQEmu/Server/pull/2779)) ([noudess](https://github.com/noudess)) 2023-01-21
* #tune command various fixes ([#2046](https://github.com/EQEmu/Server/pull/2046)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-11
* Add Complete Heal Spell back to IsCompleteHealSpell Method ([#2722](https://github.com/EQEmu/Server/pull/2722)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-11
* Add SE_MakeDrunk to avoid error message. ([#2601](https://github.com/EQEmu/Server/pull/2601)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Add omitted function call in UCS ([#2768](https://github.com/EQEmu/Server/pull/2768)) ([Valorith](https://github.com/Valorith)) 2023-01-20
* Add required distance to CoTH before aggro wipe ([#2253](https://github.com/EQEmu/Server/pull/2253)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03
* Adjustment for nullptr crash ([#2232](https://github.com/EQEmu/Server/pull/2232)) ([Akkadius](https://github.com/Akkadius)) 2022-06-01
* Alleviate some lag with crosszone/worldwide spell casting. ([#2016](https://github.com/EQEmu/Server/pull/2016)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-21
* Allow High Level Spells to be Unmemorized. ([#2641](https://github.com/EQEmu/Server/pull/2641)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14
* Allow Songs to be scribed from scrolls ([#2460](https://github.com/EQEmu/Server/pull/2460)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-12
* AltCurrencySelectItemReply_Struct was not handled correctly. ([#2702](https://github.com/EQEmu/Server/pull/2702)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-04
* Any use of TempName left old clean_name. ([#1946](https://github.com/EQEmu/Server/pull/1946)) ([noudess](https://github.com/noudess)) 2022-01-26
* Avoid erase in discord queue range loop ([#2411](https://github.com/EQEmu/Server/pull/2411)) ([hgtw](https://github.com/hgtw)) 2022-09-03
* Bandolier didn't recognize source weapon on cursor ([#2026](https://github.com/EQEmu/Server/pull/2026)) ([noudess](https://github.com/noudess)) 2022-03-07
* Bard Invisible causing display issues. ([#2067](https://github.com/EQEmu/Server/pull/2067)) ([KayenEQ](https://github.com/KayenEQ)) 2022-04-01
* Bard update fixes 1 ([#1982](https://github.com/EQEmu/Server/pull/1982)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-09
* Bazaar Search MYSQL Error ([#2252](https://github.com/EQEmu/Server/pull/2252)) ([fryguy503](https://github.com/fryguy503)) 2022-06-08
* Blocked spells max spell id increased ([#2207](https://github.com/EQEmu/Server/pull/2207)) ([Isaaru](https://github.com/Isaaru)) 2022-05-25
* Boats should never get FixZ'd ([#2246](https://github.com/EQEmu/Server/pull/2246)) ([noudess](https://github.com/noudess)) 2022-07-02
* Clamp Item Ldon Sell Back Rates. ([#2592](https://github.com/EQEmu/Server/pull/2592)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-30
* Clear title/suffix bug fix. ([#2068](https://github.com/EQEmu/Server/pull/2068)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-02
* Correct (probably) unintended bitwise AND instead of logical AND ([#2239](https://github.com/EQEmu/Server/pull/2239)) ([Quintinon](https://github.com/Quintinon)) 2022-06-02
* Correct type signed/unsigned int when reading item from database in shareddb ([#2269](https://github.com/EQEmu/Server/pull/2269)) ([Quintinon](https://github.com/Quintinon)) 2022-06-15
* Data Bucket Permanent Duration String ([#2624](https://github.com/EQEmu/Server/pull/2624)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Delete NpcType Struct returned by Bot::CreateDefaultNPCTypeStructForBot() when unused ([#2267](https://github.com/EQEmu/Server/pull/2267)) ([Quintinon](https://github.com/Quintinon)) 2022-06-18
* Do not allow /open to be used on traps or auras, causes crash ([#1951](https://github.com/EQEmu/Server/pull/1951)) ([KayenEQ](https://github.com/KayenEQ)) 2022-01-30
* Doors::GetSize() Perl Croak Typo. ([#2027](https://github.com/EQEmu/Server/pull/2027)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-04
* EVENT_ENTER_AREA/EVENT_LEAVE_AREA. ([#2698](https://github.com/EQEmu/Server/pull/2698)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02
* Edge case AA reset timer issue fixes ([#1995](https://github.com/EQEmu/Server/pull/1995)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-14
* Fix #door Save ([#2699](https://github.com/EQEmu/Server/pull/2699)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02
* Fix #findaa and GetAAName(). ([#2774](https://github.com/EQEmu/Server/pull/2774)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Fix #zone 0. ([#2691](https://github.com/EQEmu/Server/pull/2691)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Fix Aug Clicks where item has no click effect. ([#2725](https://github.com/EQEmu/Server/pull/2725)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-12
* Fix Bot "Failed to Load" Messages. ([#2719](https://github.com/EQEmu/Server/pull/2719)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-11
* Fix Bot Group Loading ([#2780](https://github.com/EQEmu/Server/pull/2780)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-22
* Fix Bot ^spellsettingsadd command ([#2603](https://github.com/EQEmu/Server/pull/2603)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-01
* Fix Duplicate Silent Saylink Messages ([#2386](https://github.com/EQEmu/Server/pull/2386)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22
* Fix EntityList::GetBotListByCharacterID() ([#2569](https://github.com/EQEmu/Server/pull/2569)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Fix Flag Updating with SetGMStatus() in Lua. ([#2554](https://github.com/EQEmu/Server/pull/2554)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20
* Fix Group XP not working. ([#2748](https://github.com/EQEmu/Server/pull/2748)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-17
* Fix HP Regen Per Second. ([#2206](https://github.com/EQEmu/Server/pull/2206)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-25
* Fix IDFile Crash with spaces or invalid data. ([#2597](https://github.com/EQEmu/Server/pull/2597)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Fix IP Exemptions. ([#2189](https://github.com/EQEmu/Server/pull/2189)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28
* Fix Instance Repository ([#2598](https://github.com/EQEmu/Server/pull/2598)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Fix Legacy Combat Lua Script ([#2226](https://github.com/EQEmu/Server/pull/2226)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-31
* Fix MovePC in #zone and #zoneinstance Commands. ([#2236](https://github.com/EQEmu/Server/pull/2236)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01
* Fix NPC Reference in EVENT_SPAWN ([#2712](https://github.com/EQEmu/Server/pull/2712)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-08
* Fix ST_TargetsTarget Spells with Restrictions ([#2746](https://github.com/EQEmu/Server/pull/2746)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15
* Fix Silent Saylinks Sending Message to Others. ([#2389](https://github.com/EQEmu/Server/pull/2389)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22
* Fix Spell Bucket and Spell Global Logic Checks. ([#2285](https://github.com/EQEmu/Server/pull/2285)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05
* Fix Spellinfo Command to work with SpellIDs above int16 ([#2437](https://github.com/EQEmu/Server/pull/2437)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-20
* Fix Strings::Money Missing Conditions. ([#2383](https://github.com/EQEmu/Server/pull/2383)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-21
* Fix Swarm Pet Flurry/Rampages Messages ([#2444](https://github.com/EQEmu/Server/pull/2444)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-25
* Fix bot compile locking client on server enter. ([#2210](https://github.com/EQEmu/Server/pull/2210)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-26
* Fix bot guild removal. ([#2194](https://github.com/EQEmu/Server/pull/2194)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Fix botgrouplist to display unique entries. ([#2785](https://github.com/EQEmu/Server/pull/2785)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
* Fix bots equipping augments. ([#2772](https://github.com/EQEmu/Server/pull/2772)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22
* Fix case-sensitivity in #suspend Command. ([#2613](https://github.com/EQEmu/Server/pull/2613)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-05
* Fix duplicate and missing messages due to innate in spells ([#2170](https://github.com/EQEmu/Server/pull/2170)) ([noudess](https://github.com/noudess)) 2022-05-20
* Fix empty spawned merchants ([#2275](https://github.com/EQEmu/Server/pull/2275)) ([hgtw](https://github.com/hgtw)) 2022-06-28
* Fix for Bot command casting ([#1990](https://github.com/EQEmu/Server/pull/1990)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-12
* Fix for PR1954 target restriction with npcpc_only_flag from groupbuffs ([#1986](https://github.com/EQEmu/Server/pull/1986)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-10
* Fix for being able to skill up on corspe. ([#2058](https://github.com/EQEmu/Server/pull/2058)) ([noudess](https://github.com/noudess)) 2022-03-19
* Fix for castspell command ([#2010](https://github.com/EQEmu/Server/pull/2010)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-18
* Fix issue where #advnpcspawn addspawn does not add spawn sometimes. ([#2247](https://github.com/EQEmu/Server/pull/2247)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-07
* Fix issue where you can set your title to titles you don't have. ([#1917](https://github.com/EQEmu/Server/pull/1917)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-01-30
* Fix issue with Bot::LoadAndSpawnAllZonedBots. ([#2733](https://github.com/EQEmu/Server/pull/2733)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Fix issue with mobs summoning PCs into ceilings ([#1921](https://github.com/EQEmu/Server/pull/1921)) ([noudess](https://github.com/noudess)) 2022-01-30
* Fix loading world shared task state ([#2398](https://github.com/EQEmu/Server/pull/2398)) ([hgtw](https://github.com/hgtw)) 2022-08-28
* Fix luamod GetExperienceForKill return value ([Cole-SoD](https://github.com/Cole-SoD)) 2023-01-12
* Fix memory leak in ucs ([#2409](https://github.com/EQEmu/Server/pull/2409)) ([hgtw](https://github.com/hgtw)) 2022-09-03
* Fix miscellaneous memory leaks related to EQApplicationPacket and it's pBuffer ([#2262](https://github.com/EQEmu/Server/pull/2262)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Fix null pointer crash on zones that have not booted a zone yet with #reload commands or anything that calls GetZoneDescription ([#2231](https://github.com/EQEmu/Server/pull/2231)) ([Akkadius](https://github.com/Akkadius)) 2022-06-01
* Fix possible crash in ProcessSpecialAbilities. ([#2630](https://github.com/EQEmu/Server/pull/2630)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Fix possible crash with zone name methods. ([#2055](https://github.com/EQEmu/Server/pull/2055)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-13
* Fix possible issue where variables have the same name. ([#2156](https://github.com/EQEmu/Server/pull/2156)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Fix quest::updatespawntimer() Perl croak. ([#1947](https://github.com/EQEmu/Server/pull/1947)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-01-26
* Fix recipient sound (vtell) on non-player races ([#2066](https://github.com/EQEmu/Server/pull/2066)) ([noudess](https://github.com/noudess)) 2022-04-02
* Fix scenario where dereferenced object could be null. ([#2784](https://github.com/EQEmu/Server/pull/2784)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23
* Fix stack leaks in Lua events #2254 ([hgtw](https://github.com/hgtw)) 2022-06-09
* Fix trading with bots when in an illusion. ([#2645](https://github.com/EQEmu/Server/pull/2645)) ([nytmyr](https://github.com/nytmyr)) 2022-12-15
* Fix two invalid data accesses in zone/client.cpp ([#2238](https://github.com/EQEmu/Server/pull/2238)) ([Quintinon](https://github.com/Quintinon)) 2022-06-07
* Fixed Spell Logic for Bot Nukes ([#2481](https://github.com/EQEmu/Server/pull/2481)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13
* Fixed message on promote/demote permissions check. ([#2700](https://github.com/EQEmu/Server/pull/2700)) ([Valorith](https://github.com/Valorith)) 2023-01-02
* Fixed several instances of incorrect comparision - & executes after == ([#2025](https://github.com/EQEmu/Server/pull/2025)) ([noudess](https://github.com/noudess)) 2022-03-07
* Force NPCs to respect special ability 24 and 50 when set on player pets ([#2059](https://github.com/EQEmu/Server/pull/2059)) ([Natedog2012](https://github.com/Natedog2012)) 2022-03-16
* Free return value of ZoneDatabase::LoadTraderItemWithCharges() ([#2264](https://github.com/EQEmu/Server/pull/2264)) ([Quintinon](https://github.com/Quintinon)) 2022-06-18
* Hacker_Str was causing sql errors - Non Escaped ([#2251](https://github.com/EQEmu/Server/pull/2251)) ([fryguy503](https://github.com/fryguy503)) 2022-06-08
* Handle memory leaks from return value of Client::GetTraderItems() ([#2266](https://github.com/EQEmu/Server/pull/2266)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03
* Handle_OP_AugmentItem could cause Zone crash ([#2750](https://github.com/EQEmu/Server/pull/2750)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-17
* HasPet() Zone Crashes ([#2744](https://github.com/EQEmu/Server/pull/2744)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15
* Illusions will now properly display armor to other clients when they zone in. ([#1958](https://github.com/EQEmu/Server/pull/1958)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-04
* Instrument Mods should not affect spells that change model size. ([#2072](https://github.com/EQEmu/Server/pull/2072)) ([KayenEQ](https://github.com/KayenEQ)) 2022-04-13
* Invisible will display as dropped now on air pets when they attack. ([#2042](https://github.com/EQEmu/Server/pull/2042)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-07
* IsDamage test for lifetap was not complete. ([#2213](https://github.com/EQEmu/Server/pull/2213)) ([noudess](https://github.com/noudess)) 2022-05-27
* Limit merchant temp item list to zone and instance ([#2346](https://github.com/EQEmu/Server/pull/2346)) ([mackal](https://github.com/mackal)) 2022-07-31
* Lua GetBlockNextSpell() no return. ([#2151](https://github.com/EQEmu/Server/pull/2151)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Make Perl TakeMoneyFromPP int64 ([#2158](https://github.com/EQEmu/Server/pull/2158)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08
* Missing break ([#2031](https://github.com/EQEmu/Server/pull/2031)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-04
* Move EVENT_SPAWN for adding NPCs back to original spot, also add NPCs… ([#2749](https://github.com/EQEmu/Server/pull/2749)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-17
* NPC Constructor was passing hp_regen_per_second out of order to Mob(). ([#2681](https://github.com/EQEmu/Server/pull/2681)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-29
* NPC::CountItem and Corpse::CountItem 0 Charge Item Fix. ([#1959](https://github.com/EQEmu/Server/pull/1959)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-04
* NPC::GetNPCStat has no default return. ([#2150](https://github.com/EQEmu/Server/pull/2150)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* NPCs were getting weapon proc added twice ([#2277](https://github.com/EQEmu/Server/pull/2277)) ([noudess](https://github.com/noudess)) 2022-07-07
* Objects::GetTiltX() and Objects::GetTiltY() Perl Croak Typos. ([#2028](https://github.com/EQEmu/Server/pull/2028)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-04
* PR 1982 ([#1985](https://github.com/EQEmu/Server/pull/1985)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-10
* PR 2032 would lock client on casting fail as written ([#2038](https://github.com/EQEmu/Server/pull/2038)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-07
* Remove StringUtilTest::EscapeStringMemoryTest ([#2310](https://github.com/EQEmu/Server/pull/2310)) ([mackal](https://github.com/mackal)) 2022-07-15
* Remove Unnecessary Attack Log ([#2643](https://github.com/EQEmu/Server/pull/2643)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14
* Remove unnecessary log messages. ([#2642](https://github.com/EQEmu/Server/pull/2642)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14
* Removed Lua Event Argument Dispatch. ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-01
* Resolve Warning due to Virtual Mob Method GetInv() ([#2650](https://github.com/EQEmu/Server/pull/2650)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-19
* Resolve XP Calculation Bug introduced w/ recent Rule addition ([#2703](https://github.com/EQEmu/Server/pull/2703)) ([Valorith](https://github.com/Valorith)) 2023-01-07
* Resolve logic error in Raid::QueueClients ([#2404](https://github.com/EQEmu/Server/pull/2404)) ([mackal](https://github.com/mackal)) 2022-09-01
* Resolve subroutine redefinition due to bot methods. ([#2117](https://github.com/EQEmu/Server/pull/2117)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Restore missing messages for lifetap and dmg spells. ([#2057](https://github.com/EQEmu/Server/pull/2057)) ([noudess](https://github.com/noudess)) 2022-04-14
* Shared Memory Faction Association Typo ([#2419](https://github.com/EQEmu/Server/pull/2419)) ([mackal](https://github.com/mackal)) 2022-09-03
* Spell Buckets/Globals SQL Escape. ([#2019](https://github.com/EQEmu/Server/pull/2019)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-26
* Spell Buckets/Globals did not allow string-based values. ([#2043](https://github.com/EQEmu/Server/pull/2043)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-09
* Stop skill ups on Charmed NPCs. ([#2249](https://github.com/EQEmu/Server/pull/2249)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-10
* Summon Companion causing pets to warps away. ([#1972](https://github.com/EQEmu/Server/pull/1972)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-08
* Touch Of Vinitras was ignoring pet DT rule ([#2469](https://github.com/EQEmu/Server/pull/2469)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-03
* Tradeskill Autocombine MinSkill ([#2260](https://github.com/EQEmu/Server/pull/2260)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10
* Tradeskill Item 0 Error ([#2256](https://github.com/EQEmu/Server/pull/2256)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10
* Zone Flags Regression ([#2760](https://github.com/EQEmu/Server/pull/2760)) ([Akkadius](https://github.com/Akkadius)) 2023-01-19
* checking casting_spell_slot before its defined is bad ([#2013](https://github.com/EQEmu/Server/pull/2013)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-20
* manifest for db version 9176 had incorrect field name ([#2062](https://github.com/EQEmu/Server/pull/2062)) ([noudess](https://github.com/noudess)) 2022-03-19
* quest::MovePCInstance() Arguments Fix. ([#2020](https://github.com/EQEmu/Server/pull/2020)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-27
### Hotfix
* Add Bazaar portal discs to SQL ([Akkadius](https://github.com/Akkadius)) 2022-09-05
* Add discord_webhooks to server tables ([Akkadius](https://github.com/Akkadius)) 2022-07-03
* Blocks are nested too deeply. ([#2689](https://github.com/EQEmu/Server/pull/2689)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Cleanup #questerrors Command. ([#2116](https://github.com/EQEmu/Server/pull/2116)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07
* Compiling fails on FMT 9.1 with Bots ([#2665](https://github.com/EQEmu/Server/pull/2665)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-21
* Correct database call to point to the content_db connection ([Akkadius](https://github.com/Akkadius)) 2022-06-12
* Corrected misnamed Database Query file for Experience Toggle ([#2683](https://github.com/EQEmu/Server/pull/2683)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-31
* Faction associations file naming / lock consistency ([Akkadius](https://github.com/Akkadius)) 2022-09-05
* Fix DB version merge ([Akkadius](https://github.com/Akkadius)) 2022-05-08
* Fix door click crash issue if destination zone doesn't exist ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Fix issue with Bot Loading with 0 Health causing buffs to be lost. ([#2552](https://github.com/EQEmu/Server/pull/2552)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-18
* Fix lua mod load path ([Akkadius](https://github.com/Akkadius)) 2022-09-29
* Fix merge issue ([Akkadius](https://github.com/Akkadius)) 2022-07-14
* Fix path load ordering for CLI commands ([Akkadius](https://github.com/Akkadius)) 2022-10-16
* Fix potential race for crash dumps (Linux) ([Akkadius](https://github.com/Akkadius)) 2022-07-31
* Fix regression caused by #2129 ([Akkadius](https://github.com/Akkadius)) 2022-05-09
* Flipped positive / negative values for legacy_combat.lua ([Akkadius](https://github.com/Akkadius)) 2022-06-09
* Force collation on conversion script ([Akkadius](https://github.com/Akkadius)) 2022-09-28
* Instances Repository Fix ([#2576](https://github.com/EQEmu/Server/pull/2576)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Login Server failing to compile on Windows. ([#2758](https://github.com/EQEmu/Server/pull/2758)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-19
* Lua Parser Needs Lua_ItemInst ([#2696](https://github.com/EQEmu/Server/pull/2696)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Make sure we have a proper split size before assuming we can split it ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Move discord_webhooks to state tables because we don't want webhooks being exported ([Akkadius](https://github.com/Akkadius)) 2022-07-03
* Possible windows compile fix ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* Possible windows compile fix take 2 ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* Remove appveyor fetch bots ([Akkadius](https://github.com/Akkadius)) 2023-01-21
* Remove expansion field from account for those who have it ([#2357](https://github.com/EQEmu/Server/pull/2357)) ([Akkadius](https://github.com/Akkadius)) 2022-08-01
* Resolve Zone Crashing when grouped with Bots. ([#2747](https://github.com/EQEmu/Server/pull/2747)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-16
* Resolve issue with Bot Casting after zoning. ([#2617](https://github.com/EQEmu/Server/pull/2617)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Return weather_type_map ([Akkadius](https://github.com/Akkadius)) 2022-10-14
* SQL Update ([Akkadius](https://github.com/Akkadius)) 2022-07-31
* Shared Memory Protection Fixes ([Akkadius](https://github.com/Akkadius)) 2022-07-27
* Windows compile fix take 3 (final) ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* fix manifest ([Akkadius](https://github.com/Akkadius)) 2022-07-16
### Logging
* Add stack trace in code paths that shouldn't occur ([#2453](https://github.com/EQEmu/Server/pull/2453)) ([Akkadius](https://github.com/Akkadius)) 2022-09-28
* Cleanup AI Logging Events ([#2615](https://github.com/EQEmu/Server/pull/2615)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04
* Fix log messages to final damage values ([#2056](https://github.com/EQEmu/Server/pull/2056)) ([noudess](https://github.com/noudess)) 2022-03-14
* Fix zoning log typo ([#2478](https://github.com/EQEmu/Server/pull/2478)) ([Akkadius](https://github.com/Akkadius)) 2022-10-11
* Force crash logs to always be on regardless of setting ([#2762](https://github.com/EQEmu/Server/pull/2762)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Improvements to GM Say Logging ([#2765](https://github.com/EQEmu/Server/pull/2765)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Logging Improvements ([#2755](https://github.com/EQEmu/Server/pull/2755)) ([Akkadius](https://github.com/Akkadius)) 2023-01-18
* More AI Logging Cleanup ([#2616](https://github.com/EQEmu/Server/pull/2616)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-10
* Netcode Logging Unify ([#2443](https://github.com/EQEmu/Server/pull/2443)) ([Akkadius](https://github.com/Akkadius)) 2022-09-28
* Remove function prefixes ([#2766](https://github.com/EQEmu/Server/pull/2766)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20
* Remove loginserver unhandled error ([#2458](https://github.com/EQEmu/Server/pull/2458)) ([Akkadius](https://github.com/Akkadius)) 2022-09-29
* Reset stream so we don't bold the whole line ([Akkadius](https://github.com/Akkadius)) 2023-01-18
* Table Injection - Member Variable Cleanup ([#2281](https://github.com/EQEmu/Server/pull/2281)) ([Akkadius](https://github.com/Akkadius)) 2022-07-07
* Update BUILD_LOGGING=false Blank Aliases ([#2083](https://github.com/EQEmu/Server/pull/2083)) ([Akkadius](https://github.com/Akkadius)) 2022-05-01
### Luamod
* Add CalcSpellEffectValue_formula to luamods ([#2721](https://github.com/EQEmu/Server/pull/2721)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-11
### Mercs
* Add Mercenary Support ([#2745](https://github.com/EQEmu/Server/pull/2745)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-17
### Optimization
* Handle channel name filter checks in memory ([#2767](https://github.com/EQEmu/Server/pull/2767)) ([Valorith](https://github.com/Valorith)) 2023-01-20
### QS
* Database class name change ([#2743](https://github.com/EQEmu/Server/pull/2743)) ([Akkadius](https://github.com/Akkadius)) 2023-01-15
### Quest API
* Add AddAISpellEffect(spell_effect_id, base_value, limit_value, max_value) and RemoveAISpellEffect(spell_effect_id) to Lua. ([#1981](https://github.com/EQEmu/Server/pull/1981)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-09
* Add AddItem() to Perl/Lua. ([#2054](https://github.com/EQEmu/Server/pull/2054)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-13
* Add AddPlatinum(), GetCarriedPlatinum() and TakePlatinum() to Perl/Lua. ([#2079](https://github.com/EQEmu/Server/pull/2079)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30
* Add Area Damage Methods to Perl/Lua. ([#2549](https://github.com/EQEmu/Server/pull/2549)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17
* Add Augment Slot Type/Visible to GetItemStat ([#2686](https://github.com/EQEmu/Server/pull/2686)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add Bot Methods to Lua. ([#2731](https://github.com/EQEmu/Server/pull/2731)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-14
* Add Bot::Camp() to Perl/Lua. ([#2718](https://github.com/EQEmu/Server/pull/2718)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-11
* Add BuffCount() Overloads to Perl/Lua. ([#2679](https://github.com/EQEmu/Server/pull/2679)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-29
* Add CampAllBots() to Perl/Lua. ([#2732](https://github.com/EQEmu/Server/pull/2732)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-14
* Add Charges/Augment/Attuned Support to Varlink. ([#2685](https://github.com/EQEmu/Server/pull/2685)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add CheckNameFilter to Perl/Lua. ([#2175](https://github.com/EQEmu/Server/pull/2175)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-20
* Add Client Augment Events to Perl/Lua. ([#2735](https://github.com/EQEmu/Server/pull/2735)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Add Client Spell Methods to Perl/Lua. ([#2550](https://github.com/EQEmu/Server/pull/2550)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add CloneAppearance() to Perl/Lua. ([#2531](https://github.com/EQEmu/Server/pull/2531)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add CopyHateList() to Perl/Lua. ([#2623](https://github.com/EQEmu/Server/pull/2623)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Add Corpse::AddItem overloads for Lua ([#2509](https://github.com/EQEmu/Server/pull/2509)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Add Despawn Events to Perl/Lua. ([#2707](https://github.com/EQEmu/Server/pull/2707)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-07
* Add DoAnim Overloads to Perl/Lua. ([#2627](https://github.com/EQEmu/Server/pull/2627)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-10
* Add DoAugmentSlotsMatch() to Perl/Lua. ([#2687](https://github.com/EQEmu/Server/pull/2687)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add DoesAugmentFit() to Perl/Lua. ([#2688](https://github.com/EQEmu/Server/pull/2688)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01
* Add Door Methods to Perl/Lua. ([#2724](https://github.com/EQEmu/Server/pull/2724)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-12
* Add EVENT_AA_BUY and EVENT_AA_GAIN to Perl/Lua. ([#2504](https://github.com/EQEmu/Server/pull/2504)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add EVENT_BOT_CREATE to Perl/Lua ([#2713](https://github.com/EQEmu/Server/pull/2713)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-09
* Add EVENT_CAST_ON exports to EVENT_CAST and EVENT_CAST_BEGIN. ([#2051](https://github.com/EQEmu/Server/pull/2051)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12
* Add EVENT_EQUIP_ITEM_CLIENT and EVENT_UNEQUIP_ITEM_CLIENT to Perl/Lua. ([#2015](https://github.com/EQEmu/Server/pull/2015)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-23
* Add EVENT_GM_COMMAND to Perl/Lua. ([#2634](https://github.com/EQEmu/Server/pull/2634)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Add EVENT_LEVEL_DOWN to Perl/Lua. ([#2620](https://github.com/EQEmu/Server/pull/2620)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Add EVENT_PAYLOAD to Perl/Lua. ([#2611](https://github.com/EQEmu/Server/pull/2611)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Add EVENT_SKILL_UP & EVENT_LANGUAGE_SKILL_UP to Perl/Lua ([#2076](https://github.com/EQEmu/Server/pull/2076)) ([nytmyr](https://github.com/nytmyr)) 2022-04-25
* Add Entity Variable Methods to Perl/Lua. ([#2609](https://github.com/EQEmu/Server/pull/2609)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Add Fling Overloads to Perl/Lua. ([#2622](https://github.com/EQEmu/Server/pull/2622)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Add GetAugmentIDsBySlotID() to Perl/Lua. ([#2673](https://github.com/EQEmu/Server/pull/2673)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25
* Add GetAverageLevel() to Perl/Lua. ([#2524](https://github.com/EQEmu/Server/pull/2524)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add GetBotItem() and GetBotItemIDBySlot() to Perl/Lua. ([#2350](https://github.com/EQEmu/Server/pull/2350)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-31
* Add GetBotListByCharacterID() to Perl/Lua. ([#2069](https://github.com/EQEmu/Server/pull/2069)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-02
* Add GetBotListByClientName() Class Overload to Perl/Lua. ([#2577](https://github.com/EQEmu/Server/pull/2577)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add GetBotListByClientName(client_name) to Perl/Lua. ([#2064](https://github.com/EQEmu/Server/pull/2064)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-23
* Add GetEnvironmentalDamageName() to Perl/Lua. ([#1964](https://github.com/EQEmu/Server/pull/1964)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10
* Add GetGMStatus() to Perl/Lua. ([#2448](https://github.com/EQEmu/Server/pull/2448)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-09-28
* Add GetGuildPublicNote() to Perl/Lua. ([#2608](https://github.com/EQEmu/Server/pull/2608)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Add GetHealAmount() and GetSpellDamage() to Perl/Lua. ([#2165](https://github.com/EQEmu/Server/pull/2165)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-11
* Add GetLeader() and GetLeaderName() to Perl/Lua. ([#2701](https://github.com/EQEmu/Server/pull/2701)) ([Valorith](https://github.com/Valorith)) 2023-01-04
* Add GetLowestLevel() to Perl. ([#2517](https://github.com/EQEmu/Server/pull/2517)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add GetRandomBot() to Perl/Lua ([#2543](https://github.com/EQEmu/Server/pull/2543)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add GetRandomClient(), GetRandomMob() and GetRandomNPC() overloads to Perl/Lua. ([#2541](https://github.com/EQEmu/Server/pull/2541)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add GetRandomMob() and GetRandomNPC() to Perl/Lua. ([#2006](https://github.com/EQEmu/Server/pull/2006)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-17
* Add GetSkillDmgAmt() to Perl. ([#2365](https://github.com/EQEmu/Server/pull/2365)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-10
* Add GetUltimateOwner() to Perl/Lua. ([#2516](https://github.com/EQEmu/Server/pull/2516)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add Goto Player Teleport Methods. ([#2379](https://github.com/EQEmu/Server/pull/2379)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20
* Add Group/Raid Overloads to Perl/Lua. ([#2587](https://github.com/EQEmu/Server/pull/2587)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Add Group/Raid overloads to Perl/Lua. ([#2526](https://github.com/EQEmu/Server/pull/2526)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add HasBotSpellEntry() to Perl/Lua. ([#2563](https://github.com/EQEmu/Server/pull/2563)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25
* Add Hotzone Methods to Perl/Lua. ([#2558](https://github.com/EQEmu/Server/pull/2558)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add Instance ID/Version exports to EVENT_ZONE. ([#2502](https://github.com/EQEmu/Server/pull/2502)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05
* Add Instance Methods to Perl/Lua. ([#2573](https://github.com/EQEmu/Server/pull/2573)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add IsAttackAllowed() to Perl/Lua. ([#2672](https://github.com/EQEmu/Server/pull/2672)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25
* Add IsRaining() and IsSnowing() to Perl/Lua. ([#2477](https://github.com/EQEmu/Server/pull/2477)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-14
* Add IsRareSpawn() to Perl/Lua. ([#2338](https://github.com/EQEmu/Server/pull/2338)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-30
* Add Lua handlers for zone controller events ([#2514](https://github.com/EQEmu/Server/pull/2514)) ([hgtw](https://github.com/hgtw)) 2022-11-05
* Add Marquee methods to Perl/Lua. ([#2544](https://github.com/EQEmu/Server/pull/2544)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add MaxSkills() to Perl/Lua. ([#2621](https://github.com/EQEmu/Server/pull/2621)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06
* Add Merchant Events to Perl/Lua. ([#2452](https://github.com/EQEmu/Server/pull/2452)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-09-28
* Add Mob Hate Methods to Perl/Lua. ([#2548](https://github.com/EQEmu/Server/pull/2548)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16
* Add Overloads to MoveZone Methods in Perl/Lua. ([#2551](https://github.com/EQEmu/Server/pull/2551)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22
* Add Owner methods to Perl/Lua. ([#2542](https://github.com/EQEmu/Server/pull/2542)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add Popup methods to Perl/Lua. ([#2533](https://github.com/EQEmu/Server/pull/2533)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add Proximity Range Methods to Perl/Lua. ([#2572](https://github.com/EQEmu/Server/pull/2572)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add RandomizeFeature() overloads to Perl/Lua. ([#2532](https://github.com/EQEmu/Server/pull/2532)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add Recipe Methods ([#2393](https://github.com/EQEmu/Server/pull/2393)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-23
* Add ResetAlternateAdvancementRank() to Perl/Lua. ([#2510](https://github.com/EQEmu/Server/pull/2510)) ([hgtw](https://github.com/hgtw)) 2022-10-29
* Add ResetDecayTimer() to Perl/Lua. ([#2520](https://github.com/EQEmu/Server/pull/2520)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Add SendGMCommand() to Perl/Lua. ([#2527](https://github.com/EQEmu/Server/pull/2527)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add SendPath() to Perl/Lua. ([#2740](https://github.com/EQEmu/Server/pull/2740)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15
* Add SignalAllBotsByOwnerName() to Perl/Lua. ([#2730](https://github.com/EQEmu/Server/pull/2730)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13
* Add SplitMoney() with Client splitter to Perl. ([#2525](https://github.com/EQEmu/Server/pull/2525)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14
* Add TaskSelector to Perl/Lua. ([#2177](https://github.com/EQEmu/Server/pull/2177)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-15
* Add Time String to Seconds Method to Perl/Lua. ([#2580](https://github.com/EQEmu/Server/pull/2580)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Add TrackNPC to Perl/Lua. ([#2272](https://github.com/EQEmu/Server/pull/2272)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-29
* Add WearChange Overloads to Perl/Lua. ([#2600](https://github.com/EQEmu/Server/pull/2600)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01
* Add Zone Flag Methods to Perl/Lua. ([#2574](https://github.com/EQEmu/Server/pull/2574)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26
* Add apis to end shared tasks ([#2521](https://github.com/EQEmu/Server/pull/2521)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Add caster_id and caster_level export to EVENT_CAST_ON in Perl/Lua. ([#2049](https://github.com/EQEmu/Server/pull/2049)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-11
* Add commify to Perl/Lua. ([#2099](https://github.com/EQEmu/Server/pull/2099)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-03
* Add inventory->CountItemEquippedByID(item_id) and inventory->HasItemEquippedByID(item_id) to Perl/Lua. ([#1963](https://github.com/EQEmu/Server/pull/1963)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-06
* Add missing methods/package.adds to Perl API. ([#2287](https://github.com/EQEmu/Server/pull/2287)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05
* Add multiple inventory method short hands to client. ([#2078](https://github.com/EQEmu/Server/pull/2078)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30
* Add option to Ignore Mods to CalcEXP ([#2704](https://github.com/EQEmu/Server/pull/2704)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-06
* Adjustment to depop_all function. ([#2595](https://github.com/EQEmu/Server/pull/2595)) ([fryguy503](https://github.com/fryguy503)) 2022-11-30
* Allow CreateInstance to be used without a Client initiator. ([#2399](https://github.com/EQEmu/Server/pull/2399)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-28
* Allow EVENT_ZONE to be parsed as non-zero to prevent zoning. ([#2052](https://github.com/EQEmu/Server/pull/2052)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12
* Allow scripts to prevent door click ([#2327](https://github.com/EQEmu/Server/pull/2327)) ([hgtw](https://github.com/hgtw)) 2022-07-27
* Cleanup Proximity Events ([#2697](https://github.com/EQEmu/Server/pull/2697)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02
* Cleanup Signal Methods in Perl/Lua. ([#2604](https://github.com/EQEmu/Server/pull/2604)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04
* Expand Bot quest API functionality. ([#2096](https://github.com/EQEmu/Server/pull/2096)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Expand SaveGuardSpot ([#2258](https://github.com/EQEmu/Server/pull/2258)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10
* Export corpse in EVENT_DEATH_COMPLETE ([#2519](https://github.com/EQEmu/Server/pull/2519)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Export killed XYZH to EVENT_DEATH_ZONE in Perl. ([#2050](https://github.com/EQEmu/Server/pull/2050)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12
* Fix Lua Door/Object Create Methods. ([#2633](https://github.com/EQEmu/Server/pull/2633)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11
* Fix Perl EVENT_HP double parsing in Spire. ([#2585](https://github.com/EQEmu/Server/pull/2585)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27
* Fix lua task selector count when over max ([#2353](https://github.com/EQEmu/Server/pull/2353)) ([hgtw](https://github.com/hgtw)) 2022-07-31
* Fix missing arg in perl set_proximity ([#2291](https://github.com/EQEmu/Server/pull/2291)) ([hgtw](https://github.com/hgtw)) 2022-07-09
* Fix parameters in some Perl worldwide methods. ([#2224](https://github.com/EQEmu/Server/pull/2224)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-31
* Let HasQuestSub check encounters ([#2435](https://github.com/EQEmu/Server/pull/2435)) ([hgtw](https://github.com/hgtw)) 2022-09-20
* Perl Doors Fix. ([#2288](https://github.com/EQEmu/Server/pull/2288)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05
* Perl Money Fixes. ([#2098](https://github.com/EQEmu/Server/pull/2098)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04
* Send delivered task items in trade events ([#2518](https://github.com/EQEmu/Server/pull/2518)) ([hgtw](https://github.com/hgtw)) 2022-11-06
* Use Floating Point for CameraEffect Intensity ([#2337](https://github.com/EQEmu/Server/pull/2337)) ([hgtw](https://github.com/hgtw)) 2022-07-31
* Use binding library for perl apis ([#2216](https://github.com/EQEmu/Server/pull/2216)) ([hgtw](https://github.com/hgtw)) 2022-07-04
### Rules
* Add Backstab Rules ([#2666](https://github.com/EQEmu/Server/pull/2666)) ([Valorith](https://github.com/Valorith)) 2022-12-21
* Add Frontal Stun Immunity Rules. ([#2217](https://github.com/EQEmu/Server/pull/2217)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-07
* Add Keep Level on Death ([#2319](https://github.com/EQEmu/Server/pull/2319)) ([trentdm](https://github.com/trentdm)) 2022-07-30
* Add LDoN Loot Count Modifier Rule ([#2694](https://github.com/EQEmu/Server/pull/2694)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03
* Add ManaOnDeath and EndurOnDeath ([#2661](https://github.com/EQEmu/Server/pull/2661)) ([fryguy503](https://github.com/fryguy503)) 2022-12-20
* Add Rule to Disable NPC Last Names. ([#2227](https://github.com/EQEmu/Server/pull/2227)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04
* Add Rule to Enable Tells with #hideme ([#2358](https://github.com/EQEmu/Server/pull/2358)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-04
* Add Rule to allow Assassinate on non-Humanoid body types. ([#2331](https://github.com/EQEmu/Server/pull/2331)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-29
* Add Rule to allow Headshots on non-Humanoid body types. ([#2329](https://github.com/EQEmu/Server/pull/2329)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-29
* Add Rules to disable various item functionalities and cleanup data types. ([#2225](https://github.com/EQEmu/Server/pull/2225)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01
* Add Spells:BuffsFadeOnDeath. ([#2200](https://github.com/EQEmu/Server/pull/2200)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Add Spells:IllusionsAlwaysPersist. ([#2199](https://github.com/EQEmu/Server/pull/2199)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27
* Add Toggle for Warrior Shielding ([#2496](https://github.com/EQEmu/Server/pull/2496)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-22
* Add adjustment for zone forage. ([#2330](https://github.com/EQEmu/Server/pull/2330)) ([fryguy503](https://github.com/fryguy503)) 2022-07-30
* Add rule for NPC Level Based Buff Restrictions. ([#2708](https://github.com/EQEmu/Server/pull/2708)) ([noudess](https://github.com/noudess)) 2023-01-15
* Add rule to allow players to permanently save chat channels to database, up to a limit. ([#2706](https://github.com/EQEmu/Server/pull/2706)) ([Valorith](https://github.com/Valorith)) 2023-01-19
* Change TradeskillUp Rules to be Floats ([#2674](https://github.com/EQEmu/Server/pull/2674)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-25
* Cleanup all unused rules. ([#2184](https://github.com/EQEmu/Server/pull/2184)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23
* Rule Gate Pet Zoning ([#2625](https://github.com/EQEmu/Server/pull/2625)) ([fryguy503](https://github.com/fryguy503)) 2022-12-07
* Rule to allow cap on % XP gain per kill ([#2667](https://github.com/EQEmu/Server/pull/2667)) ([Valorith](https://github.com/Valorith)) 2022-12-25
* Update logic checks everywhere for FVNoDropFlag. ([#2179](https://github.com/EQEmu/Server/pull/2179)) ([Quintinon](https://github.com/Quintinon)) 2022-07-30
### SQL
* Bugs Table Migration (#2602) ([#2559](https://github.com/EQEmu/Server/pull/2559)) ([joligario](https://github.com/joligario)) 2022-12-01
* Update 2023_01_15_merc_data.sql ([#2763](https://github.com/EQEmu/Server/pull/2763)) ([joligario](https://github.com/joligario)) 2023-01-20
### UCS
* Auto Client Reconnection ([#2154](https://github.com/EQEmu/Server/pull/2154)) ([Akkadius](https://github.com/Akkadius)) 2022-05-08
### Websocket
* Fix cpp20/gcc11 compile failure ([#2737](https://github.com/EQEmu/Server/pull/2737)) ([Akkadius](https://github.com/Akkadius)) 2023-01-15
### Zone Flags
* Use database connection, not content connection ([#2759](https://github.com/EQEmu/Server/pull/2759)) ([Akkadius](https://github.com/Akkadius)) 2023-01-19
+13 -7
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.7)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
@@ -12,7 +12,7 @@ IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_CXX_STANDARD 20) SET(CMAKE_CXX_STANDARD 14)
SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF) SET(CMAKE_CXX_EXTENSIONS OFF)
@@ -20,10 +20,8 @@ IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-DNOMINMAX) ADD_DEFINITIONS(-DNOMINMAX)
ADD_DEFINITIONS(-DCRASH_LOGGING) ADD_DEFINITIONS(-DCRASH_LOGGING)
ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os")
ELSE(MSVC) ELSE(MSVC)
ADD_DEFINITIONS(-DHAS_UNION_SEMUN) ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC) ENDIF(MSVC)
@@ -123,6 +121,8 @@ ENDIF()
MESSAGE(STATUS "**************************************************") MESSAGE(STATUS "**************************************************")
#options #options
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON) OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON) OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON) OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
@@ -176,6 +176,10 @@ IF(EQEMU_COMMANDS_LOGGING)
ADD_DEFINITIONS(-DCOMMANDS_LOGGING) ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
ENDIF(EQEMU_COMMANDS_LOGGING) ENDIF(EQEMU_COMMANDS_LOGGING)
IF(EQEMU_ENABLE_BOTS)
ADD_DEFINITIONS(-DBOTS)
ENDIF(EQEMU_ENABLE_BOTS)
#database #database
IF(MySQL_FOUND AND MariaDB_FOUND) IF(MySQL_FOUND AND MariaDB_FOUND)
SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use: SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use:
@@ -336,8 +340,10 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
# silence obnoxious deprecation message OPTION(EQEMU_BUILD_LOGGING "Build Logging (To speed up compilation)" ON)
ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS) IF(EQEMU_BUILD_LOGGING)
ADD_DEFINITIONS(-DBUILD_LOGGING)
ENDIF()
IF(TLS_LIBRARY_ENABLED) IF(TLS_LIBRARY_ENABLED)
SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS}) SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS})
@@ -367,7 +373,7 @@ ENDIF()
IF(PERL_LIBRARY_ENABLED) IF(PERL_LIBRARY_ENABLED)
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
IF(EQEMU_BUILD_PERL) IF(EQEMU_BUILD_PERL)
SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS} perlbind) SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}") INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
ADD_DEFINITIONS(-DEMBPERL) ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN) ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
+3 -3
View File
@@ -18,11 +18,11 @@
|**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)| |**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)|
### > Windows ### > Windows
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-windows/) * [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-windows)
### > Debian/Ubuntu/CentOS/Fedora ### > Debian/Ubuntu/CentOS/Fedora
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-linux/) * [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-linux)
* You can use curl or wget to kick off the installer (whichever your OS has) * You can use curl or wget to kick off the installer (whichever your OS has)
> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh > curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh
@@ -56,7 +56,7 @@ forum, although pull requests will be much quicker and easier on all parties.
## Resources ## Resources
- [EQEmulator Forums](http://www.eqemulator.org/forums) - [EQEmulator Forums](http://www.eqemulator.org/forums)
- [EQEmulator Wiki](https://docs.eqemu.io/) - [EQEmulator Wiki](https://eqemu.gitbook.io/)
## Related Repositories ## Related Repositories
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests) * [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
+21
View File
@@ -0,0 +1,21 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll
appveyor PushArtifact build_x64-bots.zip
+21
View File
@@ -0,0 +1,21 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=OFF -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-no-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll
appveyor PushArtifact build_x64-no-bots.zip
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(export_sources SET(export_sources
main.cpp main.cpp
+5 -16
View File
@@ -25,15 +25,11 @@
#include "../../common/platform.h" #include "../../common/platform.h"
#include "../../common/crash.h" #include "../../common/crash.h"
#include "../../common/rulesys.h" #include "../../common/rulesys.h"
#include "../../common/strings.h" #include "../../common/string_util.h"
#include "../../common/content/world_content_service.h" #include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys; EQEmuLogSys LogSys;
WorldContentService content_service; WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ExportSpells(SharedDatabase *db); void ExportSpells(SharedDatabase *db);
void ExportSkillCaps(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db);
@@ -46,8 +42,6 @@ int main(int argc, char **argv)
LogSys.LoadLogSettingsDefaults(); LogSys.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Export Utility"); LogInfo("Client Files Export Utility");
if (!EQEmuConfig::LoadConfig()) { if (!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file"); LogError("Unable to load configuration file");
@@ -90,7 +84,6 @@ int main(int argc, char **argv)
} }
LogSys.SetDatabase(&database) LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings() ->LoadLogDatabaseSettings()
->StartFileLogs(); ->StartFileLogs();
@@ -131,8 +124,7 @@ void ExportSpells(SharedDatabase *db)
{ {
LogInfo("Exporting Spells"); LogInfo("Exporting Spells");
std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath()); FILE *f = fopen("export/spells_us.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/spells_us.txt to write, skipping."); LogError("Unable to open export/spells_us.txt to write, skipping.");
return; return;
@@ -214,8 +206,7 @@ void ExportSkillCaps(SharedDatabase *db)
{ {
LogInfo("Exporting Skill Caps"); LogInfo("Exporting Skill Caps");
std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()); FILE *f = fopen("export/SkillCaps.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/SkillCaps.txt to write, skipping."); LogError("Unable to open export/SkillCaps.txt to write, skipping.");
return; return;
@@ -245,8 +236,7 @@ void ExportBaseData(SharedDatabase *db)
{ {
LogInfo("Exporting Base Data"); LogInfo("Exporting Base Data");
std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath()); FILE *f = fopen("export/BaseData.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/BaseData.txt to write, skipping."); LogError("Unable to open export/BaseData.txt to write, skipping.");
return; return;
@@ -279,8 +269,7 @@ void ExportDBStrings(SharedDatabase *db)
{ {
LogInfo("Exporting DB Strings"); LogInfo("Exporting DB Strings");
std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()); FILE *f = fopen("export/dbstr_us.txt", "w");
FILE *f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
LogError("Unable to open export/dbstr_us.txt to write, skipping."); LogError("Unable to open export/dbstr_us.txt to write, skipping.");
return; return;
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(import_sources SET(import_sources
main.cpp main.cpp
+15 -26
View File
@@ -23,15 +23,11 @@
#include "../../common/platform.h" #include "../../common/platform.h"
#include "../../common/crash.h" #include "../../common/crash.h"
#include "../../common/rulesys.h" #include "../../common/rulesys.h"
#include "../../common/strings.h" #include "../../common/string_util.h"
#include "../../common/content/world_content_service.h" #include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
EQEmuLogSys LogSys; EQEmuLogSys LogSys;
WorldContentService content_service; WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ImportSpells(SharedDatabase *db); void ImportSpells(SharedDatabase *db);
void ImportSkillCaps(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db);
@@ -43,8 +39,6 @@ int main(int argc, char **argv) {
LogSys.LoadLogSettingsDefaults(); LogSys.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
path.LoadPaths();
LogInfo("Client Files Import Utility"); LogInfo("Client Files Import Utility");
if(!EQEmuConfig::LoadConfig()) { if(!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file."); LogError("Unable to load configuration file.");
@@ -87,7 +81,6 @@ int main(int argc, char **argv) {
} }
LogSys.SetDatabase(&database) LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings() ->LoadLogDatabaseSettings()
->StartFileLogs(); ->StartFileLogs();
@@ -132,10 +125,9 @@ bool IsStringField(int i) {
void ImportSpells(SharedDatabase *db) { void ImportSpells(SharedDatabase *db) {
LogInfo("Importing Spells"); LogInfo("Importing Spells");
std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath()); FILE *f = fopen("import/spells_us.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/spells_us.txt to read, skipping.");
return; return;
} }
@@ -154,8 +146,8 @@ void ImportSpells(SharedDatabase *db) {
} }
} }
std::string escaped = ::Strings::Escape(buffer); std::string escaped = ::EscapeString(buffer);
auto split = Strings::Split(escaped, '^'); auto split = SplitString(escaped, '^');
int line_columns = (int)split.size(); int line_columns = (int)split.size();
std::string sql; std::string sql;
@@ -222,10 +214,9 @@ void ImportSpells(SharedDatabase *db) {
void ImportSkillCaps(SharedDatabase *db) { void ImportSkillCaps(SharedDatabase *db) {
LogInfo("Importing Skill Caps"); LogInfo("Importing Skill Caps");
std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath()); FILE *f = fopen("import/SkillCaps.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/SkillCaps.txt to read, skipping.");
return; return;
} }
@@ -234,7 +225,7 @@ void ImportSkillCaps(SharedDatabase *db) {
char buffer[2048]; char buffer[2048];
while(fgets(buffer, 2048, f)) { while(fgets(buffer, 2048, f)) {
auto split = Strings::Split(buffer, '^'); auto split = SplitString(buffer, '^');
if(split.size() < 4) { if(split.size() < 4) {
continue; continue;
@@ -258,10 +249,9 @@ void ImportSkillCaps(SharedDatabase *db) {
void ImportBaseData(SharedDatabase *db) { void ImportBaseData(SharedDatabase *db) {
LogInfo("Importing Base Data"); LogInfo("Importing Base Data");
std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath()); FILE *f = fopen("import/BaseData.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/BaseData.txt to read, skipping.");
return; return;
} }
@@ -270,7 +260,7 @@ void ImportBaseData(SharedDatabase *db) {
char buffer[2048]; char buffer[2048];
while(fgets(buffer, 2048, f)) { while(fgets(buffer, 2048, f)) {
auto split = Strings::Split(buffer, '^'); auto split = SplitString(buffer, '^');
if(split.size() < 10) { if(split.size() < 10) {
continue; continue;
@@ -304,10 +294,9 @@ void ImportBaseData(SharedDatabase *db) {
void ImportDBStrings(SharedDatabase *db) { void ImportDBStrings(SharedDatabase *db) {
LogInfo("Importing DB Strings"); LogInfo("Importing DB Strings");
std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath()); FILE *f = fopen("import/dbstr_us.txt", "r");
FILE *f = fopen(file.c_str(), "r");
if(!f) { if(!f) {
LogError("Unable to open {} to read, skipping.", file); LogError("Unable to open import/dbstr_us.txt to read, skipping.");
return; return;
} }
@@ -329,7 +318,7 @@ void ImportDBStrings(SharedDatabase *db) {
} }
} }
auto split = Strings::Split(buffer, '^'); auto split = SplitString(buffer, '^');
if(split.size() < 2) { if(split.size() < 2) {
continue; continue;
@@ -343,7 +332,7 @@ void ImportDBStrings(SharedDatabase *db) {
type = atoi(split[1].c_str()); type = atoi(split[1].c_str());
if(split.size() >= 3) { if(split.size() >= 3) {
value = ::Strings::Escape(split[2]); value = ::EscapeString(split[2]);
} }
sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')", sql = StringFormat("INSERT INTO db_str(id, type, value) VALUES(%u, %u, '%s')",
+26 -48
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12) CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
SET(common_sources SET(common_sources
base_packet.cpp base_packet.cpp
@@ -7,7 +7,6 @@ SET(common_sources
compression.cpp compression.cpp
condition.cpp condition.cpp
content/world_content_service.cpp content/world_content_service.cpp
discord/discord.cpp
crash.cpp crash.cpp
crc16.cpp crc16.cpp
crc32.cpp crc32.cpp
@@ -35,9 +34,8 @@ SET(common_sources
event_sub.cpp event_sub.cpp
expedition_lockout_timer.cpp expedition_lockout_timer.cpp
extprofile.cpp extprofile.cpp
discord_manager.cpp
faction.cpp faction.cpp
file.cpp file_util.cpp
guild_base.cpp guild_base.cpp
guilds.cpp guilds.cpp
inventory_profile.cpp inventory_profile.cpp
@@ -61,10 +59,8 @@ SET(common_sources
packet_dump.cpp packet_dump.cpp
packet_dump_file.cpp packet_dump_file.cpp
packet_functions.cpp packet_functions.cpp
path_manager.cpp
perl_eqdb.cpp perl_eqdb.cpp
perl_eqdb_res.cpp perl_eqdb_res.cpp
process/process.cpp
proc_launcher.cpp proc_launcher.cpp
profanity_manager.cpp profanity_manager.cpp
ptimer.cpp ptimer.cpp
@@ -79,14 +75,13 @@ SET(common_sources
shareddb.cpp shareddb.cpp
skills.cpp skills.cpp
spdat.cpp spdat.cpp
strings.cpp string_util.cpp
struct_strategy.cpp struct_strategy.cpp
textures.cpp textures.cpp
timer.cpp timer.cpp
unix.cpp unix.cpp
platform.cpp platform.cpp
json/jsoncpp.cpp json/jsoncpp.cpp
zone_store.cpp
net/console_server.cpp net/console_server.cpp
net/console_server_connection.cpp net/console_server_connection.cpp
net/crc32.cpp net/crc32.cpp
@@ -123,9 +118,6 @@ SET(repositories
# Criteria # Criteria
repositories/criteria/content_filter_criteria.h repositories/criteria/content_filter_criteria.h
repositories/base/base_grid_repository.h
repositories/base/base_grid_entries_repository.h
# Base Repositories # Base Repositories
repositories/base/base_aa_ability_repository.h repositories/base/base_aa_ability_repository.h
repositories/base/base_aa_ranks_repository.h repositories/base/base_aa_ranks_repository.h
@@ -145,7 +137,6 @@ SET(repositories
repositories/base/base_auras_repository.h repositories/base/base_auras_repository.h
repositories/base/base_base_data_repository.h repositories/base/base_base_data_repository.h
repositories/base/base_blocked_spells_repository.h repositories/base/base_blocked_spells_repository.h
repositories/base/base_books_repository.h
repositories/base/base_bugs_repository.h repositories/base/base_bugs_repository.h
repositories/base/base_bug_reports_repository.h repositories/base/base_bug_reports_repository.h
repositories/base/base_buyer_repository.h repositories/base/base_buyer_repository.h
@@ -162,7 +153,6 @@ SET(repositories
repositories/base/base_character_data_repository.h repositories/base/base_character_data_repository.h
repositories/base/base_character_disciplines_repository.h repositories/base/base_character_disciplines_repository.h
repositories/base/base_character_expedition_lockouts_repository.h repositories/base/base_character_expedition_lockouts_repository.h
repositories/base/base_character_exp_modifiers_repository.h
repositories/base/base_character_inspect_messages_repository.h repositories/base/base_character_inspect_messages_repository.h
repositories/base/base_character_instance_safereturns_repository.h repositories/base/base_character_instance_safereturns_repository.h
repositories/base/base_character_item_recast_repository.h repositories/base/base_character_item_recast_repository.h
@@ -170,38 +160,32 @@ SET(repositories
repositories/base/base_character_leadership_abilities_repository.h repositories/base/base_character_leadership_abilities_repository.h
repositories/base/base_character_material_repository.h repositories/base/base_character_material_repository.h
repositories/base/base_character_memmed_spells_repository.h repositories/base/base_character_memmed_spells_repository.h
repositories/base/base_character_peqzone_flags_repository.h
repositories/base/base_character_pet_buffs_repository.h repositories/base/base_character_pet_buffs_repository.h
repositories/base/base_character_pet_info_repository.h repositories/base/base_character_pet_info_repository.h
repositories/base/base_character_pet_inventory_repository.h repositories/base/base_character_pet_inventory_repository.h
repositories/base/base_character_potionbelt_repository.h repositories/base/base_character_potionbelt_repository.h
repositories/base/base_character_skills_repository.h repositories/base/base_character_skills_repository.h
repositories/base/base_character_spells_repository.h repositories/base/base_character_spells_repository.h
repositories/base/base_character_tasks_repository.h
repositories/base/base_character_task_timers_repository.h repositories/base/base_character_task_timers_repository.h
repositories/base/base_character_tasks_repository.h
repositories/base/base_char_create_combinations_repository.h repositories/base/base_char_create_combinations_repository.h
repositories/base/base_char_create_point_allocations_repository.h repositories/base/base_char_create_point_allocations_repository.h
repositories/base/base_char_recipe_list_repository.h repositories/base/base_char_recipe_list_repository.h
repositories/base/base_chatchannels_repository.h
repositories/base/base_chatchannel_reserved_names_repository.h
repositories/base/base_completed_shared_tasks_repository.h
repositories/base/base_completed_shared_task_activity_state_repository.h
repositories/base/base_completed_shared_task_members_repository.h
repositories/base/base_completed_tasks_repository.h repositories/base/base_completed_tasks_repository.h
repositories/base/base_completed_shared_tasks_repository.h
repositories/base/base_completed_shared_task_members_repository.h
repositories/base/base_completed_shared_task_activity_state_repository.h
repositories/base/base_content_flags_repository.h repositories/base/base_content_flags_repository.h
repositories/base/base_damageshieldtypes_repository.h repositories/base/base_damageshieldtypes_repository.h
repositories/base/base_data_buckets_repository.h repositories/base/base_data_buckets_repository.h
repositories/base/base_db_str_repository.h repositories/base/base_db_str_repository.h
repositories/base/base_discord_webhooks_repository.h
repositories/base/base_discovered_items_repository.h repositories/base/base_discovered_items_repository.h
repositories/base/base_doors_repository.h repositories/base/base_doors_repository.h
repositories/base/base_dynamic_zones_repository.h repositories/base/base_dynamic_zones_repository.h
repositories/base/base_dynamic_zone_members_repository.h repositories/base/base_dynamic_zone_members_repository.h
repositories/base/base_dynamic_zone_templates_repository.h
repositories/base/base_eventlog_repository.h repositories/base/base_eventlog_repository.h
repositories/base/base_expeditions_repository.h repositories/base/base_expeditions_repository.h
repositories/base/base_expedition_lockouts_repository.h repositories/base/base_expedition_lockouts_repository.h
repositories/base/base_faction_association_repository.h
repositories/base/base_faction_base_data_repository.h repositories/base/base_faction_base_data_repository.h
repositories/base/base_faction_list_repository.h repositories/base/base_faction_list_repository.h
repositories/base/base_faction_list_mod_repository.h repositories/base/base_faction_list_mod_repository.h
@@ -211,15 +195,18 @@ SET(repositories
repositories/base/base_friends_repository.h repositories/base/base_friends_repository.h
repositories/base/base_global_loot_repository.h repositories/base/base_global_loot_repository.h
repositories/base/base_gm_ips_repository.h repositories/base/base_gm_ips_repository.h
repositories/base/base_goallists_repository.h
repositories/base/base_graveyard_repository.h repositories/base/base_graveyard_repository.h
repositories/base/base_grid_repository.h
repositories/base/base_grid_entries_repository.h
repositories/base/base_ground_spawns_repository.h repositories/base/base_ground_spawns_repository.h
repositories/base/base_group_id_repository.h repositories/base/base_group_id_repository.h
repositories/base/base_group_leaders_repository.h repositories/base/base_group_leaders_repository.h
repositories/base/base_guilds_repository.h repositories/base/base_guilds_repository.h
repositories/base/base_guild_members_repository.h
repositories/base/base_guild_ranks_repository.h repositories/base/base_guild_ranks_repository.h
repositories/base/base_guild_relations_repository.h repositories/base/base_guild_relations_repository.h
repositories/base/base_hackers_repository.h repositories/base/base_hackers_repository.h
repositories/base/base_horses_repository.h
repositories/base/base_instance_list_repository.h repositories/base/base_instance_list_repository.h
repositories/base/base_instance_list_player_repository.h repositories/base/base_instance_list_player_repository.h
repositories/base/base_inventory_repository.h repositories/base/base_inventory_repository.h
@@ -260,10 +247,10 @@ SET(repositories
repositories/base/base_perl_event_export_settings_repository.h repositories/base/base_perl_event_export_settings_repository.h
repositories/base/base_petitions_repository.h repositories/base/base_petitions_repository.h
repositories/base/base_pets_repository.h repositories/base/base_pets_repository.h
repositories/base/base_pets_beastlord_data_repository.h
repositories/base/base_pets_equipmentset_repository.h repositories/base/base_pets_equipmentset_repository.h
repositories/base/base_pets_equipmentset_entries_repository.h repositories/base/base_pets_equipmentset_entries_repository.h
repositories/base/base_player_titlesets_repository.h repositories/base/base_player_titlesets_repository.h
repositories/base/base_proximities_repository.h
repositories/base/base_quest_globals_repository.h repositories/base/base_quest_globals_repository.h
repositories/base/base_raid_details_repository.h repositories/base/base_raid_details_repository.h
repositories/base/base_raid_members_repository.h repositories/base/base_raid_members_repository.h
@@ -323,7 +310,6 @@ SET(repositories
repositories/auras_repository.h repositories/auras_repository.h
repositories/base_data_repository.h repositories/base_data_repository.h
repositories/blocked_spells_repository.h repositories/blocked_spells_repository.h
repositories/books_repository.h
repositories/bugs_repository.h repositories/bugs_repository.h
repositories/bug_reports_repository.h repositories/bug_reports_repository.h
repositories/buyer_repository.h repositories/buyer_repository.h
@@ -340,7 +326,6 @@ SET(repositories
repositories/character_data_repository.h repositories/character_data_repository.h
repositories/character_disciplines_repository.h repositories/character_disciplines_repository.h
repositories/character_expedition_lockouts_repository.h repositories/character_expedition_lockouts_repository.h
repositories/character_exp_modifiers_repository.h
repositories/character_inspect_messages_repository.h repositories/character_inspect_messages_repository.h
repositories/character_instance_safereturns_repository.h repositories/character_instance_safereturns_repository.h
repositories/character_item_recast_repository.h repositories/character_item_recast_repository.h
@@ -348,38 +333,32 @@ SET(repositories
repositories/character_leadership_abilities_repository.h repositories/character_leadership_abilities_repository.h
repositories/character_material_repository.h repositories/character_material_repository.h
repositories/character_memmed_spells_repository.h repositories/character_memmed_spells_repository.h
repositories/character_peqzone_flags_repository.h
repositories/character_pet_buffs_repository.h repositories/character_pet_buffs_repository.h
repositories/character_pet_info_repository.h repositories/character_pet_info_repository.h
repositories/character_pet_inventory_repository.h repositories/character_pet_inventory_repository.h
repositories/character_potionbelt_repository.h repositories/character_potionbelt_repository.h
repositories/character_skills_repository.h repositories/character_skills_repository.h
repositories/character_spells_repository.h repositories/character_spells_repository.h
repositories/character_tasks_repository.h
repositories/character_task_timers_repository.h repositories/character_task_timers_repository.h
repositories/character_tasks_repository.h
repositories/char_create_combinations_repository.h repositories/char_create_combinations_repository.h
repositories/char_create_point_allocations_repository.h repositories/char_create_point_allocations_repository.h
repositories/char_recipe_list_repository.h repositories/char_recipe_list_repository.h
repositories/chatchannels_repository.h
repositories/chatchannel_reserved_names_repository.h
repositories/completed_shared_tasks_repository.h
repositories/completed_shared_task_activity_state_repository.h
repositories/completed_shared_task_members_repository.h
repositories/completed_tasks_repository.h repositories/completed_tasks_repository.h
repositories/completed_shared_tasks_repository.h
repositories/completed_shared_task_members_repository.h
repositories/completed_shared_task_activity_state_repository.h
repositories/content_flags_repository.h repositories/content_flags_repository.h
repositories/damageshieldtypes_repository.h repositories/damageshieldtypes_repository.h
repositories/data_buckets_repository.h repositories/data_buckets_repository.h
repositories/db_str_repository.h repositories/db_str_repository.h
repositories/discord_webhooks_repository.h
repositories/discovered_items_repository.h repositories/discovered_items_repository.h
repositories/doors_repository.h repositories/doors_repository.h
repositories/dynamic_zones_repository.h repositories/dynamic_zones_repository.h
repositories/dynamic_zone_members_repository.h repositories/dynamic_zone_members_repository.h
repositories/dynamic_zone_templates_repository.h
repositories/eventlog_repository.h repositories/eventlog_repository.h
repositories/expeditions_repository.h repositories/expeditions_repository.h
repositories/expedition_lockouts_repository.h repositories/expedition_lockouts_repository.h
repositories/faction_association_repository.h
repositories/faction_base_data_repository.h repositories/faction_base_data_repository.h
repositories/faction_list_repository.h repositories/faction_list_repository.h
repositories/faction_list_mod_repository.h repositories/faction_list_mod_repository.h
@@ -389,15 +368,18 @@ SET(repositories
repositories/friends_repository.h repositories/friends_repository.h
repositories/global_loot_repository.h repositories/global_loot_repository.h
repositories/gm_ips_repository.h repositories/gm_ips_repository.h
repositories/goallists_repository.h
repositories/graveyard_repository.h repositories/graveyard_repository.h
repositories/grid_repository.h
repositories/grid_entries_repository.h
repositories/ground_spawns_repository.h repositories/ground_spawns_repository.h
repositories/group_id_repository.h repositories/group_id_repository.h
repositories/group_leaders_repository.h repositories/group_leaders_repository.h
repositories/guilds_repository.h repositories/guilds_repository.h
repositories/guild_members_repository.h
repositories/guild_ranks_repository.h repositories/guild_ranks_repository.h
repositories/guild_relations_repository.h repositories/guild_relations_repository.h
repositories/hackers_repository.h repositories/hackers_repository.h
repositories/horses_repository.h
repositories/instance_list_repository.h repositories/instance_list_repository.h
repositories/instance_list_player_repository.h repositories/instance_list_player_repository.h
repositories/inventory_repository.h repositories/inventory_repository.h
@@ -438,10 +420,10 @@ SET(repositories
repositories/perl_event_export_settings_repository.h repositories/perl_event_export_settings_repository.h
repositories/petitions_repository.h repositories/petitions_repository.h
repositories/pets_repository.h repositories/pets_repository.h
repositories/pets_beastlord_data_repository.h
repositories/pets_equipmentset_repository.h repositories/pets_equipmentset_repository.h
repositories/pets_equipmentset_entries_repository.h repositories/pets_equipmentset_entries_repository.h
repositories/player_titlesets_repository.h repositories/player_titlesets_repository.h
repositories/proximities_repository.h
repositories/quest_globals_repository.h repositories/quest_globals_repository.h
repositories/raid_details_repository.h repositories/raid_details_repository.h
repositories/raid_members_repository.h repositories/raid_members_repository.h
@@ -482,10 +464,13 @@ SET(repositories
repositories/zone_repository.h repositories/zone_repository.h
repositories/zone_points_repository.h repositories/zone_points_repository.h
# Non-Comformative
repositories/character_recipe_list_repository.h
) )
SET(common_headers SET(common_headers
additive_lagged_fibonacci_engine.h additive_lagged_fibonacci_engine.h
any.h
base_packet.h base_packet.h
base_data.h base_data.h
bodytypes.h bodytypes.h
@@ -506,8 +491,6 @@ SET(common_headers
database_schema.h database_schema.h
dbcore.h dbcore.h
deity.h deity.h
discord/discord.h
discord_manager.h
dynamic_zone_base.h dynamic_zone_base.h
emu_constants.h emu_constants.h
emu_limits.h emu_limits.h
@@ -535,7 +518,7 @@ SET(common_headers
expedition_lockout_timer.h expedition_lockout_timer.h
extprofile.h extprofile.h
faction.h faction.h
file.h file_util.h
features.h features.h
fixed_memory_hash_set.h fixed_memory_hash_set.h
fixed_memory_variable_hash_set.h fixed_memory_variable_hash_set.h
@@ -571,9 +554,7 @@ SET(common_headers
packet_dump.h packet_dump.h
packet_dump_file.h packet_dump_file.h
packet_functions.h packet_functions.h
path_manager.cpp
platform.h platform.h
process/process.h
proc_launcher.h proc_launcher.h
profanity_manager.h profanity_manager.h
profiler.h profiler.h
@@ -594,7 +575,7 @@ SET(common_headers
shareddb.h shareddb.h
skills.h skills.h
spdat.h spdat.h
strings.h string_util.h
struct_strategy.h struct_strategy.h
tasks.h tasks.h
textures.h textures.h
@@ -604,7 +585,6 @@ SET(common_headers
useperl.h useperl.h
version.h version.h
zone_numbers.h zone_numbers.h
zone_store.h
event/event_loop.h event/event_loop.h
event/task.h event/task.h
event/timer.h event/timer.h
@@ -656,8 +636,6 @@ SET(common_headers
patches/uf_limits.h patches/uf_limits.h
patches/uf_ops.h patches/uf_ops.h
patches/uf_structs.h patches/uf_structs.h
termcolor/rang.hpp
stacktrace/backward.hpp
StackWalker/StackWalker.h StackWalker/StackWalker.h
util/memory_stream.h util/memory_stream.h
util/directory.h util/directory.h
+190
View File
@@ -0,0 +1,190 @@
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
// EQ::Any is a modified version of Boost::Any and as such retains the Boost licensing.
#ifndef EQEMU_COMMON_ANY_H
#define EQEMU_COMMON_ANY_H
#include <algorithm>
#include <typeinfo>
namespace EQ
{
class Any
{
public:
Any()
: content(nullptr)
{
}
template<typename ValueType>
Any(const ValueType &value)
: content(new Holder<ValueType>(value))
{
}
Any(const Any &other)
: content(other.content ? other.content->clone() : 0)
{
}
~Any()
{
if(content)
delete content;
}
Any& swap(Any &rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
Any& operator=(const ValueType &rhs)
{
Any(rhs).swap(*this);
return *this;
}
Any& operator=(Any rhs)
{
rhs.swap(*this);
return *this;
}
bool empty() const
{
return !content;
}
const std::type_info& type() const
{
return content ? content->type() : typeid(void);
}
class Placeholder
{
public:
virtual ~Placeholder()
{
}
virtual const std::type_info& type() const = 0;
virtual Placeholder* clone() const = 0;
};
template<typename ValueType>
class Holder : public Placeholder
{
public:
Holder(const ValueType &value)
: held(value)
{
}
virtual const std::type_info& type() const
{
return typeid(ValueType);
}
virtual Placeholder* clone() const
{
return new Holder(held);
}
ValueType held;
private:
Holder& operator=(const Holder&);
};
private:
template<typename ValueType>
friend ValueType* any_cast(Any*);
template<typename ValueType>
friend ValueType* unsafe_any_cast(Any*);
Placeholder* content;
};
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{
return "DBI::bad_any_cast: failed conversion using DBI::any_cast";
}
};
template<typename ValueType>
ValueType* any_cast(Any* operand)
{
return operand &&
operand->type() == typeid(ValueType) ? &static_cast<Any::Holder<ValueType>*>(operand->content)->held : nullptr;
}
template<typename ValueType>
inline const ValueType* any_cast(const Any* operand)
{
return any_cast<ValueType>(const_cast<Any*>(operand));
}
template<typename ValueType>
ValueType any_cast(Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
nonref* result = any_cast<nonref>(&operand);
if(!result)
throw bad_any_cast();
return *result;
}
template<typename ValueType>
inline ValueType any_cast(const Any& operand)
{
typedef typename std::remove_reference<ValueType>::type nonref;
return any_cast<const nonref&>(const_cast<Any&>(operand));
}
template<typename ValueType>
inline ValueType* unsafe_any_cast(Any* operand)
{
return &static_cast<Any::Holder<ValueType>*>(operand->content)->held;
}
template<typename ValueType>
inline const ValueType* unsafe_any_cast(const Any* operand)
{
return unsafe_any_cast<ValueType>(const_cast<Any*>(operand));
}
}
#endif
+8 -8
View File
@@ -23,18 +23,18 @@
BasePacket::BasePacket(const unsigned char *buf, uint32 len) BasePacket::BasePacket(const unsigned char *buf, uint32 len)
{ {
pBuffer=nullptr; this->pBuffer=nullptr;
size=0; this->size=0;
_wpos = 0; this->_wpos = 0;
_rpos = 0; this->_rpos = 0;
timestamp.tv_sec = 0; this->timestamp.tv_sec = 0;
if (len>0) { if (len>0) {
size=len; this->size=len;
pBuffer= new unsigned char[len]; pBuffer= new unsigned char[len];
if (buf) { if (buf) {
memcpy(pBuffer,buf,len); memcpy(this->pBuffer,buf,len);
} else { } else {
memset(pBuffer,0,len); memset(this->pBuffer,0,len);
} }
} }
} }
+5 -5
View File
@@ -380,12 +380,12 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Merchant"; return "Merchant";
case DISCORD_MERCHANT: case DISCORD_MERCHANT:
return "Discord Merchant"; return "Discord Merchant";
case ADVENTURE_RECRUITER: case ADVENTURERECRUITER:
return "Adventure Recruiter"; return "Adventure Recruiter";
case ADVENTURE_MERCHANT: case ADVENTUREMERCHANT:
return "Adventure Merchant"; return "Adventure Merchant";
case LDON_TREASURE: case CORPSE_CLASS:
return "LDoN Treasure"; return "Corpse Class";
case TRIBUTE_MASTER: case TRIBUTE_MASTER:
return "Tribute Master"; return "Tribute Master";
case GUILD_TRIBUTE_MASTER: case GUILD_TRIBUTE_MASTER:
@@ -400,7 +400,7 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Fellowship Master"; return "Fellowship Master";
case ALT_CURRENCY_MERCHANT: case ALT_CURRENCY_MERCHANT:
return "Alternate Currency Merchant"; return "Alternate Currency Merchant";
case MERCENARY_MASTER: case MERCERNARY_MASTER:
return "Mercenary Liaison"; return "Mercenary Liaison";
default: default:
return "Unknown"; return "Unknown";
+5 -5
View File
@@ -20,7 +20,6 @@
#include "../common/types.h" #include "../common/types.h"
#define NO_CLASS 0
#define WARRIOR 1 #define WARRIOR 1
#define CLERIC 2 #define CLERIC 2
#define PALADIN 3 #define PALADIN 3
@@ -56,9 +55,10 @@
#define BANKER 40 #define BANKER 40
#define MERCHANT 41 #define MERCHANT 41
#define DISCORD_MERCHANT 59 #define DISCORD_MERCHANT 59
#define ADVENTURE_RECRUITER 60 #define ADVENTURERECRUITER 60
#define ADVENTURE_MERCHANT 61 #define ADVENTUREMERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva #define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs
#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far..
#define TRIBUTE_MASTER 63 #define TRIBUTE_MASTER 63
#define GUILD_TRIBUTE_MASTER 64 // not sure #define GUILD_TRIBUTE_MASTER 64 // not sure
#define GUILD_BANKER 66 #define GUILD_BANKER 66
@@ -66,7 +66,7 @@
#define DARK_REIGN_MERCHANT 68 #define DARK_REIGN_MERCHANT 68
#define FELLOWSHIP_MASTER 69 #define FELLOWSHIP_MASTER 69
#define ALT_CURRENCY_MERCHANT 70 #define ALT_CURRENCY_MERCHANT 70
#define MERCENARY_MASTER 71 #define MERCERNARY_MASTER 71
// player class values // player class values
+13 -134
View File
@@ -22,7 +22,6 @@
#include "../database.h" #include "../database.h"
#include "../rulesys.h" #include "../rulesys.h"
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../loottable.h"
#include "../repositories/content_flags_repository.h" #include "../repositories/content_flags_repository.h"
@@ -36,12 +35,8 @@ int WorldContentService::GetCurrentExpansion() const
return current_expansion; return current_expansion;
} }
WorldContentService *WorldContentService::SetExpansionContext() void WorldContentService::SetExpansionContext()
{ {
// do a rule manager reload until where we store expansion is changed to somewhere else
RuleManager::Instance()->LoadRules(GetDatabase(), "default", true);
// pull expansion from rules
int expansion = RuleI(Expansion, CurrentExpansion); int expansion = RuleI(Expansion, CurrentExpansion);
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) { if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
content_service.SetCurrentExpansion(expansion); content_service.SetCurrentExpansion(expansion);
@@ -52,8 +47,6 @@ WorldContentService *WorldContentService::SetExpansionContext()
GetCurrentExpansion(), GetCurrentExpansion(),
GetCurrentExpansionName() GetCurrentExpansionName()
); );
return this;
} }
std::string WorldContentService::GetCurrentExpansionName() std::string WorldContentService::GetCurrentExpansionName()
@@ -80,47 +73,15 @@ void WorldContentService::SetCurrentExpansion(int current_expansion)
/** /**
* @return * @return
*/ */
const std::vector<ContentFlagsRepository::ContentFlags> &WorldContentService::GetContentFlags() const const std::vector<std::string> &WorldContentService::GetContentFlags() const
{ {
return content_flags; return content_flags;
} }
/**
* @return
*/
std::vector<std::string> WorldContentService::GetContentFlagsEnabled()
{
std::vector<std::string> enabled_flags;
for (auto &f: GetContentFlags()) {
if (f.enabled) {
enabled_flags.emplace_back(f.flag_name);
}
}
return enabled_flags;
}
/**
* @return
*/
std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
{
std::vector<std::string> disabled_flags;
for (auto &f: GetContentFlags()) {
if (!f.enabled) {
disabled_flags.emplace_back(f.flag_name);
}
}
return disabled_flags;
}
/** /**
* @param content_flags * @param content_flags
*/ */
void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags) void WorldContentService::SetContentFlags(std::vector<std::string> content_flags)
{ {
WorldContentService::content_flags = content_flags; WorldContentService::content_flags = content_flags;
} }
@@ -131,8 +92,8 @@ void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::Co
*/ */
bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag) bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag)
{ {
for (auto &f: GetContentFlags()) { for (auto &flag : GetContentFlags()) {
if (f.flag_name == content_flag && f.enabled == true) { if (flag == content_flag) {
return true; return true;
} }
} }
@@ -140,102 +101,20 @@ bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
return false; return false;
} }
/** void WorldContentService::ReloadContentFlags(Database &db)
* @param content_flag
* @return
*/
bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
{ {
for (auto &f: GetContentFlags()) { std::vector<std::string> set_content_flags;
if (f.flag_name == content_flag && f.enabled == false) { auto content_flags = ContentFlagsRepository::GetWhere(db, "enabled = 1");
return true;
}
}
return false; set_content_flags.reserve(content_flags.size());
for (auto &flags: content_flags) {
set_content_flags.push_back(flags.flag_name);
} }
bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f)
{
// if we're not set to (-1 All) then fail when we aren't within minimum expansion
if (f.min_expansion > Expansion::EXPANSION_ALL && current_expansion < f.min_expansion && current_expansion != -1) {
return false;
}
// if we're not set to (-1 All) then fail when we aren't within max expansion
if (f.max_expansion > Expansion::EXPANSION_ALL && current_expansion > f.max_expansion && current_expansion != -1) {
return false;
}
// if we don't have any enabled flag in enabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags)) {
if (!Strings::Contains(GetContentFlagsEnabled(), flag)) {
return false;
}
}
// if we don't have any disabled flag in disabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags_disabled)) {
if (!Strings::Contains(GetContentFlagsDisabled(), flag)) {
return false;
}
}
return true;
}
void WorldContentService::ReloadContentFlags()
{
std::vector<ContentFlagsRepository::ContentFlags> set_content_flags;
auto flags = ContentFlagsRepository::All(*GetDatabase());
set_content_flags.reserve(flags.size());
for (auto &f: flags) {
set_content_flags.push_back(f);
LogInfo( LogInfo(
"Loaded content flag [{}] [{}]", "Enabled content flags [{}]",
f.flag_name, implode(", ", set_content_flags)
(f.enabled ? "Enabled" : "Disabled")
); );
}
SetContentFlags(set_content_flags); SetContentFlags(set_content_flags);
} }
Database *WorldContentService::GetDatabase() const
{
return m_database;
}
WorldContentService *WorldContentService::SetDatabase(Database *database)
{
WorldContentService::m_database = database;
return this;
}
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
{
auto flags = ContentFlagsRepository::GetWhere(
*GetDatabase(),
fmt::format("flag_name = '{}'", content_flag_name)
);
auto f = ContentFlagsRepository::NewEntity();
if (!flags.empty()) {
f = flags.front();
}
f.enabled = enabled ? 1 : 0;
f.flag_name = content_flag_name;
if (!flags.empty()) {
ContentFlagsRepository::UpdateOne(*GetDatabase(), f);
}
else {
ContentFlagsRepository::InsertOne(*GetDatabase(), f);
}
ReloadContentFlags();
}
+10 -25
View File
@@ -23,8 +23,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "../loottable.h"
#include "../repositories/content_flags_repository.h"
class Database; class Database;
@@ -54,7 +52,7 @@ namespace Expansion {
VeilOfAlaris, VeilOfAlaris,
RainOfFear, RainOfFear,
CallOfTheForsaken, CallOfTheForsaken,
TheDarkenedSea, TheDarkendSea,
TheBrokenMirror, TheBrokenMirror,
EmpiresOfKunark, EmpiresOfKunark,
RingOfScale, RingOfScale,
@@ -127,7 +125,7 @@ public:
bool IsVeilOfAlarisEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::VeilOfAlaris || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsVeilOfAlarisEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::VeilOfAlaris || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsRainOfFearEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RainOfFear || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsRainOfFearEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RainOfFear || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsCallOfTheForsakenEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::CallOfTheForsaken || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsCallOfTheForsakenEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::CallOfTheForsaken || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheDarkenedSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheDarkenedSea || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsTheDarkendSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheDarkendSea || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsTheBrokenMirrorEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBrokenMirror || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsTheBrokenMirrorEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBrokenMirror || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsEmpiresOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::EmpiresOfKunark || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsEmpiresOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::EmpiresOfKunark || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
bool IsRingOfScaleEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RingOfScale || GetCurrentExpansion() == Expansion::EXPANSION_ALL; } bool IsRingOfScaleEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RingOfScale || GetCurrentExpansion() == Expansion::EXPANSION_ALL; }
@@ -155,35 +153,22 @@ public:
bool IsCurrentExpansionVeilOfAlaris() { return current_expansion == Expansion::ExpansionNumber::VeilOfAlaris; } bool IsCurrentExpansionVeilOfAlaris() { return current_expansion == Expansion::ExpansionNumber::VeilOfAlaris; }
bool IsCurrentExpansionRainOfFear() { return current_expansion == Expansion::ExpansionNumber::RainOfFear; } bool IsCurrentExpansionRainOfFear() { return current_expansion == Expansion::ExpansionNumber::RainOfFear; }
bool IsCurrentExpansionCallOfTheForsaken() { return current_expansion == Expansion::ExpansionNumber::CallOfTheForsaken; } bool IsCurrentExpansionCallOfTheForsaken() { return current_expansion == Expansion::ExpansionNumber::CallOfTheForsaken; }
bool IsCurrentExpansionTheDarkenedSea() { return current_expansion == Expansion::ExpansionNumber::TheDarkenedSea; } bool IsCurrentExpansionTheDarkendSea() { return current_expansion == Expansion::ExpansionNumber::TheDarkendSea; }
bool IsCurrentExpansionTheBrokenMirror() { return current_expansion == Expansion::ExpansionNumber::TheBrokenMirror; } bool IsCurrentExpansionTheBrokenMirror() { return current_expansion == Expansion::ExpansionNumber::TheBrokenMirror; }
bool IsCurrentExpansionEmpiresOfKunark() { return current_expansion == Expansion::ExpansionNumber::EmpiresOfKunark; } bool IsCurrentExpansionEmpiresOfKunark() { return current_expansion == Expansion::ExpansionNumber::EmpiresOfKunark; }
bool IsCurrentExpansionRingOfScale() { return current_expansion == Expansion::ExpansionNumber::RingOfScale; } bool IsCurrentExpansionRingOfScale() { return current_expansion == Expansion::ExpansionNumber::RingOfScale; }
bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; } bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; }
bool IsCurrentExpansionTormentOfVelious() { return current_expansion == Expansion::ExpansionNumber::TormentOfVelious; } bool IsCurrentExpansionTormentOfVelious() { return current_expansion == Expansion::ExpansionNumber::TormentOfVelious; }
const std::vector<ContentFlagsRepository::ContentFlags> &GetContentFlags() const;
std::vector<std::string> GetContentFlagsEnabled();
std::vector<std::string> GetContentFlagsDisabled();
bool IsContentFlagEnabled(const std::string& content_flag);
bool IsContentFlagDisabled(const std::string& content_flag);
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
void ReloadContentFlags();
WorldContentService * SetExpansionContext();
bool DoesPassContentFiltering(const ContentFlags& f);
WorldContentService * SetDatabase(Database *database);
Database *GetDatabase() const;
void SetContentFlag(const std::string &content_flag_name, bool enabled);
private: private:
int current_expansion{}; int current_expansion{};
std::vector<ContentFlagsRepository::ContentFlags> content_flags; std::vector<std::string> content_flags;
public:
// reference to database const std::vector<std::string> &GetContentFlags() const;
Database *m_database; bool IsContentFlagEnabled(const std::string& content_flag);
void SetContentFlags(std::vector<std::string> content_flags);
void ReloadContentFlags(Database &db);
void SetExpansionContext();
}; };
extern WorldContentService content_service; extern WorldContentService content_service;
+5 -141
View File
@@ -1,98 +1,6 @@
#include "global_define.h" #include "global_define.h"
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "crash.h" #include "crash.h"
#include "strings.h"
#include "process/process.h"
#include "http/httplib.h"
#include "http/uri.h"
#include "json/json.h"
#include "version.h"
#include "eqemu_config.h"
#include "serverinfo.h"
#include "rulesys.h"
#include "platform.h"
#include <cstdio>
#include <vector>
#if WINDOWS
#define popen _popen
#endif
void SendCrashReport(const std::string &crash_report)
{
// can configure multiple endpoints if need be
std::vector<std::string> endpoints = {
"http://spire.akkadius.com/api/v1/analytics/server-crash-report",
// "http://localhost:3010/api/v1/analytics/server-crash-report", // development
};
auto config = EQEmuConfig::get();
for (auto &e: endpoints) {
uri u(e);
std::string base_url = fmt::format("{}://{}", u.get_scheme(), u.get_host());
if (u.get_port()) {
base_url += fmt::format(":{}", u.get_port());
}
// client
httplib::Client r(base_url);
r.set_connection_timeout(1, 0);
r.set_read_timeout(1, 0);
r.set_write_timeout(1, 0);
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
// os info
auto os = EQ::GetOS();
auto cpus = EQ::GetCPUs();
auto process_id = EQ::GetPID();
auto rss = EQ::GetRSS() / 1048576.0;
auto uptime = static_cast<uint32>(EQ::GetUptime());
// payload
Json::Value p;
p["platform_name"] = GetPlatformName();
p["crash_report"] = crash_report;
p["server_version"] = CURRENT_VERSION;
p["compile_date"] = COMPILE_DATE;
p["compile_time"] = COMPILE_TIME;
p["server_name"] = config->LongName;
p["server_short_name"] = config->ShortName;
p["uptime"] = uptime;
p["os_machine"] = os.machine;
p["os_release"] = os.release;
p["os_version"] = os.version;
p["os_sysname"] = os.sysname;
p["process_id"] = process_id;
p["rss_memory"] = rss;
p["cpus"] = cpus.size();
p["origination_info"] = "";
if (!LogSys.origination_info.zone_short_name.empty()) {
p["origination_info"] = fmt::format(
"{} ({}) instance_id [{}]",
LogSys.origination_info.zone_short_name,
LogSys.origination_info.zone_long_name,
LogSys.origination_info.instance_id
);
}
std::stringstream payload;
payload << p;
if (auto res = r.Post(e, payload.str(), "application/json")) {
if (res->status == 200) {
LogInfo("Sent crash report");
}
else {
LogError("Failed to send crash report to [{}]", e);
}
}
}
}
#if defined(_WINDOWS) && defined(CRASH_LOGGING) #if defined(_WINDOWS) && defined(CRASH_LOGGING)
#include "StackWalker.h" #include "StackWalker.h"
@@ -112,22 +20,14 @@ public:
if(szText[i] == '\n' || szText[i] == '\r') { if(szText[i] == '\n' || szText[i] == '\r') {
buffer[i] = ' '; buffer[i] = ' ';
} } else {
else {
buffer[i] = szText[i]; buffer[i] = szText[i];
} }
} }
std::string line = buffer;
_lines.push_back(line);
Log(Logs::General, Logs::Crash, buffer); Log(Logs::General, Logs::Crash, buffer);
StackWalker::OnOutput(szText); StackWalker::OnOutput(szText);
} }
const std::vector<std::string>& const GetLines() { return _lines; }
private:
std::vector<std::string> _lines;
}; };
LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
@@ -201,20 +101,7 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
{ {
EQEmuStackWalker sw; EQEmuStackWalker sw; sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
if (RuleB(Analytics, CrashReporting)) {
std::string crash_report;
auto& lines = sw.GetLines();
for (auto& line : lines) {
crash_report += line;
crash_report += "\n";
}
SendCrashReport(crash_report);
}
} }
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
@@ -238,27 +125,9 @@ void set_exception_handler() {
void print_trace() void print_trace()
{ {
bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU");
if (!does_gdb_exist) {
LogCrash(
"[Error] GDB is not installed, if you want crash dumps on Linux to work properly you will need GDB installed"
);
std::exit(1);
}
auto uid = geteuid(); auto uid = geteuid();
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
// check for passwordless sudo if not root std::string temp_output_file = "/tmp/dump-output";
if (uid != 0) {
bool sudo_password_required = Strings::Contains(Process::execute("sudo -n true"), "a password is required");
if (sudo_password_required) {
LogCrash(
"[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root."
);
std::exit(1);
}
}
char pid_buf[30]; char pid_buf[30];
sprintf(pid_buf, "%d", getpid()); sprintf(pid_buf, "%d", getpid());
@@ -267,6 +136,7 @@ void print_trace()
int child_pid = fork(); int child_pid = fork();
if (!child_pid) { if (!child_pid) {
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
dup2(fd, 1); // redirect output to stderr dup2(fd, 1); // redirect output to stderr
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf); fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
if (uid == 0) { if (uid == 0) {
@@ -281,22 +151,16 @@ void print_trace()
abort(); /* If gdb failed to start */ abort(); /* If gdb failed to start */
} }
else { else {
waitpid(child_pid, nullptr, 0); waitpid(child_pid, NULL, 0);
} }
std::ifstream input(temp_output_file); std::ifstream input(temp_output_file);
std::string crash_report;
for (std::string line; getline(input, line);) { for (std::string line; getline(input, line);) {
LogCrash("{}", line); LogCrash("{}", line);
crash_report += fmt::format("{}\n", line);
} }
std::remove(temp_output_file.c_str()); std::remove(temp_output_file.c_str());
if (RuleB(Analytics, CrashReporting)) {
SendCrashReport(crash_report);
}
exit(1); exit(1);
} }
+328 -239
View File
@@ -45,14 +45,11 @@
#include "database.h" #include "database.h"
#include "eq_packet_structs.h" #include "eq_packet_structs.h"
#include "extprofile.h" #include "extprofile.h"
#include "strings.h" #include "string_util.h"
#include "database_schema.h" #include "database_schema.h"
#include "http/httplib.h" #include "http/httplib.h"
#include "http/uri.h" #include "http/uri.h"
#include "repositories/zone_repository.h"
#include "zone_store.h"
extern Client client; extern Client client;
Database::Database () { Database::Database () {
@@ -71,11 +68,11 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c
uint32 errnum= 0; uint32 errnum= 0;
char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf[MYSQL_ERRMSG_SIZE];
if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { if (!Open(host, user, passwd, database, port, &errnum, errbuf)) {
LogError("Connection [{}] Failed to connect to database Error [{}]", connection_label, errbuf); LogError("[MySQL] Connection [{}] Failed to connect to database: Error [{}]", connection_label, errbuf);
return false; return false;
} }
else { else {
LogInfo("Connected to database [{}] [{}] @ [{}:{}]", connection_label, database, host,port); LogInfo("[MySQL] Connection [{}] database [{}] at [{}]:[{}]", connection_label, database, host,port);
return true; return true;
} }
} }
@@ -98,120 +95,109 @@ uint32 Database::CheckLogin(const char* name, const char* password, const char *
if(strlen(name) >= 50 || strlen(password) >= 50) if(strlen(name) >= 50 || strlen(password) >= 50)
return(0); return(0);
char temporary_username[100]; char tmpUN[100];
char temporary_password[100]; char tmpPW[100];
DoEscapeString(temporary_username, name, strlen(name)); DoEscapeString(tmpUN, name, strlen(name));
DoEscapeString(temporary_password, password, strlen(password)); DoEscapeString(tmpPW, password, strlen(password));
std::string query = fmt::format( std::string query = StringFormat("SELECT id, status FROM account WHERE `name`='%s' AND ls_id='%s' AND password is not null "
"SELECT id, status FROM account WHERE `name` = '{}' AND ls_id = '{}' AND password is NOT NULL " "and length(password) > 0 and (password='%s' or password=MD5('%s'))",
"AND length(password) > 0 AND (password = '{}' OR password = MD5('{}'))", tmpUN, EscapeString(loginserver).c_str(), tmpPW, tmpPW);
temporary_username,
Strings::Escape(loginserver),
temporary_password,
temporary_password
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) { if (!results.Success())
{
return 0; return 0;
} }
if(results.RowCount() == 0)
return 0;
auto row = results.begin(); auto row = results.begin();
auto id = std::stoul(row[0]); uint32 id = atoi(row[0]);
if (oStatus) { if (oStatus)
*oStatus = std::stoi(row[1]); *oStatus = atoi(row[1]);
}
return id; return id;
} }
//Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. //Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table.
bool Database::CheckBannedIPs(std::string login_ip) bool Database::CheckBannedIPs(const char* loginIP)
{ {
auto query = fmt::format( std::string query = StringFormat("SELECT ip_address FROM banned_ips WHERE ip_address='%s'", loginIP);
"SELECT ip_address FROM banned_ips WHERE ip_address = '{}'",
login_ip
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() != 0) { if (!results.Success())
{
return true; return true;
} }
if (results.RowCount() != 0)
return true;
return false; return false;
} }
bool Database::AddBannedIP(std::string banned_ip, std::string notes) { bool Database::AddBannedIP(char* bannedIP, const char* notes) {
auto query = fmt::format( std::string query = StringFormat("INSERT into banned_ips SET ip_address='%s', notes='%s'", bannedIP, notes);
"INSERT into banned_ips SET ip_address = '{}', notes = '{}'",
Strings::Escape(banned_ip),
Strings::Escape(notes)
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return false; return false;
} }
return true; return true;
} }
bool Database::CheckGMIPs(std::string login_ip, uint32 account_id) { bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) {
auto query = fmt::format( std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id);
"SELECT * FROM `gm_ips` WHERE `ip_address` = '{}' AND `account_id` = {}",
login_ip,
account_id
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success())
return false; return false;
}
if (results.RowCount() == 1) { if (results.RowCount() == 1)
return true; return true;
}
return false; return false;
} }
void Database::LoginIP(uint32 account_id, std::string login_ip) { bool Database::AddGMIP(char* ip_address, char* name) {
auto query = fmt::format( std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name);
"INSERT INTO account_ip SET accid = {}, ip = '{}' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", auto results = QueryDatabase(query);
account_id, return results.Success();
login_ip }
);
void Database::LoginIP(uint32 AccountID, const char* LoginIP) {
std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP);
QueryDatabase(query); QueryDatabase(query);
} }
int16 Database::CheckStatus(uint32 account_id) int16 Database::CheckStatus(uint32 account_id)
{ {
auto query = fmt::format( std::string query = StringFormat(
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = {}", "SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = %i",
account_id account_id);
);
auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() != 1) { auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() != 1)
return 0; return 0;
}
auto row = results.begin(); auto row = results.begin();
int16 status = std::stoi(row[0]); int16 status = atoi(row[0]);
int32 date_diff = 0; int32 date_diff = 0;
if (row[1]) { if (row[1] != nullptr)
date_diff = std::stoi(row[1]); date_diff = atoi(row[1]);
}
if (date_diff > 0) { if (date_diff > 0)
return -1; return -1;
}
return status; return status;
} }
@@ -281,7 +267,7 @@ bool Database::DeleteAccount(const char* name, const char *loginserver) {
} }
bool Database::SetLocalPassword(uint32 accid, const char* password) { bool Database::SetLocalPassword(uint32 accid, const char* password) {
std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", Strings::Escape(password).c_str(), accid); std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", EscapeString(password).c_str(), accid);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -321,7 +307,9 @@ bool Database::SetAccountStatus(const std::string& account_name, int16 status)
LogInfo("Account [{}] is attempting to be set to status [{}]", account_name, status); LogInfo("Account [{}] is attempting to be set to status [{}]", account_name, status);
std::string query = fmt::format( std::string query = fmt::format(
"UPDATE account SET status = {} WHERE name = '{}'", SQL(
UPDATE account SET status = {} WHERE name = '{}'
),
status, status,
account_name account_name
); );
@@ -376,8 +364,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
* @param character_name * @param character_name
* @return * @return
*/ */
bool Database::DeleteCharacter(char *character_name) bool Database::DeleteCharacter(char *character_name) {
{
uint32 character_id = 0; uint32 character_id = 0;
if(!character_name || !strlen(character_name)) { if(!character_name || !strlen(character_name)) {
LogInfo("DeleteCharacter: request to delete without a name (empty char slot)"); LogInfo("DeleteCharacter: request to delete without a name (empty char slot)");
@@ -391,14 +378,14 @@ bool Database::DeleteCharacter(char *character_name)
} }
if (character_id <= 0) { if (character_id <= 0) {
LogError("Invalid Character ID [{}]", character_name); LogError("DeleteCharacter | Invalid Character ID [{}]", character_name);
return false; return false;
} }
std::string delete_type = "hard-deleted"; std::string delete_type = "hard-deleted";
if (RuleB(Character, SoftDeletes)) { if (RuleB(Character, SoftDeletes)) {
delete_type = "soft-deleted"; delete_type = "soft-deleted";
query = fmt::format( std::string query = fmt::format(
SQL( SQL(
UPDATE UPDATE
character_data character_data
@@ -413,30 +400,11 @@ bool Database::DeleteCharacter(char *character_name)
QueryDatabase(query); QueryDatabase(query);
if (RuleB(Bots, Enabled)) {
query = fmt::format(
SQL(
UPDATE
bot_data
SET
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64)
WHERE
owner_id = '{}'
),
character_id
);
QueryDatabase(query);
LogInfo(
"[DeleteCharacter] character_name [{}] ({}) bots are being [{}]",
character_name,
character_id,
delete_type
);
}
return true; return true;
} }
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
for (const auto& iter : DatabaseSchema::GetCharacterTables()) { for (const auto& iter : DatabaseSchema::GetCharacterTables()) {
std::string table_name = iter.first; std::string table_name = iter.first;
std::string character_id_column_name = iter.second; std::string character_id_column_name = iter.second;
@@ -444,7 +412,11 @@ bool Database::DeleteCharacter(char *character_name)
QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id)); QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id));
} }
LogInfo("character_name [{}] ({}) is being [{}]", character_name, character_id, delete_type); #ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
QueryDatabase(query);
#endif
return true; return true;
} }
@@ -636,8 +608,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
")", ")",
character_id, // " id, " character_id, // " id, "
account_id, // " account_id, " account_id, // " account_id, "
Strings::Escape(pp->name).c_str(), // " `name`, " EscapeString(pp->name).c_str(), // " `name`, "
Strings::Escape(pp->last_name).c_str(), // " last_name, " EscapeString(pp->last_name).c_str(), // " last_name, "
pp->gender, // " gender, " pp->gender, // " gender, "
pp->race, // " race, " pp->race, // " race, "
pp->class_, // " class, " pp->class_, // " class, "
@@ -661,8 +633,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
pp->ability_number, // " ability_number, " pp->ability_number, // " ability_number, "
pp->ability_time_minutes, // " ability_time_minutes, " pp->ability_time_minutes, // " ability_time_minutes, "
pp->ability_time_hours, // " ability_time_hours, " pp->ability_time_hours, // " ability_time_hours, "
Strings::Escape(pp->title).c_str(), // " title, " EscapeString(pp->title).c_str(), // " title, "
Strings::Escape(pp->suffix).c_str(), // " suffix, " EscapeString(pp->suffix).c_str(), // " suffix, "
pp->exp, // " exp, " pp->exp, // " exp, "
pp->points, // " points, " pp->points, // " points, "
pp->mana, // " mana, " pp->mana, // " mana, "
@@ -744,7 +716,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
/* HoTT Ability */ /* HoTT Ability */
if(RuleB(Character, GrantHoTTOnCreate)) if(RuleB(Character, GrantHoTTOnCreate))
{ {
query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)", character_id, 14, 1); query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, rank) VALUES (%u, %i, %i)", character_id, 14, 1);
results = QueryDatabase(query); results = QueryDatabase(query);
} }
@@ -798,7 +770,7 @@ uint32 Database::GetCharacterID(const char *name) {
Zero will also be returned if there is a database error. Zero will also be returned if there is a database error.
*/ */
uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) {
std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", Strings::Escape(charname).c_str()); std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", EscapeString(charname).c_str());
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -835,34 +807,36 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) {
return atoi(row[0]); return atoi(row[0]);
} }
uint32 Database::GetAccountIDByName(std::string account_name, std::string loginserver, int16* status, uint32* lsid) { uint32 Database::GetAccountIDByName(const char* accname, const char *loginserver, int16* status, uint32* lsid) {
if (!isAlphaNumeric(account_name.c_str())) { if (!isAlphaNumeric(accname))
return 0; return 0;
}
auto query = fmt::format( std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' AND `ls_id`='%s' LIMIT 1",
"SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '{}' AND `ls_id` = '{}' LIMIT 1", EscapeString(accname).c_str(), EscapeString(loginserver).c_str());
Strings::Escape(account_name),
Strings::Escape(loginserver)
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) { if (!results.Success()) {
return 0; return 0;
} }
auto row = results.begin(); if (results.RowCount() != 1)
auto account_id = std::stoul(row[0]); return 0;
if (status) { auto row = results.begin();
*status = static_cast<int16>(std::stoi(row[1]));
} uint32 id = atoi(row[0]);
if (status)
*status = atoi(row[1]);
if (lsid) { if (lsid) {
*lsid = row[2] ? std::stoul(row[2]) : 0; if (row[2])
*lsid = atoi(row[2]);
else
*lsid = 0;
} }
return account_id; return id;
} }
void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) {
@@ -975,8 +949,6 @@ bool Database::LoadVariables() {
varcache.Add(key, value); varcache.Add(key, value);
} }
LogInfo("Loaded [{}] variable(s)", Strings::Commify(std::to_string(results.RowCount())));
return true; return true;
} }
@@ -1001,8 +973,8 @@ bool Database::GetVariable(std::string varname, std::string &varvalue)
bool Database::SetVariable(const std::string varname, const std::string &varvalue) bool Database::SetVariable(const std::string varname, const std::string &varvalue)
{ {
std::string escaped_name = Strings::Escape(varname); std::string escaped_name = EscapeString(varname);
std::string escaped_value = Strings::Escape(varvalue); std::string escaped_value = EscapeString(varvalue);
std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str()); std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str());
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@@ -1025,16 +997,110 @@ bool Database::SetVariable(const std::string varname, const std::string &varvalu
return true; return true;
} }
void Database::SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum) // Get zone starting points from DB
{ bool Database::GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x, float* safe_y, float* safe_z, float* safe_heading, int16* min_status, uint8* min_level, char *flag_needed) {
QueryDatabase(
fmt::format( if (zone_short_name == nullptr)
"UPDATE `account` SET `{}` = '{}' WHERE `id` = {}", return false;
field_name,
checksum, std::string query = fmt::format(
account_id SQL(
) SELECT
`safe_x`, `safe_y`, `safe_z`, `safe_heading`, `min_status`, `min_level`, `flag_needed`
FROM
zone
WHERE
`short_name` = '{}'
AND
(`version` = {} OR `version` = 0)
ORDER BY `version` DESC
), zone_short_name, instance_version
); );
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() == 0)
return false;
auto row = results.begin();
if (safe_x != nullptr)
*safe_x = atof(row[0]);
if (safe_y != nullptr)
*safe_y = atof(row[1]);
if (safe_z != nullptr)
*safe_z = atof(row[2]);
if (safe_heading != nullptr)
*safe_heading = atof(row[3]);
if (min_status != nullptr)
*min_status = atoi(row[4]);
if (min_level != nullptr)
*min_level = atoi(row[5]);
if (flag_needed != nullptr)
strcpy(flag_needed, row[6]);
return true;
}
bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) {
std::string query = StringFormat("SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
if (results.RowCount() == 0)
return false;
auto row = results.begin();
if (long_name != nullptr)
*long_name = strcpy(new char[strlen(row[0])+1], row[0]);
if (file_name != nullptr) {
if (row[1] == nullptr)
strcpy(file_name, short_name);
else
strcpy(file_name, row[1]);
}
if (safe_x != nullptr)
*safe_x = atof(row[2]);
if (safe_y != nullptr)
*safe_y = atof(row[3]);
if (safe_z != nullptr)
*safe_z = atof(row[4]);
if (graveyard_id != nullptr)
*graveyard_id = atoi(row[5]);
if (maxclients != nullptr)
*maxclients = atoi(row[6]);
return true;
}
uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) {
std::string query = StringFormat("SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
} }
bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) {
@@ -1065,74 +1131,108 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon
return true; return true;
} }
uint8 Database::GetPEQZone(uint32 zone_id, uint32 version){ uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){
auto z = GetZoneVersionWithFallback(zone_id, version); std::string query = StringFormat("SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version);
auto results = QueryDatabase(query);
return z ? z->peqzone : 0; if (!results.Success()) {
return 0;
} }
bool Database::CheckNameFilter(std::string name, bool surname) if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
bool Database::CheckNameFilter(const char* name, bool surname)
{ {
name = Strings::ToLower(name); std::string str_name = name;
// the minimum 4 is enforced by the client too // the minimum 4 is enforced by the client too
if (name.empty() || name.size() < 4) { if (!name || strlen(name) < 4)
{
return false; return false;
} }
// Given name length is enforced by the client too // Given name length is enforced by the client too
if (!surname && name.size() > 15) { if (!surname && strlen(name) > 15)
{
return false; return false;
} }
for (size_t i = 0; i < name.size(); i++) { for (size_t i = 0; i < str_name.size(); i++)
if (!isalpha(name[i])) { {
if(!isalpha(str_name[i]))
{
return false; return false;
} }
} }
for(size_t x = 0; x < str_name.size(); ++x)
{
str_name[x] = tolower(str_name[x]);
}
char c = '\0'; char c = '\0';
uint8 num_c = 0; uint8 num_c = 0;
for (size_t x = 0; x < name.size(); ++x) { for(size_t x = 0; x < str_name.size(); ++x)
if (name[x] == c) { {
if(str_name[x] == c)
{
num_c++; num_c++;
} else { }
else
{
num_c = 1; num_c = 1;
c = name[x]; c = str_name[x];
} }
if(num_c > 2)
if (num_c > 2) { {
return false; return false;
} }
} }
std::string query = "SELECT name FROM name_filter";
std::string query("SELECT name FROM name_filter");
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success())
{
// false through to true? shouldn't it be falls through to false?
return true; return true;
} }
for (auto row : results) { for (auto row = results.begin();row != results.end();++row)
std::string current_row = Strings::ToLower(row[0]); {
if (name.find(current_row) != std::string::npos) { std::string current_row = row[0];
for(size_t x = 0; x < current_row.size(); ++x)
current_row[x] = tolower(current_row[x]);
if(str_name.find(current_row) != std::string::npos)
return false; return false;
} }
}
return true; return true;
} }
bool Database::AddToNameFilter(std::string name) { bool Database::AddToNameFilter(const char* name) {
auto query = fmt::format(
"INSERT INTO name_filter (name) values ('{}')", std::string query = StringFormat("INSERT INTO name_filter (name) values ('%s')", name);
name
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || !results.RowsAffected()) {
if (!results.Success())
{
return false; return false;
} }
if (results.RowsAffected() == 0)
return false;
return true; return true;
} }
@@ -1220,16 +1320,16 @@ bool Database::UpdateName(const char* oldname, const char* newname) {
} }
// If the name is used or an error occurs, it returns false, otherwise it returns true // If the name is used or an error occurs, it returns false, otherwise it returns true
bool Database::CheckUsedName(std::string name) { bool Database::CheckUsedName(const char* name) {
auto query = fmt::format( std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name);
"SELECT `id` FROM `character_data` WHERE `name` = '{}'",
name
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount()) { if (!results.Success()) {
return false; return false;
} }
if (results.RowCount() > 0)
return false;
return true; return true;
} }
@@ -1387,25 +1487,41 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16
return base_cap; return base_cap;
} }
uint32 Database::GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id) uint32 Database::GetCharacterInfo(
const char *iName,
uint32 *oAccID,
uint32 *oZoneID,
uint32 *oInstanceID,
float *oX,
float *oY,
float *oZ
)
{ {
auto query = fmt::format( std::string query = StringFormat(
"SELECT `id`, `account_id`, `zone_id`, `zone_instance` FROM `character_data` WHERE `name` = '{}'", "SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'",
Strings::Escape(character_name) EscapeString(iName).c_str()
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
if (!results.Success()) {
return 0;
}
if (results.RowCount() != 1) {
return 0; return 0;
} }
auto row = results.begin(); auto row = results.begin();
auto character_id = std::stoul(row[0]); uint32 charid = atoi(row[0]);
*account_id = std::stoul(row[1]); if (oAccID) { *oAccID = atoi(row[1]); }
*zone_id = std::stoul(row[2]); if (oZoneID) { *oZoneID = atoi(row[2]); }
*instance_id = std::stoul(row[3]); if (oInstanceID) { *oInstanceID = atoi(row[3]); }
if (oX) { *oX = atof(row[4]); }
if (oY) { *oY = atof(row[5]); }
if (oZ) { *oZ = atof(row[6]); }
return character_id; return charid;
} }
bool Database::UpdateLiveChar(char* charname, uint32 account_id) { bool Database::UpdateLiveChar(char* charname, uint32 account_id) {
@@ -1464,7 +1580,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines
auto escape_str = new char[lines.size() * 2 + 1]; auto escape_str = new char[lines.size() * 2 + 1];
DoEscapeString(escape_str, lines.c_str(), lines.size()); DoEscapeString(escape_str, lines.c_str(), lines.size());
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", Strings::Escape(who).c_str(), Strings::Escape(against).c_str(), escape_str); std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str);
QueryDatabase(query); QueryDatabase(query);
safe_delete_array(escape_str); safe_delete_array(escape_str);
} }
@@ -1529,40 +1645,33 @@ uint32 Database::GetGroupID(const char* name){
return atoi(row[0]); return atoi(row[0]);
} }
std::string Database::GetGroupLeaderForLogin(std::string character_name) { /* Is this really getting used properly... A half implementation ? Akkadius */
char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) {
strcpy(leaderbuf, "");
uint32 group_id = 0; uint32 group_id = 0;
auto query = fmt::format( std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name` = '%s'", name);
"SELECT `groupid` FROM `group_id` WHERE `name` = '{}'",
character_name
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (results.Success() && results.RowCount()) { for (auto row = results.begin(); row != results.end(); ++row)
auto row = results.begin(); if (row[0])
group_id = std::stoul(row[0]); group_id = atoi(row[0]);
}
if (!group_id) { if (group_id == 0)
return std::string(); return leaderbuf;
}
query = fmt::format( query = StringFormat("SELECT `leadername` FROM `group_leaders` WHERE `gid` = '%u' LIMIT 1", group_id);
"SELECT `leadername` FROM `group_leaders` WHERE `gid` = {} LIMIT 1",
group_id
);
results = QueryDatabase(query); results = QueryDatabase(query);
if (results.Success() && results.RowCount()) { for (auto row = results.begin(); row != results.end(); ++row)
auto row = results.begin(); if (row[0])
return row[0]; strcpy(leaderbuf, row[0]);
}
return std::string(); return leaderbuf;
} }
void Database::SetGroupLeaderName(uint32 gid, const char* name) { void Database::SetGroupLeaderName(uint32 gid, const char* name) {
std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", Strings::Escape(name).c_str(), gid); std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", EscapeString(name).c_str(), gid);
auto result = QueryDatabase(query); auto result = QueryDatabase(query);
if(result.RowsAffected() != 0) { if(result.RowsAffected() != 0) {
@@ -1570,7 +1679,7 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) {
} }
query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')", query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')",
gid, Strings::Escape(name).c_str()); gid, EscapeString(name).c_str());
result = QueryDatabase(query); result = QueryDatabase(query);
if(!result.Success()) { if(!result.Success()) {
@@ -2153,32 +2262,28 @@ bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year
} }
int Database::GetIPExemption(std::string account_ip) { int Database::GetIPExemption(std::string account_ip) {
auto query = fmt::format( std::string query = StringFormat("SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '%s'", account_ip.c_str());
"SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'",
account_ip
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
if (results.Success() && results.RowCount() > 0) {
auto row = results.begin();
return atoi(row[0]);
}
return RuleI(World, MaxClientsPerIP); return RuleI(World, MaxClientsPerIP);
} }
auto row = results.begin();
return std::stoi(row[0]);
}
void Database::SetIPExemption(std::string account_ip, int exemption_amount) { void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
auto query = fmt::format( std::string query = fmt::format(
"SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'", "SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'",
account_ip account_ip
); );
uint32 exemption_id = 0;
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (results.Success() && results.RowCount()) { uint32 exemption_id = 0;
if (results.Success() && results.RowCount() > 0) {
auto row = results.begin(); auto row = results.begin();
exemption_id = std::stoul(row[0]); exemption_id = atoi(row[0]);
} }
query = fmt::format( query = fmt::format(
@@ -2187,14 +2292,13 @@ void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
exemption_amount exemption_amount
); );
if (exemption_id) { if (exemption_id != 0) {
query = fmt::format( query = fmt::format(
"UPDATE `ip_exemptions` SET `exemption_amount` = {} WHERE `exemption_ip` = '{}'", "UPDATE `ip_exemptions` SET `exemption_amount` = {} WHERE `exemption_ip` = '{}'",
exemption_amount, exemption_amount,
account_ip account_ip
); );
} }
QueryDatabase(query); QueryDatabase(query);
} }
@@ -2217,9 +2321,9 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
* @return * @return
*/ */
bool Database::CopyCharacter( bool Database::CopyCharacter(
const std::string& source_character_name, std::string source_character_name,
const std::string& destination_character_name, std::string destination_character_name,
const std::string& destination_account_name std::string destination_account_name
) )
{ {
auto results = QueryDatabase( auto results = QueryDatabase(
@@ -2231,7 +2335,6 @@ bool Database::CopyCharacter(
if (results.RowCount() == 0) { if (results.RowCount() == 0) {
LogError("No character found with name [{}]", source_character_name); LogError("No character found with name [{}]", source_character_name);
return false;
} }
auto row = results.begin(); auto row = results.begin();
@@ -2246,7 +2349,6 @@ bool Database::CopyCharacter(
if (results.RowCount() == 0) { if (results.RowCount() == 0) {
LogError("No account found with name [{}]", destination_account_name); LogError("No account found with name [{}]", destination_account_name);
return false;
} }
row = results.begin(); row = results.begin();
@@ -2278,7 +2380,7 @@ bool Database::CopyCharacter(
results = QueryDatabase( results = QueryDatabase(
fmt::format( fmt::format(
"SELECT {} FROM {} WHERE {} = {}", "SELECT {} FROM {} WHERE {} = {}",
Strings::Implode(",", Strings::Wrap(columns, "`")), implode(",", wrap(columns, "`")),
table_name, table_name,
character_id_column_name, character_id_column_name,
source_character_id source_character_id
@@ -2314,7 +2416,7 @@ bool Database::CopyCharacter(
std::vector<std::string> insert_rows; std::vector<std::string> insert_rows;
for (auto &r: new_rows) { for (auto &r: new_rows) {
std::string insert_row = "(" + Strings::Implode(",", Strings::Wrap(r, "'")) + ")"; std::string insert_row = "(" + implode(",", wrap(r, "'")) + ")";
insert_rows.emplace_back(insert_row); insert_rows.emplace_back(insert_row);
} }
@@ -2332,8 +2434,8 @@ bool Database::CopyCharacter(
fmt::format( fmt::format(
"INSERT INTO {} ({}) VALUES {}", "INSERT INTO {} ({}) VALUES {}",
table_name, table_name,
Strings::Implode(",", Strings::Wrap(columns, "`")), implode(",", wrap(columns, "`")),
Strings::Implode(",", insert_rows) implode(",", insert_rows)
) )
); );
@@ -2356,7 +2458,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
uri request_uri(url); uri request_uri(url);
LogHTTP( LogHTTP(
"parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]", "[SourceDatabaseTableFromUrl] parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]",
url, url,
request_uri.get_path(), request_uri.get_path(),
request_uri.get_host(), request_uri.get_host(),
@@ -2385,8 +2487,8 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
if (auto res = cli.Get(request_uri.get_path().c_str())) { if (auto res = cli.Get(request_uri.get_path().c_str())) {
if (res->status == 200) { if (res->status == 200) {
for (auto &s: Strings::Split(res->body, ';')) { for (auto &s: SplitString(res->body, ';')) {
if (!Strings::Trim(s).empty()) { if (!trim(s).empty()) {
auto results = QueryDatabase(s); auto results = QueryDatabase(s);
if (!results.ErrorMessage().empty()) { if (!results.ErrorMessage().empty()) {
LogError("Error sourcing SQL [{}]", results.ErrorMessage()); LogError("Error sourcing SQL [{}]", results.ErrorMessage());
@@ -2410,20 +2512,7 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur
} }
catch (std::invalid_argument iae) { catch (std::invalid_argument iae) {
LogError("URI parser error [{}]", iae.what()); LogError("[SourceDatabaseTableFromUrl] URI parser error [{}]", iae.what());
} }
} }
uint8 Database::GetMinStatus(uint32 zone_id, uint32 instance_version)
{
auto zones = ZoneRepository::GetWhere(
*this,
fmt::format(
"zoneidnumber = {} AND (version = {} OR version = 0) ORDER BY version DESC LIMIT 1",
zone_id,
instance_version
)
);
return !zones.empty() ? zones[0].min_status : 0;
}
+30 -27
View File
@@ -88,6 +88,7 @@ public:
/* Character Creation */ /* Character Creation */
bool AddToNameFilter(const char *name);
bool CreateCharacter( bool CreateCharacter(
uint32 account_id, uint32 account_id,
char *name, char *name,
@@ -113,25 +114,25 @@ public:
bool SetMQDetectionFlag(const char *accountname, const char *charactername, const std::string &hacked, const char *zone); bool SetMQDetectionFlag(const char *accountname, const char *charactername, const std::string &hacked, const char *zone);
bool UpdateName(const char *oldname, const char *newname); bool UpdateName(const char *oldname, const char *newname);
bool CopyCharacter( bool CopyCharacter(
const std::string& source_character_name, std::string source_character_name,
const std::string& destination_character_name, std::string destination_character_name,
const std::string& destination_account_name std::string destination_account_name
); );
/* General Information Queries */ /* General Information Queries */
bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table. bool AddBannedIP(char* bannedIP, const char* notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(std::string name); bool AddGMIP(char* ip_address, char* name);
bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table. bool CheckBannedIPs(const char* loginIP); //Check incoming connection against banned IP table.
bool CheckGMIPs(std::string login_ip, uint32 account_id); bool CheckGMIPs(const char* loginIP, uint32 account_id);
bool CheckNameFilter(std::string name, bool surname = false); bool CheckNameFilter(const char* name, bool surname = false);
bool CheckUsedName(std::string name); bool CheckUsedName(const char* name);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0); uint32 GetAccountIDByName(const char* accname, const char *loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name); uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id); uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
uint32 GetGuildIDByCharID(uint32 char_id); uint32 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id); uint32 GetGroupIDByCharID(uint32 char_id);
uint32 GetRaidIDByCharID(uint32 char_id); uint32 GetRaidIDByCharID(uint32 char_id);
@@ -141,34 +142,35 @@ public:
std::string GetCharNameByID(uint32 char_id); std::string GetCharNameByID(uint32 char_id);
std::string GetNPCNameByID(uint32 npc_id); std::string GetNPCNameByID(uint32 npc_id);
std::string GetCleanNPCNameByID(uint32 npc_id); std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 account_id, std::string login_ip); void LoginIP(uint32 AccountID, const char* LoginIP);
/* Instancing */ /* Instancing */
bool AddClientToInstance(uint16 instance_id, uint32 character_id); bool AddClientToInstance(uint16 instance_id, uint32 char_id);
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id); bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id);
bool CheckInstanceExists(uint16 instance_id); bool CheckInstanceExists(uint16 instance_id);
bool CheckInstanceExpired(uint16 instance_id); bool CheckInstanceExpired(uint16 instance_id);
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
bool GetUnusedInstanceID(uint16 &instance_id); bool GetUnusedInstanceID(uint16 &instance_id);
bool IsGlobalInstance(uint16 instance_id); bool GlobalInstance(uint16 instance_id);
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id); bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
bool RemoveClientsFromInstance(uint16 instance_id); bool RemoveClientsFromInstance(uint16 instance_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id); bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id);
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version); uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id); uint16 GetInstanceVersion(uint16 instance_id);
uint8_t GetInstanceVersion(uint16 instance_id);
uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma);
uint32 GetInstanceZoneID(uint16 instance_id); uint32 VersionFromInstanceID(uint16 instance_id);
uint32 ZoneIDFromInstanceID(uint16 instance_id);
void AssignGroupToInstance(uint32 gid, uint32 instance_id); void AssignGroupToInstance(uint32 gid, uint32 instance_id);
void AssignRaidToInstance(uint32 rid, uint32 instance_id); void AssignRaidToInstance(uint32 rid, uint32 instance_id);
void BuryCorpsesInInstance(uint16 instance_id);
void DeleteInstance(uint16 instance_id); void DeleteInstance(uint16 instance_id);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id); void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id); void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids); void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list);
void PurgeExpiredInstances(); void PurgeExpiredInstances();
void SetInstanceDuration(uint16 instance_id, uint32 new_duration); void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
@@ -188,8 +190,6 @@ public:
int16 CheckStatus(uint32 account_id); int16 CheckStatus(uint32 account_id);
void SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum);
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0); uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id); uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0); uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
@@ -206,7 +206,7 @@ public:
/* Groups */ /* Groups */
std::string GetGroupLeaderForLogin(std::string character_name); 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); 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); uint32 GetGroupID(const char* name);
@@ -245,11 +245,14 @@ public:
/* General Queries */ /* General Queries */
bool GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, float* safe_heading = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr);
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0);
bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0);
bool LoadPTimers(uint32 charid, PTimerList &into); bool LoadPTimers(uint32 charid, PTimerList &into);
uint8 GetPEQZone(uint32 zone_id, uint32 version); uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version);
uint8 GetMinStatus(uint32 zone_id, uint32 instance_version);
uint8 GetPEQZone(uint32 zoneID, uint32 version);
uint8 GetRaceSkill(uint8 skillid, uint8 in_race); uint8 GetRaceSkill(uint8 skillid, uint8 in_race);
uint8 GetServerType(); uint8 GetServerType();
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
+110 -68
View File
@@ -23,11 +23,10 @@
#include <iterator> #include <iterator>
#include "database_dump_service.h" #include "database_dump_service.h"
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../strings.h" #include "../string_util.h"
#include "../eqemu_config.h" #include "../eqemu_config.h"
#include "../database_schema.h" #include "../database_schema.h"
#include "../file.h" #include "../file_util.h"
#include "../process/process.h"
#include <ctime> #include <ctime>
@@ -41,6 +40,38 @@
#define DATABASE_DUMP_PATH "backups/" #define DATABASE_DUMP_PATH "backups/"
/**
* @param cmd
* @param return_result
* @return
*/
std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true)
{
const char *file_name = "db-exec-result.txt";
if (return_result) {
#ifdef _WINDOWS
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#else
std::system((cmd + " > " + file_name).c_str());
#endif
}
else {
std::system((cmd).c_str());
}
std::string result;
if (return_result) {
std::ifstream file(file_name);
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
std::remove(file_name);
}
return result;
}
/** /**
* @return bool * @return bool
*/ */
@@ -57,7 +88,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
*/ */
bool DatabaseDumpService::IsTarAvailable() bool DatabaseDumpService::IsTarAvailable()
{ {
std::string version_output = Process::execute("tar --version"); std::string version_output = execute("tar --version");
return version_output.find("GNU tar") != std::string::npos; return version_output.find("GNU tar") != std::string::npos;
} }
@@ -68,7 +99,7 @@ bool DatabaseDumpService::IsTarAvailable()
*/ */
bool DatabaseDumpService::Is7ZipAvailable() bool DatabaseDumpService::Is7ZipAvailable()
{ {
std::string version_output = Process::execute("7z --help"); std::string version_output = execute("7z --help");
return version_output.find("7-Zip") != std::string::npos; return version_output.find("7-Zip") != std::string::npos;
} }
@@ -86,9 +117,9 @@ bool DatabaseDumpService::HasCompressionBinary()
*/ */
std::string DatabaseDumpService::GetMySQLVersion() std::string DatabaseDumpService::GetMySQLVersion()
{ {
std::string version_output = Process::execute("mysql --version"); std::string version_output = execute("mysql --version");
return Strings::Trim(version_output); return trim(version_output);
} }
/** /**
@@ -118,53 +149,95 @@ std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
); );
} }
/**
* @return
*/
std::string DatabaseDumpService::GetPlayerTablesList() std::string DatabaseDumpService::GetPlayerTablesList()
{ {
return Strings::Join(DatabaseSchema::GetPlayerTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetPlayerTables();
for (const auto &table : tables) {
tables_list += table + " ";
} }
std::string DatabaseDumpService::GetBotTablesList() return trim(tables_list);
{
return Strings::Join(DatabaseSchema::GetBotTables(), " ");
}
std::string DatabaseDumpService::GetMercTablesList()
{
return Strings::Join(DatabaseSchema::GetMercTables(), " ");
} }
/**
* @return
*/
std::string DatabaseDumpService::GetLoginTableList() std::string DatabaseDumpService::GetLoginTableList()
{ {
return Strings::Join(DatabaseSchema::GetLoginTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetLoginTables();
for (const auto &table : tables) {
tables_list += table + " ";
} }
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetQueryServTables() std::string DatabaseDumpService::GetQueryServTables()
{ {
return Strings::Join(DatabaseSchema::GetQueryServerTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetQueryServerTables();
for (const auto &table : tables) {
tables_list += table + " ";
} }
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetSystemTablesList() std::string DatabaseDumpService::GetSystemTablesList()
{ {
auto system_tables = DatabaseSchema::GetServerTables(); std::string tables_list;
auto version_tables = DatabaseSchema::GetVersionTables();
system_tables.insert( std::vector<std::string> tables = DatabaseSchema::GetServerTables();
std::end(system_tables), for (const auto &table : tables) {
std::begin(version_tables), tables_list += table + " ";
std::end(version_tables)
);
return Strings::Join(system_tables, " ");
} }
tables = DatabaseSchema::GetVersionTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetStateTablesList() std::string DatabaseDumpService::GetStateTablesList()
{ {
return Strings::Join(DatabaseSchema::GetStateTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetStateTables();
for (const auto &table : tables) {
tables_list += table + " ";
} }
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetContentTablesList() std::string DatabaseDumpService::GetContentTablesList()
{ {
return Strings::Join(DatabaseSchema::GetContentTables(), " "); std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetContentTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
} }
/** /**
@@ -245,16 +318,6 @@ void DatabaseDumpService::Dump()
dump_descriptor += "-player"; dump_descriptor += "-player";
} }
if (IsDumpBotTables()) {
tables_to_dump += GetBotTablesList() + " ";
dump_descriptor += "-bots";
}
if (IsDumpMercTables()) {
tables_to_dump += GetMercTablesList() + " ";
dump_descriptor += "-mercs";
}
if (IsDumpSystemTables()) { if (IsDumpSystemTables()) {
tables_to_dump += GetSystemTablesList() + " "; tables_to_dump += GetSystemTablesList() + " ";
dump_descriptor += "-system"; dump_descriptor += "-system";
@@ -301,12 +364,12 @@ void DatabaseDumpService::Dump()
pipe_file pipe_file
); );
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
File::Makedir(GetSetDumpPath()); FileUtil::mkdir(GetSetDumpPath());
} }
if (IsDumpDropTableSyntaxOnly()) { if (IsDumpDropTableSyntaxOnly()) {
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' '); std::vector<std::string> tables = SplitString(tables_to_dump, ' ');
for (auto &table : tables) { for (auto &table : tables) {
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl; std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
@@ -317,14 +380,14 @@ void DatabaseDumpService::Dump()
} }
} }
else { else {
std::string execution_result = Process::execute(execute_command); std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
if (!execution_result.empty() && IsDumpOutputToConsole()) { if (!execution_result.empty()) {
std::cout << execution_result; std::cout << execution_result;
} }
} }
if (!tables_to_dump.empty()) { if (!tables_to_dump.empty()) {
LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump)); LogInfo("Dumping Tables [{}]", tables_to_dump);
} }
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath()); LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
@@ -334,7 +397,7 @@ void DatabaseDumpService::Dump()
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath()); LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
if (IsTarAvailable()) { if (IsTarAvailable()) {
Process::execute( execute(
fmt::format( fmt::format(
"tar -zcvf {}.tar.gz -C {} {}.sql", "tar -zcvf {}.tar.gz -C {} {}.sql",
GetDumpFileNameWithPath(), GetDumpFileNameWithPath(),
@@ -345,7 +408,7 @@ void DatabaseDumpService::Dump()
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath()); LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
} }
else if (Is7ZipAvailable()) { else if (Is7ZipAvailable()) {
Process::execute( execute(
fmt::format( fmt::format(
"7z a -t7z {}.zip {}.sql", "7z a -t7z {}.zip {}.sql",
GetDumpFileNameWithPath(), GetDumpFileNameWithPath(),
@@ -373,7 +436,6 @@ void DatabaseDumpService::Dump()
// LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false")); // LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false"));
// LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false")); // LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false"));
// LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false")); // LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false"));
// LogDebug("[{}] bot", (IsDumpBotTables() ? "true" : "false"));
} }
bool DatabaseDumpService::IsDumpSystemTables() const bool DatabaseDumpService::IsDumpSystemTables() const
@@ -515,23 +577,3 @@ void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables)
{ {
DatabaseDumpService::dump_state_tables = dump_state_tables; DatabaseDumpService::dump_state_tables = dump_state_tables;
} }
bool DatabaseDumpService::IsDumpBotTables() const
{
return dump_bot_tables;
}
void DatabaseDumpService::SetDumpBotTables(bool dump_bot_tables)
{
DatabaseDumpService::dump_bot_tables = dump_bot_tables;
}
bool DatabaseDumpService::IsDumpMercTables() const
{
return dump_merc_tables;
}
void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables)
{
DatabaseDumpService::dump_merc_tables = dump_merc_tables;
}
+1 -8
View File
@@ -53,10 +53,6 @@ public:
void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only); void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only);
bool IsDumpStateTables() const; bool IsDumpStateTables() const;
void SetDumpStateTables(bool dump_state_tables); void SetDumpStateTables(bool dump_state_tables);
bool IsDumpBotTables() const;
void SetDumpBotTables(bool dump_bot_tables);
bool IsDumpMercTables() const;
void SetDumpMercTables(bool dump_bot_tables);
private: private:
bool dump_all_tables = false; bool dump_all_tables = false;
@@ -71,17 +67,14 @@ private:
bool dump_with_compression = false; bool dump_with_compression = false;
bool dump_output_to_console = false; bool dump_output_to_console = false;
bool dump_drop_table_syntax_only = false; bool dump_drop_table_syntax_only = false;
bool dump_bot_tables = false;
bool dump_merc_tables = false;
std::string dump_path; std::string dump_path;
std::string dump_file_name; std::string dump_file_name;
std::string execute(const std::string &cmd, bool return_result);
bool IsMySQLInstalled(); bool IsMySQLInstalled();
std::string GetMySQLVersion(); std::string GetMySQLVersion();
std::string GetBaseMySQLDumpCommand(); std::string GetBaseMySQLDumpCommand();
std::string GetPlayerTablesList(); std::string GetPlayerTablesList();
std::string GetBotTablesList();
std::string GetMercTablesList();
std::string GetSystemTablesList(); std::string GetSystemTablesList();
std::string GetStateTablesList(); std::string GetStateTablesList();
std::string GetContentTablesList(); std::string GetContentTablesList();
+8 -17
View File
@@ -18,12 +18,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/strings.h" #include "../common/string_util.h"
#include "../common/timer.h" #include "../common/timer.h"
#include "database.h" #include "database.h"
#include "extprofile.h" #include "extprofile.h"
#include "path_manager.h"
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
@@ -476,16 +475,8 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertPPDeblob(); CheckDatabaseConvertPPDeblob();
CheckDatabaseConvertCorpseDeblob(); CheckDatabaseConvertCorpseDeblob();
RuleManager::Instance()->LoadRules(this, "default", false);
if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) {
LogInfo("Bot tables found but rule not enabled, enabling");
RuleManager::Instance()->SetRule("Bots:Enabled", "true", this, true, true);
}
/* Run EQEmu Server script (Checks for database updates) */ /* Run EQEmu Server script (Checks for database updates) */
if(system("perl eqemu_server.pl ran_from_world"));
const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath());
system(fmt::format("perl {} ran_from_world", file).c_str());
return true; return true;
} }
@@ -970,7 +961,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)" std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)"
"VALUES (%u, '%s')", "VALUES (%u, '%s')",
character_id, character_id,
Strings::Escape(inspectmessage).c_str() EscapeString(inspectmessage).c_str()
); );
auto results = QueryDatabase(rquery); auto results = QueryDatabase(rquery);
} }
@@ -1207,8 +1198,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
")", ")",
character_id, character_id,
account_id, account_id,
Strings::Escape(pp->name).c_str(), EscapeString(pp->name).c_str(),
Strings::Escape(pp->last_name).c_str(), EscapeString(pp->last_name).c_str(),
pp->gender, pp->gender,
pp->race, pp->race,
pp->class_, pp->class_,
@@ -1232,8 +1223,8 @@ bool Database::CheckDatabaseConvertPPDeblob(){
pp->ability_number, pp->ability_number,
pp->ability_time_minutes, pp->ability_time_minutes,
pp->ability_time_hours, pp->ability_time_hours,
Strings::Escape(pp->title).c_str(), EscapeString(pp->title).c_str(),
Strings::Escape(pp->suffix).c_str(), EscapeString(pp->suffix).c_str(),
pp->exp, pp->exp,
pp->points, pp->points,
pp->mana, pp->mana,
@@ -1461,7 +1452,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){ for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){
if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){ if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){
if (first_entry != 1){ if (first_entry != 1){
rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
first_entry = 1; first_entry = 1;
} }
rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
+308 -247
View File
@@ -18,18 +18,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/strings.h" #include "../common/string_util.h"
#include "../common/timer.h" #include "../common/timer.h"
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/dynamic_zone_members_repository.h" #include "../common/repositories/dynamic_zone_members_repository.h"
#include "../common/repositories/dynamic_zones_repository.h" #include "../common/repositories/dynamic_zones_repository.h"
#include "../common/repositories/group_id_repository.h"
#include "../common/repositories/instance_list_repository.h"
#include "../common/repositories/instance_list_player_repository.h"
#include "../common/repositories/raid_members_repository.h"
#include "../common/repositories/respawn_times_repository.h"
#include "../common/repositories/spawn_condition_values_repository.h"
#include "database.h" #include "database.h"
@@ -49,83 +41,115 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/time.h> #include <sys/time.h>
#endif #endif
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id) /**
* @param instance_id
* @param char_id
* @return
*/
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
{ {
auto e = InstanceListPlayerRepository::NewEntity(); std::string query = StringFormat(
"REPLACE INTO `instance_list_player` (id, charid) "
e.id = instance_id; "VALUES "
e.charid = character_id; "(%lu, %lu)",
(unsigned long) instance_id,
return InstanceListPlayerRepository::ReplaceOne(*this, e); (unsigned long) char_id
}
bool Database::CheckInstanceByCharID(uint16 instance_id, uint32 character_id)
{
if (!instance_id) {
return false;
}
auto l = InstanceListPlayerRepository::GetWhere(
*this,
fmt::format(
"id = {} AND charid = {}",
instance_id,
character_id
)
); );
if (l.empty()) {
return false; auto results = QueryDatabase(query);
return results.Success();
} }
bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id)
{
std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
if (results.RowCount() != 1)
return false;
return true; return true;
} }
bool Database::CheckInstanceExists(uint16 instance_id) bool Database::CheckInstanceExists(uint16 instance_id) {
{ std::string query = StringFormat(
if (!instance_id) { "SELECT "
return false; "`id` "
} "FROM "
"`instance_list` "
"WHERE "
"`id` = %u",
instance_id
);
auto results = QueryDatabase(query);
auto i = InstanceListRepository::FindOne(*this, instance_id); if (!results.Success())
if (!i.id) { return false;
if (results.RowCount() == 0)
return false; return false;
}
return true; return true;
} }
bool Database::CheckInstanceExpired(uint16 instance_id) bool Database::CheckInstanceExpired(uint16 instance_id)
{ {
if (!instance_id) {
int32 start_time = 0;
int32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat(
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
instance_id
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return true; return true;
} }
auto i = InstanceListRepository::FindOne(*this, instance_id); if (results.RowCount() == 0) {
if (!i.id) {
return true; return true;
} }
if (i.never_expires) { auto row = results.begin();
start_time = atoi(row[0]);
duration = atoi(row[1]);
never_expires = atoi(row[2]);
if (never_expires == 1) {
return false; return false;
} }
timeval tv{}; timeval tv{};
gettimeofday(&tv, nullptr); gettimeofday(&tv, nullptr);
return (i.start_time + i.duration) <= tv.tv_sec; return (start_time + duration) <= tv.tv_sec;
} }
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
{ {
auto e = InstanceListRepository::NewEntity(); std::string query = StringFormat(
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
instance_id,
zone_id,
version,
duration
);
e.id = instance_id; auto results = QueryDatabase(query);
e.zone = zone_id;
e.version = version;
e.start_time = std::time(nullptr);
e.duration = duration;
return InstanceListRepository::InsertOne(*this, e).id; return results.Success();
} }
bool Database::GetUnusedInstanceID(uint16 &instance_id) bool Database::GetUnusedInstanceID(uint16 &instance_id)
@@ -133,8 +157,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances); uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max = 32000; uint32 max = 32000;
auto query = fmt::format( std::string query = StringFormat(
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}", "SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
max_reserved_instance_id, max_reserved_instance_id,
max_reserved_instance_id max_reserved_instance_id
); );
@@ -178,7 +202,7 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true; return true;
} }
query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id); query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id);
results = QueryDatabase(query); results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
@@ -192,9 +216,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
} }
max_reserved_instance_id++; max_reserved_instance_id++;
for (auto row = results.begin(); row != results.end(); ++row) {
for (auto row : results) { if (max_reserved_instance_id < atoi(row[0])) {
if (max_reserved_instance_id < std::stoul(row[0])) {
instance_id = max_reserved_instance_id; instance_id = max_reserved_instance_id;
return true; return true;
} }
@@ -212,45 +235,57 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id)
return true; return true;
} }
bool Database::IsGlobalInstance(uint16 instance_id) bool Database::GlobalInstance(uint16 instance_id)
{ {
if (!instance_id) { std::string query = StringFormat(
return false; "SELECT "
} "is_global "
"FROM "
"instance_list "
"WHERE "
"id = %u "
"LIMIT 1 ",
instance_id
);
auto results = QueryDatabase(query);
auto i = InstanceListRepository::FindOne(*this, instance_id); if (!results.Success())
if (!i.id) {
return false; return false;
}
return i.is_global; if (results.RowCount() == 0)
return false;
auto row = results.begin();
return (atoi(row[0]) == 1) ? true : false;
} }
bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id)
{ {
return InstanceListPlayerRepository::DeleteWhere( std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu",
*this, (unsigned long)instance_id, (unsigned long)char_id);
fmt::format( auto results = QueryDatabase(query);
"id = {} AND charid = {}",
instance_id, return results.Success();
char_id
)
);
} }
bool Database::RemoveClientsFromInstance(uint16 instance_id) bool Database::RemoveClientsFromInstance(uint16 instance_id)
{ {
return InstanceListPlayerRepository::DeleteOne(*this, instance_id); std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id);
auto results = QueryDatabase(query);
return results.Success();
} }
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id) bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id)
{ {
//we are not saved to this instance so set our instance to 0 //we are not saved to this instance so set our instance to 0
if (!IsGlobalInstance(instance_id) && !CheckInstanceByCharID(instance_id, character_id)) { if (!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id))
return false; return false;
}
if (CheckInstanceExpired(instance_id)) { if (CheckInstanceExpired(instance_id))
{
DeleteInstance(instance_id); DeleteInstance(instance_id);
return false; return false;
} }
@@ -260,102 +295,99 @@ bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 character_id)
bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id)
{ {
auto l = InstanceListRepository::GetWhere(
*this, std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u", instance_id, zone_id);
fmt::format( auto results = QueryDatabase(query);
"id = {} AND zone = {}",
instance_id, if (!results.Success())
zone_id return false;
)
); if (results.RowCount() == 0)
if (l.empty()) {
return false; return false;
}
return true; return true;
} }
uint16 Database::GetInstanceID(uint32 zone_id, uint32 character_id, int16 version) uint16 Database::GetInstanceID(uint32 zone, uint32 character_id, int16 version)
{ {
if (!zone_id) { if (!zone)
return 0; return 0;
}
const auto query = fmt::format( std::string query = StringFormat(
"SELECT instance_list.id FROM " "SELECT "
"instance_list, instance_list_player WHERE " "instance_list.id "
"instance_list.zone = {} AND " "FROM "
"instance_list.version = {} AND " "instance_list, "
"instance_list.id = instance_list_player.id AND " "instance_list_player "
"instance_list_player.charid = {} " "WHERE "
"instance_list.zone = %u "
"AND instance_list.version = %u "
"AND instance_list.id = instance_list_player.id "
"AND instance_list_player.charid = %u "
"LIMIT 1; ", "LIMIT 1; ",
zone_id, zone,
version, version,
character_id character_id
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) { if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint16 Database::GetInstanceVersion(uint16 instance_id) {
if (instance_id == 0)
return 0;
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
{
uint32 start_time = 0;
uint32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
{
is_perma = false;
return 0;
}
if (results.RowCount() == 0)
{
is_perma = false;
return 0; return 0;
} }
auto row = results.begin(); auto row = results.begin();
return static_cast<uint16>(std::stoul(row[0])); start_time = atoi(row[0]);
} duration = atoi(row[1]);
never_expires = atoi(row[2]);
std::vector<uint16> Database::GetInstanceIDs(uint32 zone_id, uint32 character_id) if (never_expires == 1)
{ {
std::vector<uint16> l;
if (!zone_id) {
return l;
}
const auto query = fmt::format(
"SELECT instance_list.id FROM "
"instance_list, instance_list_player WHERE "
"instance_list.zone = {} AND "
"instance_list.id = instance_list_player.id AND "
"instance_list_player.charid = {}",
zone_id,
character_id
);
auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
return l;
}
for (auto row : results) {
l.push_back(static_cast<uint16>(std::stoul(row[0])));
}
return l;
}
uint8_t Database::GetInstanceVersion(uint16 instance_id) {
if (!instance_id) {
return 0;
}
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
return 0;
}
return i.version;
}
uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
{
auto i = InstanceListRepository::FindOne(*this, instance_id);
if (!i.id) {
is_perma = false;
return 0;
}
if (i.never_expires) {
is_perma = true; is_perma = true;
return 0; return 0;
} }
@@ -364,175 +396,204 @@ uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma)
timeval tv; timeval tv;
gettimeofday(&tv, nullptr); gettimeofday(&tv, nullptr);
return ((i.start_time + i.duration) - tv.tv_sec); return ((start_time + duration) - tv.tv_sec);
} }
uint32 Database::GetInstanceZoneID(uint16 instance_id) uint32 Database::VersionFromInstanceID(uint16 instance_id)
{ {
if (!instance_id) {
std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
} }
auto i = InstanceListRepository::FindOne(*this, instance_id); uint32 Database::ZoneIDFromInstanceID(uint16 instance_id)
if (!i.id) { {
return 0;
}
return i.zone; std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
} }
void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id) void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
{ {
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = GroupIdRepository::GetWhere( uint32 zone_id = ZoneIDFromInstanceID(instance_id);
*this, uint16 version = VersionFromInstanceID(instance_id);
fmt::format(
"groupid = {}", std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id);
group_id auto results = QueryDatabase(query);
)
); if (!results.Success())
if (l.empty()) {
return; return;
}
for (const auto& e : l) { for (auto row = results.begin(); row != results.end(); ++row)
if (!GetInstanceID(zone_id, e.charid, version)) { {
AddClientToInstance(instance_id, e.charid); uint32 charid = atoi(row[0]);
} if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
} }
} }
void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id) void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
{ {
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = GroupIdRepository::GetWhere( uint32 zone_id = ZoneIDFromInstanceID(instance_id);
*this, uint16 version = VersionFromInstanceID(instance_id);
std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id);
auto results = QueryDatabase(query);
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
{
uint32 charid = atoi(row[0]);
if (GetInstanceID(zone_id, charid, version) == 0)
AddClientToInstance(instance_id, charid);
}
}
void Database::BuryCorpsesInInstance(uint16 instance_id) {
QueryDatabase(
fmt::format( fmt::format(
"raidid = {}", "UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id = {}",
raid_id instance_id
) )
); );
if (l.empty()) {
return;
}
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
}
}
} }
void Database::DeleteInstance(uint16 instance_id) void Database::DeleteInstance(uint16 instance_id)
{ {
std::string query; std::string query;
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id)); query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id);
QueryDatabase(query);
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id);
QueryDatabase(query);
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
QueryDatabase(query);
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id); DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id)); DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
CharacterCorpsesRepository::BuryInstance(*this, instance_id); BuryCorpsesInInstance(instance_id);
} }
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id) void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid)
{ {
auto instance_id = GetInstanceID(zone_id, character_id, version); uint16 id = GetInstanceID(zone, charid, version);
if (instance_id) { if (id != 0)
return; return;
}
char ln[128]; char ln[128];
memset(ln, 0, 128); memset(ln, 0, 128);
GetGroupLeadershipInfo(group_id, ln); GetGroupLeadershipInfo(gid, ln);
uint32 l_charid = GetCharacterID((const char*)ln);
uint16 l_id = GetInstanceID(zone, l_charid, version);
auto group_leader_id = GetCharacterID((const char*)ln); if (l_id == 0)
auto group_leader_instance_id = GetInstanceID(zone_id, group_leader_id, version);
if (!group_leader_instance_id) {
return; return;
AddClientToInstance(l_id, charid);
} }
AddClientToInstance(group_leader_instance_id, character_id); void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid)
}
void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id)
{ {
uint16 instance_id = GetInstanceID(zone_id, character_id, version); uint16 id = GetInstanceID(zone, charid, version);
if (instance_id) { if (id != 0)
return; return;
}
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id)); uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid));
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version); uint16 l_id = GetInstanceID(zone, l_charid, version);
if (!raid_leader_instance_id) { if (l_id == 0)
return; return;
AddClientToInstance(l_id, charid);
} }
AddClientToInstance(raid_leader_instance_id, character_id); void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list) {
}
void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids) std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id);
{ auto results = QueryDatabase(query);
auto l = InstanceListPlayerRepository::GetWhere(*this, fmt::format("id = {}", instance_id));
if (l.empty()) { if (!results.Success())
return; return;
}
for (const auto& e : l) { for (auto row = results.begin(); row != results.end(); ++row)
character_ids.push_back(e.charid); charid_list.push_back(atoi(row[0]));
}
} }
void Database::PurgeExpiredInstances() void Database::PurgeExpiredInstances()
{ {
/** /**
* Delay purging by a day so that we can continue using adjacent free instance id's * Delay purging by a day so that we can continue using adjacent free instance id's
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but * from the table without risking the chance we immediately re-allocate a zone that freshly expired but
* has not been fully de-allocated * has not been fully de-allocated
*/ */
auto l = InstanceListRepository::GetWhere( std::string query =
*this, SQL(
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0" SELECT
id
FROM
instance_list
where
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
and never_expires = 0
); );
if (l.empty()) {
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
if (results.RowCount() == 0) {
return; return;
} }
std::vector<std::string> instance_ids; std::vector<std::string> instance_ids;
for (const auto& e : l) { for (auto row = results.begin(); row != results.end(); ++row) {
instance_ids.emplace_back(std::to_string(e.id)); instance_ids.emplace_back(row[0]);
} }
const auto imploded_instance_ids = Strings::Implode(",", instance_ids); std::string imploded_instance_ids = implode(",", instance_ids);
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM instance_list WHERE id IN ({})", imploded_instance_ids));
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM instance_list_player WHERE id IN ({})", imploded_instance_ids));
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids); QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids));
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids); DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
} }
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
{ {
auto i = InstanceListRepository::FindOne(*this, instance_id); std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), "
if (!i.id) { "duration=%u WHERE id=%u", new_duration, instance_id);
return; auto results = QueryDatabase(query);
}
i.start_time = std::time(nullptr);
i.duration = new_duration;
InstanceListRepository::UpdateOne(*this, i);
} }
+4 -62
View File
@@ -62,7 +62,6 @@ namespace DatabaseSchema {
{"character_pet_buffs", "char_id"}, {"character_pet_buffs", "char_id"},
{"character_pet_info", "char_id"}, {"character_pet_info", "char_id"},
{"character_pet_inventory", "char_id"}, {"character_pet_inventory", "char_id"},
{"character_peqzone_flags", "id"},
{"character_potionbelt", "id"}, {"character_potionbelt", "id"},
{"character_skills", "id"}, {"character_skills", "id"},
{"character_spells", "id"}, {"character_spells", "id"},
@@ -83,6 +82,7 @@ namespace DatabaseSchema {
{"player_titlesets", "char_id"}, {"player_titlesets", "char_id"},
{"quest_globals", "charid"}, {"quest_globals", "charid"},
{"timers", "char_id"}, {"timers", "char_id"},
{"titles", "char_id"},
{"trader", "char_id"}, {"trader", "char_id"},
{"zone_flags", "charID"} {"zone_flags", "charID"}
}; };
@@ -130,7 +130,6 @@ namespace DatabaseSchema {
"character_pet_buffs", "character_pet_buffs",
"character_pet_info", "character_pet_info",
"character_pet_inventory", "character_pet_inventory",
"character_peqzone_flags",
"character_potionbelt", "character_potionbelt",
"character_skills", "character_skills",
"character_spells", "character_spells",
@@ -159,6 +158,7 @@ namespace DatabaseSchema {
"spell_buckets", "spell_buckets",
"spell_globals", "spell_globals",
"timers", "timers",
"titles",
"trader", "trader",
"trader_audit", "trader_audit",
"zone_flags" "zone_flags"
@@ -189,14 +189,13 @@ namespace DatabaseSchema {
"char_create_point_allocations", "char_create_point_allocations",
"damageshieldtypes", "damageshieldtypes",
"doors", "doors",
"dynamic_zone_templates",
"faction_association",
"faction_base_data", "faction_base_data",
"faction_list", "faction_list",
"faction_list_mod", "faction_list_mod",
"fishing", "fishing",
"forage", "forage",
"global_loot", "global_loot",
"goallists",
"graveyard", "graveyard",
"grid", "grid",
"grid_entries", "grid_entries",
@@ -225,6 +224,7 @@ namespace DatabaseSchema {
"pets_beastlord_data", "pets_beastlord_data",
"pets_equipmentset", "pets_equipmentset",
"pets_equipmentset_entries", "pets_equipmentset_entries",
"proximities",
"skill_caps", "skill_caps",
"spawn2", "spawn2",
"spawn_conditions", "spawn_conditions",
@@ -270,7 +270,6 @@ namespace DatabaseSchema {
"perl_event_export_settings", "perl_event_export_settings",
"profanity_list", "profanity_list",
"rule_sets", "rule_sets",
"titles",
"rule_values", "rule_values",
"variables", "variables",
}; };
@@ -318,7 +317,6 @@ namespace DatabaseSchema {
"completed_shared_task_activity_state", "completed_shared_task_activity_state",
"completed_shared_task_members", "completed_shared_task_members",
"completed_shared_tasks", "completed_shared_tasks",
"discord_webhooks",
"dynamic_zone_members", "dynamic_zone_members",
"dynamic_zones", "dynamic_zones",
"eventlog", "eventlog",
@@ -332,9 +330,7 @@ namespace DatabaseSchema {
"ip_exemptions", "ip_exemptions",
"item_tick", "item_tick",
"lfguild", "lfguild",
"merc_buffs",
"merchantlist_temp", "merchantlist_temp",
"mercs",
"object_contents", "object_contents",
"raid_details", "raid_details",
"raid_leaders", "raid_leaders",
@@ -379,60 +375,6 @@ namespace DatabaseSchema {
}; };
} }
/**
* @description Gets all player bot tables
* @note These tables have no content in the PEQ daily dump
*
* @return
*/
static std::vector<std::string> GetBotTables()
{
return {
"bot_buffs",
"bot_command_settings",
"bot_create_combinations",
"bot_data",
"bot_group_members",
"bot_groups",
"bot_guild_members",
"bot_heal_rotation_members",
"bot_heal_rotation_targets",
"bot_heal_rotations",
"bot_inspect_messages",
"bot_inventories",
"bot_owner_options",
"bot_pet_buffs",
"bot_pet_inventories",
"bot_pets",
"bot_spell_casting_chances",
"bot_spell_settings",
"bot_spells_entries",
"bot_stances",
"bot_timers"
};
}
static std::vector<std::string> GetMercTables()
{
return {
"merc_armorinfo",
"merc_inventory",
"merc_merchant_entries",
"merc_merchant_template_entries",
"merc_merchant_templates",
"merc_name_types",
"merc_npc_types",
"merc_spell_list_entries",
"merc_spell_lists",
"merc_stance_entries",
"merc_stats",
"merc_subtypes",
"merc_templates",
"merc_types",
"merc_weaponinfo"
};
}
} }
#endif //EQEMU_DATABASE_SCHEMA_H #endif //EQEMU_DATABASE_SCHEMA_H
+2 -2
View File
@@ -167,7 +167,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) { if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
if ((strncasecmp(query, "select", 6) == 0)) { if ((strncasecmp(query, "select", 6) == 0)) {
LogMySQLQuery( LogMySQLQuery(
"{0} -- ({1} row{2} returned) ({3}s)", "{0} ({1} row{2} returned) ({3}s)",
query, query,
requestResult.RowCount(), requestResult.RowCount(),
requestResult.RowCount() == 1 ? "" : "s", requestResult.RowCount() == 1 ? "" : "s",
@@ -176,7 +176,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
} }
else { else {
LogMySQLQuery( LogMySQLQuery(
"{0} -- ({1} row{2} affected) ({3}s)", "{0} ({1} row{2} affected) ({3}s)",
query, query,
requestResult.RowsAffected(), requestResult.RowsAffected(),
requestResult.RowsAffected() == 1 ? "" : "s", requestResult.RowsAffected() == 1 ? "" : "s",
-91
View File
@@ -1,91 +0,0 @@
#include "discord.h"
#include "../http/httplib.h"
#include "../json/json.h"
#include "../strings.h"
#include "../eqemu_logsys.h"
constexpr int MAX_RETRIES = 10;
void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url)
{
// validate
if (webhook_url.empty()) {
LogDiscord("[webhook_url] is empty");
return;
}
// validate
if (webhook_url.find("http://") == std::string::npos && webhook_url.find("https://") == std::string::npos) {
LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url);
return;
}
// split
auto s = Strings::Split(webhook_url, '/');
// url
std::string base_url = fmt::format("{}//{}", s[0], s[2]);
std::string endpoint = Strings::Replace(webhook_url, base_url, "");
// client
httplib::Client cli(base_url.c_str());
cli.set_connection_timeout(0, 15000000); // 15 sec
cli.set_read_timeout(15, 0); // 15 seconds
cli.set_write_timeout(15, 0); // 15 seconds
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
// payload
Json::Value p;
p["content"] = message;
std::stringstream payload;
payload << p;
bool retry = true;
int retries = 0;
int retry_timer = 1000;
while (retry) {
if (auto res = cli.Post(endpoint.c_str(), payload.str(), "application/json")) {
if (res->status != 200 && res->status != 204) {
LogError("Code [{}] Error [{}]", res->status, res->body);
}
if (res->status == 429) {
if (!res->body.empty()) {
std::stringstream ss(res->body);
Json::Value response;
try {
ss >> response;
}
catch (std::exception const &ex) {
LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body);
}
retry_timer = std::stoi(response["retry_after"].asString()) + 500;
}
LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer);
std::this_thread::sleep_for(std::chrono::milliseconds(retry_timer + 500));
}
if (res->status == 204) {
retry = false;
}
if (retries > MAX_RETRIES) {
LogDiscord("Retries exceeded for message [{}]", message);
retry = false;
}
retries++;
}
}
}
std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string &message)
{
if (category_id == Logs::LogCategory::MySQLQuery) {
return fmt::format("```sql\n{}\n```", message);
}
return message + "\n";
}
-15
View File
@@ -1,15 +0,0 @@
#ifndef EQEMU_DISCORD_H
#define EQEMU_DISCORD_H
#include <string>
#include "../types.h"
class Discord {
public:
static void SendWebhookMessage(const std::string& message, const std::string& webhook_url);
static std::string FormatDiscordMessage(uint16 category_id, const std::string& message);
};
#endif //EQEMU_DISCORD_H
-69
View File
@@ -1,69 +0,0 @@
#include "discord_manager.h"
#include "../common/discord/discord.h"
#include "../common/eqemu_logsys.h"
#include "../common/strings.h"
void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message)
{
webhook_queue_lock.lock();
webhook_message_queue[webhook_id].emplace_back(message);
webhook_queue_lock.unlock();
}
constexpr int MAX_MESSAGE_LENGTH = 1900;
void DiscordManager::ProcessMessageQueue()
{
if (webhook_message_queue.empty()) {
return;
}
webhook_queue_lock.lock();
for (auto &q: webhook_message_queue) {
LogDiscord("Processing [{}] messages in queue for webhook ID [{}]...", q.second.size(), q.first);
if (q.first >= MAX_DISCORD_WEBHOOK_ID) {
LogDiscord("Out of bounds webhook ID [{}] max [{}]", q.first, MAX_DISCORD_WEBHOOK_ID);
continue;
}
auto webhook = LogSys.GetDiscordWebhooks()[q.first];
std::string message;
for (auto &m: q.second) {
// next message would become too large
bool next_message_too_large = ((int) m.length() + (int) message.length()) > MAX_MESSAGE_LENGTH;
if (next_message_too_large) {
Discord::SendWebhookMessage(
message,
webhook.webhook_url
);
message = "";
}
message += m;
// one single message was too large
// this should rarely happen but the message will need to be split
if ((int) message.length() > MAX_MESSAGE_LENGTH) {
for (unsigned mi = 0; mi < message.length(); mi += MAX_MESSAGE_LENGTH) {
Discord::SendWebhookMessage(
message.substr(mi, MAX_MESSAGE_LENGTH),
webhook.webhook_url
);
}
message = "";
}
}
// final flush
if (!message.empty()) {
Discord::SendWebhookMessage(
message,
webhook.webhook_url
);
}
}
webhook_message_queue.clear();
webhook_queue_lock.unlock();
}
-19
View File
@@ -1,19 +0,0 @@
#ifndef EQEMU_DISCORD_MANAGER_H
#define EQEMU_DISCORD_MANAGER_H
#include <mutex>
#include <map>
#include <vector>
#include "../common/types.h"
class DiscordManager {
public:
void QueueWebhookMessage(uint32 webhook_id, const std::string& message);
void ProcessMessageQueue();
private:
std::mutex webhook_queue_lock{};
std::map<uint32, std::vector<std::string>> webhook_message_queue{};
};
#endif
+1 -51
View File
@@ -79,7 +79,6 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
m_max_players = dz_entry.max_players; m_max_players = dz_entry.max_players;
m_instance_id = dz_entry.instance_id; m_instance_id = dz_entry.instance_id;
m_type = static_cast<DynamicZoneType>(dz_entry.type); m_type = static_cast<DynamicZoneType>(dz_entry.type);
m_dz_switch_id = dz_entry.dz_switch_id;
m_compass.zone_id = dz_entry.compass_zone_id; m_compass.zone_id = dz_entry.compass_zone_id;
m_compass.x = dz_entry.compass_x; m_compass.x = dz_entry.compass_x;
m_compass.y = dz_entry.compass_y; m_compass.y = dz_entry.compass_y;
@@ -130,7 +129,6 @@ uint32_t DynamicZoneBase::SaveToDatabase()
insert_dz.max_players = m_max_players; insert_dz.max_players = m_max_players;
insert_dz.instance_id = m_instance_id, insert_dz.instance_id = m_instance_id,
insert_dz.type = static_cast<int>(m_type); insert_dz.type = static_cast<int>(m_type);
insert_dz.dz_switch_id = m_dz_switch_id;
insert_dz.compass_zone_id = m_compass.zone_id; insert_dz.compass_zone_id = m_compass.zone_id;
insert_dz.compass_x = m_compass.x; insert_dz.compass_x = m_compass.x;
insert_dz.compass_y = m_compass.y; insert_dz.compass_y = m_compass.y;
@@ -318,17 +316,6 @@ void DynamicZoneBase::SetZoneInLocation(float x, float y, float z, float heading
SetZoneInLocation({ 0, x, y, z, heading }, update_db); SetZoneInLocation({ 0, x, y, z, heading }, update_db);
} }
void DynamicZoneBase::SetSwitchID(int dz_switch_id, bool update_db)
{
m_dz_switch_id = dz_switch_id;
if (update_db)
{
DynamicZonesRepository::UpdateSwitchID(GetDatabase(), m_id, dz_switch_id);
SendServerPacket(CreateServerDzSwitchIDPacket().get());
}
}
void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update_db) void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update_db)
{ {
m_leader = new_leader; m_leader = new_leader;
@@ -416,17 +403,6 @@ std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzLocationPacket(
return pack; return pack;
} }
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzSwitchIDPacket()
{
constexpr uint32_t pack_size = sizeof(ServerDzSwitchID_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzSetSwitchID, pack_size);
auto buf = reinterpret_cast<ServerDzSwitchID_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->dz_switch_id = GetSwitchID();
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberStatusPacket( std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerMemberStatusPacket(
uint32_t character_id, DynamicZoneMemberStatus status) uint32_t character_id, DynamicZoneMemberStatus status)
{ {
@@ -585,9 +561,8 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
return "Mission"; return "Mission";
case DynamicZoneType::Quest: case DynamicZoneType::Quest:
return "Quest"; return "Quest";
default:
return "Unknown";
} }
return "Unknown";
} }
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket() EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
@@ -622,28 +597,3 @@ void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_
cereal::BinaryInputArchive archive(ss); cereal::BinaryInputArchive archive(ss);
archive(*this); archive(*this);
} }
void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template)
{
m_zone_id = dz_template.zone_id;
m_zone_version = dz_template.zone_version;
m_name = dz_template.name;
m_min_players = dz_template.min_players;
m_max_players = dz_template.max_players;
m_duration = std::chrono::seconds(dz_template.duration_seconds);
m_dz_switch_id = dz_template.dz_switch_id;
m_compass.zone_id = dz_template.compass_zone_id;
m_compass.x = dz_template.compass_x;
m_compass.y = dz_template.compass_y;
m_compass.z = dz_template.compass_z;
m_safereturn.zone_id = dz_template.return_zone_id;
m_safereturn.x = dz_template.return_x;
m_safereturn.y = dz_template.return_y;
m_safereturn.z = dz_template.return_z;
m_safereturn.heading = dz_template.return_h;
m_has_zonein = dz_template.override_zone_in;
m_zonein.x = dz_template.zone_in_x;
m_zonein.y = dz_template.zone_in_y;
m_zonein.z = dz_template.zone_in_z;
m_zonein.heading = dz_template.zone_in_h;
}
-9
View File
@@ -5,7 +5,6 @@
#include "net/packet.h" #include "net/packet.h"
#include "repositories/dynamic_zones_repository.h" #include "repositories/dynamic_zones_repository.h"
#include "repositories/dynamic_zone_members_repository.h" #include "repositories/dynamic_zone_members_repository.h"
#include "repositories/dynamic_zone_templates_repository.h"
#include <algorithm> #include <algorithm>
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
@@ -75,7 +74,6 @@ public:
virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0; virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0;
int GetDuration() const { return static_cast<int>(m_duration.count()); }
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); } uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint32_t GetID() const { return m_id; } uint32_t GetID() const { return m_id; }
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); } uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); }
@@ -87,7 +85,6 @@ public:
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_zone_id); } uint16_t GetZoneID() const { return static_cast<uint16_t>(m_zone_id); }
uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); } uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); }
uint32_t GetZoneVersion() const { return m_zone_version; } uint32_t GetZoneVersion() const { return m_zone_version; }
int GetSwitchID() const { return m_dz_switch_id; }
DynamicZoneType GetType() const { return m_type; } DynamicZoneType GetType() const { return m_type; }
const std::string& GetLeaderName() const { return m_leader.name; } const std::string& GetLeaderName() const { return m_leader.name; }
const std::string& GetName() const { return m_name; } const std::string& GetName() const { return m_name; }
@@ -115,7 +112,6 @@ public:
bool IsValid() const { return m_instance_id != 0; } bool IsValid() const { return m_instance_id != 0; }
bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; } bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; }
void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size); void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
void RemoveAllMembers(); void RemoveAllMembers();
bool RemoveMember(uint32_t character_id); bool RemoveMember(uint32_t character_id);
bool RemoveMember(const std::string& character_name); bool RemoveMember(const std::string& character_name);
@@ -131,7 +127,6 @@ public:
void SetName(const std::string& name) { m_name = name; } void SetName(const std::string& name) { m_name = name; }
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false); void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false); void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
void SetSwitchID(int dz_switch_id, bool update_db = false);
void SetType(DynamicZoneType type) { m_type = type; } void SetType(DynamicZoneType type) { m_type = type; }
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); } void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false); void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
@@ -146,7 +141,6 @@ protected:
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed); virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status); virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status);
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); } virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); }
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
virtual bool SendServerPacket(ServerPacket* packet) = 0; virtual bool SendServerPacket(ServerPacket* packet) = 0;
void AddInternalMember(const DynamicZoneMember& member); void AddInternalMember(const DynamicZoneMember& member);
@@ -159,7 +153,6 @@ protected:
std::unique_ptr<ServerPacket> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id); std::unique_ptr<ServerPacket> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id);
std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location); std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket();
std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed); std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed);
std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status); std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status);
std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member); std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
@@ -171,7 +164,6 @@ protected:
uint32_t m_zone_version = 0; uint32_t m_zone_version = 0;
uint32_t m_min_players = 0; uint32_t m_min_players = 0;
uint32_t m_max_players = 0; uint32_t m_max_players = 0;
int m_dz_switch_id = 0;
bool m_never_expires = false; bool m_never_expires = false;
bool m_has_zonein = false; bool m_has_zonein = false;
bool m_has_member_statuses = false; bool m_has_member_statuses = false;
@@ -198,7 +190,6 @@ public:
m_zone_version, m_zone_version,
m_min_players, m_min_players,
m_max_players, m_max_players,
m_dz_switch_id,
m_never_expires, m_never_expires,
m_has_zonein, m_has_zonein,
m_has_member_statuses, m_has_member_statuses,
+5 -387
View File
@@ -18,12 +18,8 @@
*/ */
#include "emu_constants.h" #include "emu_constants.h"
#include "bodytypes.h"
#include "data_verification.h"
#include "eqemu_logsys.h"
#include "eqemu_logsys_log_aliases.h"
#include "languages.h" #include "languages.h"
#include "rulesys.h"
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) { int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
static const int16 local_array[] = { static const int16 local_array[] = {
@@ -152,9 +148,8 @@ const char *EQ::constants::GetStanceName(StanceType stance_type) {
} }
int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) { int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
if (EQ::ValueWithin(stance_type, EQ::constants::stancePassive, EQ::constants::stanceBurnAE)) { if (stance_type >= EQ::constants::stancePassive && stance_type <= EQ::constants::stanceBurnAE)
return (stance_type - EQ::constants::stancePassive); return (stance_type - EQ::constants::stancePassive);
}
return 0; return 0;
} }
@@ -191,391 +186,14 @@ const std::map<int, std::string>& EQ::constants::GetLanguageMap()
{ LANG_HADAL, "Hadal" }, { LANG_HADAL, "Hadal" },
{ LANG_UNKNOWN, "Unknown" } { LANG_UNKNOWN, "Unknown" }
}; };
return language_map; return language_map;
} }
std::string EQ::constants::GetLanguageName(int language_id) std::string EQ::constants::GetLanguageName(int language_id)
{ {
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) { if (language_id >= LANG_COMMON_TONGUE && language_id <= LANG_UNKNOWN) {
return EQ::constants::GetLanguageMap().find(language_id)->second; auto languages = EQ::constants::GetLanguageMap();
return languages[language_id];
} }
return std::string();
}
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
{
static const std::map<uint32, std::string> ldon_theme_map = {
{ LDoNThemes::Unused, "Unused" },
{ LDoNThemes::GUK, "Deepest Guk" },
{ LDoNThemes::MIR, "Miragul's Menagerie" },
{ LDoNThemes::MMC, "Mistmoore Catacombs" },
{ LDoNThemes::RUJ, "Rujarkian Hills" },
{ LDoNThemes::TAK, "Takish-Hiz" },
};
return ldon_theme_map;
}
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
{
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
return std::string();
}
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
{
static const std::map<int8, std::string> flymode_map = {
{ GravityBehavior::Ground, "Ground" },
{ GravityBehavior::Flying, "Flying" },
{ GravityBehavior::Levitating, "Levitating" },
{ GravityBehavior::Water, "Water" },
{ GravityBehavior::Floating, "Floating" },
{ GravityBehavior::LevitateWhileRunning, "Levitating While Running" },
};
return flymode_map;
}
std::string EQ::constants::GetFlyModeName(int8 flymode_id)
{
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
}
return std::string();
}
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
{
static const std::map<bodyType, std::string> bodytype_map = {
{ BT_Humanoid, "Humanoid" },
{ BT_Lycanthrope, "Lycanthrope" },
{ BT_Undead, "Undead" },
{ BT_Giant, "Giant" },
{ BT_Construct, "Construct" },
{ BT_Extraplanar, "Extraplanar" },
{ BT_Magical, "Magical" },
{ BT_SummonedUndead, "Summoned Undead" },
{ BT_RaidGiant, "Raid Giant" },
{ BT_RaidColdain, "Raid Coldain" },
{ BT_NoTarget, "Untargetable" },
{ BT_Vampire, "Vampire" },
{ BT_Atenha_Ra, "Aten Ha Ra" },
{ BT_Greater_Akheva, "Greater Akheva" },
{ BT_Khati_Sha, "Khati Sha" },
{ BT_Seru, "Seru" },
{ BT_Grieg_Veneficus, "Grieg Veneficus" },
{ BT_Draz_Nurakk, "Draz Nurakk" },
{ BT_Zek, "Zek" },
{ BT_Luggald, "Luggald" },
{ BT_Animal, "Animal" },
{ BT_Insect, "Insect" },
{ BT_Monster, "Monster" },
{ BT_Summoned, "Summoned" },
{ BT_Plant, "Plant" },
{ BT_Dragon, "Dragon" },
{ BT_Summoned2, "Summoned 2" },
{ BT_Summoned3, "Summoned 3" },
{ BT_Dragon2, "Dragon 2" },
{ BT_VeliousDragon, "Velious Dragon" },
{ BT_Familiar, "Familiar" },
{ BT_Dragon3, "Dragon 3" },
{ BT_Boxes, "Boxes" },
{ BT_Muramite, "Muramite" },
{ BT_NoTarget2, "Untargetable 2" },
{ BT_SwarmPet, "Swarm Pet" },
{ BT_MonsterSummon, "Monster Summon" },
{ BT_InvisMan, "Invisible Man" },
{ BT_Special, "Special" },
};
return bodytype_map;
}
std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id)
{
if (EQ::constants::GetBodyTypeMap().find(bodytype_id) != EQ::constants::GetBodyTypeMap().end()) {
return EQ::constants::GetBodyTypeMap().find(bodytype_id)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetAccountStatusMap()
{
static const std::map<uint8, std::string> account_status_map = {
{ AccountStatus::Player, "Player" },
{ AccountStatus::Steward, "Steward" },
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
{ AccountStatus::Guide, "Guide" },
{ AccountStatus::QuestTroupe, "Quest Troupe" },
{ AccountStatus::SeniorGuide, "Senior Guide" },
{ AccountStatus::GMTester, "GM Tester" },
{ AccountStatus::EQSupport, "EQ Support" },
{ AccountStatus::GMStaff, "GM Staff" },
{ AccountStatus::GMAdmin, "GM Admin" },
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
{ AccountStatus::QuestMaster, "Quest Master" },
{ AccountStatus::GMAreas, "GM Areas" },
{ AccountStatus::GMCoder, "GM Coder" },
{ AccountStatus::GMMgmt, "GM Mgmt" },
{ AccountStatus::GMImpossible, "GM Impossible" },
{ AccountStatus::Max, "GM Max" }
};
return account_status_map;
}
std::string EQ::constants::GetAccountStatusName(uint8 account_status)
{
for (
auto status_level = EQ::constants::GetAccountStatusMap().rbegin();
status_level != EQ::constants::GetAccountStatusMap().rend();
++status_level
) {
if (account_status >= status_level->first) {
return status_level->second;
}
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
{
static const std::map<uint8, std::string> consider_level_map = {
{ ConsiderLevel::Ally, "Ally" },
{ ConsiderLevel::Warmly, "Warmly" },
{ ConsiderLevel::Kindly, "Kindly" },
{ ConsiderLevel::Amiably, "Amiably" },
{ ConsiderLevel::Indifferently, "Indifferently" },
{ ConsiderLevel::Apprehensively, "Apprehensively" },
{ ConsiderLevel::Dubiously, "Dubiously" },
{ ConsiderLevel::Threateningly, "Threateningly" },
{ ConsiderLevel::Scowls, "Scowls" }
};
return consider_level_map;
}
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
{
if (EQ::constants::GetConsiderLevelMap().find(faction_consider_level) != EQ::constants::GetConsiderLevelMap().end()) {
return EQ::constants::GetConsiderLevelMap().find(faction_consider_level)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
{
static const std::map<uint8, std::string> damage_type_map = {
{ EnvironmentalDamage::Lava, "Lava" },
{ EnvironmentalDamage::Drowning, "Drowning" },
{ EnvironmentalDamage::Falling, "Falling" },
{ EnvironmentalDamage::Trap, "Trap" }
};
return damage_type_map;
}
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
{
if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
return EQ::constants::GetEnvironmentalDamageMap().find(damage_type)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetStuckBehaviorMap()
{
static const std::map<uint8, std::string> stuck_behavior_map = {
{ StuckBehavior::RunToTarget, "Run To Target" },
{ StuckBehavior::WarpToTarget, "Warp To Target" },
{ StuckBehavior::TakeNoAction, "Take No Action" },
{ StuckBehavior::EvadeCombat, "Evade Combat" }
};
return stuck_behavior_map;
}
std::string EQ::constants::GetStuckBehaviorName(uint8 behavior_id)
{
if (EQ::ValueWithin(behavior_id, StuckBehavior::RunToTarget, StuckBehavior::EvadeCombat)) {
return EQ::constants::GetStuckBehaviorMap().find(behavior_id)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetSpawnAnimationMap()
{
static const std::map<uint8, std::string> spawn_animation_map = {
{ SpawnAnimations::Standing, "Standing" },
{ SpawnAnimations::Sitting, "Sitting" },
{ SpawnAnimations::Crouching, "Crouching" },
{ SpawnAnimations::Laying, "Laying" },
{ SpawnAnimations::Looting, "Looting" }
};
return spawn_animation_map;
}
std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
{
if (EQ::ValueWithin(animation_id, SpawnAnimations::Standing, SpawnAnimations::Looting)) {
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
}
return std::string();
}
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
{
static const std::map<int, std::string> object_type_map = {
{ ObjectTypes::SmallBag, "Small Bag" },
{ ObjectTypes::LargeBag, "Large Bag" },
{ ObjectTypes::Quiver, "Quiver" },
{ ObjectTypes::BeltPouch, "Belt Pouch" },
{ ObjectTypes::WristPouch, "Wrist Pouch" },
{ ObjectTypes::Backpack, "Backpack" },
{ ObjectTypes::SmallChest, "Small Chest" },
{ ObjectTypes::LargeChest, "Large Chest" },
{ ObjectTypes::Bandolier, "Bandolier" },
{ ObjectTypes::Medicine, "Medicine" },
{ ObjectTypes::Tinkering, "Tinkering" },
{ ObjectTypes::Lexicon, "Lexicon" },
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
{ ObjectTypes::Quest, "Quest" },
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
{ ObjectTypes::Baking, "Baking" },
{ ObjectTypes::Tailoring, "Tailoring" },
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
{ ObjectTypes::Fletching, "Fletching" },
{ ObjectTypes::Brewing, "Brewing" },
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
{ ObjectTypes::Pottery, "Pottery" },
{ ObjectTypes::Kiln, "Kiln" },
{ ObjectTypes::KeyMaker, "Key Maker" },
{ ObjectTypes::ResearchWIZ, "Lexicon" },
{ ObjectTypes::ResearchMAG, "Lexicon" },
{ ObjectTypes::ResearchNEC, "Lexicon" },
{ ObjectTypes::ResearchENC, "Lexicon" },
{ ObjectTypes::Unknown, "Unknown" },
{ ObjectTypes::ResearchPractice, "Lexicon" },
{ ObjectTypes::Alchemy, "Alchemy" },
{ ObjectTypes::HighElfForge, "High Elf Forge" },
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
{ ObjectTypes::OgreForge, "Ogre Forge" },
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
{ ObjectTypes::GnomeForge, "Gnome Forge" },
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
{ ObjectTypes::IksarForge, "Iksar Forge" },
{ ObjectTypes::HumanForgeOne, "Human Forge" },
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
{ ObjectTypes::Fishing, "Fishing" },
{ ObjectTypes::TrollForge, "Troll Forge" },
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
{ ObjectTypes::HalflingForge, "Halfling Forge" },
{ ObjectTypes::EruditeForge, "Erudite Forge" },
{ ObjectTypes::Merchant, "Merchant" },
{ ObjectTypes::FroglokForge, "Froglok Forge" },
{ ObjectTypes::Augmenter, "Augmenter" },
{ ObjectTypes::Churn, "Churn" },
{ ObjectTypes::TransformationMold, "Transformation Mold" },
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
{ ObjectTypes::Unattuner, "Unattuner" },
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
{ ObjectTypes::NoDeposit, "No Deposit" }
};
return object_type_map;
}
std::string EQ::constants::GetObjectTypeName(int object_type)
{
if (EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
{
static const std::map<uint8, std::string> weather_type_map = {
{WeatherTypes::None, "None"},
{WeatherTypes::Raining, "Raining"},
{WeatherTypes::Snowing, "Snowing"}
};
return weather_type_map;
}
std::string EQ::constants::GetWeatherTypeName(uint8 weather_type)
{
if (EQ::ValueWithin(weather_type, WeatherTypes::None, WeatherTypes::Snowing)) {
return EQ::constants::GetWeatherTypeMap().find(weather_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteEventTypeMap()
{
static const std::map<uint8, std::string> emote_event_type_map = {
{ EmoteEventTypes::LeaveCombat, "Leave Combat" },
{ EmoteEventTypes::EnterCombat, "Enter Combat" },
{ EmoteEventTypes::OnDeath, "On Death" },
{ EmoteEventTypes::AfterDeath, "After Death" },
{ EmoteEventTypes::Hailed, "Hailed" },
{ EmoteEventTypes::KilledPC, "Killed PC" },
{ EmoteEventTypes::KilledNPC, "Killed NPC" },
{ EmoteEventTypes::OnSpawn, "On Spawn" },
{ EmoteEventTypes::OnDespawn, "On Despawn" }
};
return emote_event_type_map;
}
std::string EQ::constants::GetEmoteEventTypeName(uint8 emote_event_type)
{
if (EQ::ValueWithin(emote_event_type, EmoteEventTypes::LeaveCombat, EmoteEventTypes::OnDespawn)) {
return EQ::constants::GetEmoteEventTypeMap().find(emote_event_type)->second;
}
return std::string();
}
const std::map<uint8, std::string> &EQ::constants::GetEmoteTypeMap()
{
static const std::map<uint8, std::string> emote_type_map = {
{ EmoteTypes::Emote, "Emote" },
{ EmoteTypes::Shout, "Shout" },
{ EmoteTypes::Proximity, "Proximity" }
};
return emote_type_map;
}
std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
{
if (EQ::ValueWithin(emote_type, EmoteTypes::Emote, EmoteTypes::Proximity)) {
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
}
return std::string(); return std::string();
} }
+11 -267
View File
@@ -22,7 +22,6 @@
#include "eq_limits.h" #include "eq_limits.h"
#include "emu_versions.h" #include "emu_versions.h"
#include "bodytypes.h"
#include <string.h> #include <string.h>
@@ -33,6 +32,10 @@ namespace EQ
using RoF2::IINVALID; using RoF2::IINVALID;
using RoF2::INULL; using RoF2::INULL;
namespace inventory {
} /*inventory*/
namespace invtype { namespace invtype {
using namespace RoF2::invtype::enum_; using namespace RoF2::invtype::enum_;
@@ -217,186 +220,12 @@ namespace EQ
stanceBurnAE stanceBurnAE
}; };
enum BotSpellIDs : int {
Warrior = 3001,
Cleric,
Paladin,
Ranger,
Shadowknight,
Druid,
Monk,
Bard,
Rogue,
Shaman,
Necromancer,
Wizard,
Magician,
Enchanter,
Beastlord,
Berserker
};
enum GravityBehavior : int8 {
Ground,
Flying,
Levitating,
Water,
Floating,
LevitateWhileRunning
};
enum EnvironmentalDamage : uint8 {
Lava = 250,
Drowning,
Falling,
Trap
};
enum StuckBehavior : uint8 {
RunToTarget,
WarpToTarget,
TakeNoAction,
EvadeCombat
};
enum SpawnAnimations : uint8 {
Standing,
Sitting,
Crouching,
Laying,
Looting
};
enum ObjectTypes : int {
SmallBag,
LargeBag,
Quiver,
BeltPouch,
WristPouch,
Backpack,
SmallChest,
LargeChest,
Bandolier,
Medicine,
Tinkering,
Lexicon,
PoisonMaking,
Quest,
MixingBowl,
Baking,
Tailoring,
Blacksmithing,
Fletching,
Brewing,
JewelryMaking,
Pottery,
Kiln,
KeyMaker,
ResearchWIZ,
ResearchMAG,
ResearchNEC,
ResearchENC,
Unknown,
ResearchPractice,
Alchemy,
HighElfForge,
DarkElfForge,
OgreForge,
DwarfForge,
GnomeForge,
BarbarianForge,
IksarForge,
HumanForgeOne,
HumanForgeTwo,
HalflingTailoringOne,
HalflingTailoringTwo,
EruditeTailoring,
WoodElfTailoring,
WoodElfFletching,
IksarPottery,
Fishing,
TrollForge,
WoodElfForge,
HalflingForge,
EruditeForge,
Merchant,
FroglokForge,
Augmenter,
Churn,
TransformationMold,
DetransformationMold,
Unattuner,
TradeskillBag,
CollectibleBag,
NoDeposit
};
enum WeatherTypes : uint8 {
None,
Raining,
Snowing
};
enum EmoteEventTypes : uint8 {
LeaveCombat,
EnterCombat,
OnDeath,
AfterDeath,
Hailed,
KilledPC,
KilledNPC,
OnSpawn,
OnDespawn
};
enum EmoteTypes : uint8 {
Emote,
Shout,
Proximity
};
const char *GetStanceName(StanceType stance_type); const char *GetStanceName(StanceType stance_type);
int ConvertStanceTypeToIndex(StanceType stance_type); int ConvertStanceTypeToIndex(StanceType stance_type);
extern const std::map<int, std::string>& GetLanguageMap(); extern const std::map<int, std::string>& GetLanguageMap();
std::string GetLanguageName(int language_id); std::string GetLanguageName(int language_id);
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
std::string GetLDoNThemeName(uint32 theme_id);
extern const std::map<int8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(int8 flymode_id);
extern const std::map<bodyType, std::string>& GetBodyTypeMap();
std::string GetBodyTypeName(bodyType bodytype_id);
extern const std::map<uint8, std::string>& GetAccountStatusMap();
std::string GetAccountStatusName(uint8 account_status);
extern const std::map<uint8, std::string>& GetConsiderLevelMap();
std::string GetConsiderLevelName(uint8 consider_level);
extern const std::map<uint8, std::string>& GetEnvironmentalDamageMap();
std::string GetEnvironmentalDamageName(uint8 damage_type);
extern const std::map<uint8, std::string>& GetStuckBehaviorMap();
std::string GetStuckBehaviorName(uint8 behavior_id);
extern const std::map<uint8, std::string>& GetSpawnAnimationMap();
std::string GetSpawnAnimationName(uint8 animation_id);
extern const std::map<int, std::string>& GetObjectTypeMap();
std::string GetObjectTypeName(int object_type);
extern const std::map<uint8, std::string>& GetWeatherTypeMap();
std::string GetWeatherTypeName(uint8 weather_type);
extern const std::map<uint8, std::string>& GetEmoteEventTypeMap();
std::string GetEmoteEventTypeName(uint8 emote_event_type);
extern const std::map<uint8, std::string>& GetEmoteTypeMap();
std::string GetEmoteTypeName(uint8 emote_type);
const int STANCE_TYPE_FIRST = stancePassive; const int STANCE_TYPE_FIRST = stancePassive;
const int STANCE_TYPE_LAST = stanceBurnAE; const int STANCE_TYPE_LAST = stanceBurnAE;
const int STANCE_TYPE_COUNT = stanceBurnAE; const int STANCE_TYPE_COUNT = stanceBurnAE;
@@ -499,98 +328,13 @@ namespace EQ
Guild Guild
}; };
}; // namespace consent }; // namespace consent
} /*EQEmu*/ } /*EQEmu*/
enum ServerLockType : int {
List,
Lock,
Unlock
};
enum AccountStatus : uint8 {
Player = 0,
Steward = 10,
ApprenticeGuide = 20,
Guide = 50,
QuestTroupe = 80,
SeniorGuide = 81,
GMTester = 85,
EQSupport = 90,
GMStaff = 95,
GMAdmin = 100,
GMLeadAdmin = 150,
QuestMaster = 160,
GMAreas = 170,
GMCoder = 180,
GMMgmt = 200,
GMImpossible = 250,
Max = 255
};
enum Invisibility : uint8 {
Visible,
Invisible,
Special = 255
};
enum AugmentActions : int {
Insert,
Remove,
Swap,
Destroy
};
enum ConsiderLevel : uint8 {
Ally = 1,
Warmly,
Kindly,
Amiably,
Indifferently,
Apprehensively,
Dubiously,
Threateningly,
Scowls
};
enum TargetDescriptionType : uint8 {
LCSelf,
UCSelf,
LCYou,
UCYou,
LCYour,
UCYour
};
enum ReloadWorld : uint8 {
NoRepop = 0,
Repop,
ForceRepop
};
enum BucketComparison : uint8 {
BucketEqualTo = 0,
BucketNotEqualTo,
BucketGreaterThanOrEqualTo,
BucketLesserThanOrEqualTo,
BucketGreaterThan,
BucketLesserThan,
BucketIsAny,
BucketIsNotAny,
BucketIsBetween,
BucketIsNotBetween
};
enum class EntityFilterType {
All,
Bots,
Clients,
NPCs
};
enum class ApplySpellType {
Solo,
Group,
Raid
};
#endif /*COMMON_EMU_CONSTANTS_H*/ #endif /*COMMON_EMU_CONSTANTS_H*/
/* hack list to prevent circular references
eq_limits.h:EQ::inventory::LookupEntry::InventoryTypeSize[n];
*/
+3 -7
View File
@@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest),
N(OP_AltCurrencyPurchase), N(OP_AltCurrencyPurchase),
N(OP_AltCurrencyReclaim), N(OP_AltCurrencyReclaim),
N(OP_AltCurrencySell), N(OP_AltCurrencySell),
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069 N(OP_AltCurrencySellSelection),
N(OP_Animation), N(OP_Animation),
N(OP_AnnoyingZoneUnknown), N(OP_AnnoyingZoneUnknown),
N(OP_ApplyPoison), N(OP_ApplyPoison),
@@ -71,7 +71,6 @@ N(OP_Camp),
N(OP_CancelSneakHide), N(OP_CancelSneakHide),
N(OP_CancelTask), N(OP_CancelTask),
N(OP_CancelTrade), N(OP_CancelTrade),
N(OP_CashReward),
N(OP_CastSpell), N(OP_CastSpell),
N(OP_ChangeSize), N(OP_ChangeSize),
N(OP_ChannelMessage), N(OP_ChannelMessage),
@@ -130,8 +129,8 @@ N(OP_DisciplineTimer),
N(OP_DisciplineUpdate), N(OP_DisciplineUpdate),
N(OP_DiscordMerchantInventory), N(OP_DiscordMerchantInventory),
N(OP_DoGroupLeadershipAbility), N(OP_DoGroupLeadershipAbility),
N(OP_DuelDecline), N(OP_DuelResponse),
N(OP_DuelAccept), N(OP_DuelResponse2),
N(OP_DumpName), N(OP_DumpName),
N(OP_Dye), N(OP_Dye),
N(OP_DynamicWall), N(OP_DynamicWall),
@@ -304,7 +303,6 @@ N(OP_LockoutTimerInfo),
N(OP_Login), N(OP_Login),
N(OP_LoginAccepted), N(OP_LoginAccepted),
N(OP_LoginComplete), N(OP_LoginComplete),
N(OP_LoginExpansionPacketData), //added for Rof2 client to send expansion data packet. Requires login_opcodes_sod.conf to be updated.
N(OP_LoginUnknown1), N(OP_LoginUnknown1),
N(OP_LoginUnknown2), N(OP_LoginUnknown2),
N(OP_Logout), N(OP_Logout),
@@ -457,7 +455,6 @@ N(OP_ServerListResponse),
N(OP_SessionReady), N(OP_SessionReady),
N(OP_SetChatServer), N(OP_SetChatServer),
N(OP_SetChatServer2), N(OP_SetChatServer2),
N(OP_SetFace),
N(OP_SetGroupTarget), N(OP_SetGroupTarget),
N(OP_SetGuildMOTD), N(OP_SetGuildMOTD),
N(OP_SetGuildRank), N(OP_SetGuildRank),
@@ -561,7 +558,6 @@ N(OP_WhoAllRequest),
N(OP_WhoAllResponse), N(OP_WhoAllResponse),
N(OP_World_Client_CRC1), N(OP_World_Client_CRC1),
N(OP_World_Client_CRC2), N(OP_World_Client_CRC2),
N(OP_World_Client_CRC3),
N(OP_WorldClientReady), N(OP_WorldClientReady),
N(OP_WorldComplete), N(OP_WorldComplete),
N(OP_WorldLogout), N(OP_WorldLogout),
+9 -26
View File
@@ -684,6 +684,14 @@ namespace Zones {
constexpr uint16 APPRENTICE = 999; // Designer Apprentice constexpr uint16 APPRENTICE = 999; // Designer Apprentice
} }
//ZoneChange_Struct->success values
#define ZONE_ERROR_NOMSG 0
#define ZONE_ERROR_NOTREADY -1
#define ZONE_ERROR_VALIDPC -2
#define ZONE_ERROR_STORYZONE -3
#define ZONE_ERROR_NOEXPANSION -6
#define ZONE_ERROR_NOEXPERIENCE -7
typedef enum { typedef enum {
FilterNone = 0, FilterNone = 0,
@@ -710,7 +718,7 @@ typedef enum {
FilterPetMisses = 21, //0=show, 1=hide FilterPetMisses = 21, //0=show, 1=hide
FilterFocusEffects = 22, //0=show, 1=hide FilterFocusEffects = 22, //0=show, 1=hide
FilterPetSpells = 23, //0=show, 1=hide FilterPetSpells = 23, //0=show, 1=hide
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide FilterHealOverTime = 24, //0=show, 1=hide
FilterUnknown25 = 25, FilterUnknown25 = 25,
FilterUnknown26 = 26, FilterUnknown26 = 26,
FilterUnknown27 = 27, FilterUnknown27 = 27,
@@ -1001,29 +1009,4 @@ enum StartZoneIndex {
SharVahl SharVahl
}; };
enum FVNoDropFlagRule
{
Disabled = 0,
Enabled = 1,
AdminOnly = 2
};
enum Anonymity : uint8
{
NotAnonymous,
Anonymous,
Roleplaying
};
enum ZoningMessage : int8
{
ZoneNoMessage = 0,
ZoneSuccess = 1,
ZoneNotReady = -1,
ZoneValidPC = -2,
ZoneStoryZone = -3,
ZoneNoExpansion = -6,
ZoneNoExperience = -7
};
#endif /*COMMON_EQ_CONSTANTS_H*/ #endif /*COMMON_EQ_CONSTANTS_H*/
+1 -1
View File
@@ -26,7 +26,7 @@
static bool global_dictionary_init = false; static bool global_dictionary_init = false;
void EQ::InitializeDynamicLookups() { void EQ::InitializeDynamicLookups() {
if (global_dictionary_init) if (global_dictionary_init == true)
return; return;
constants::InitializeDynamicLookups(); constants::InitializeDynamicLookups();
+17 -37
View File
@@ -378,14 +378,14 @@ struct NewZone_Struct {
// Titanium doesn't have a translator, but we can still safely add stuff under here without issues since client memcpy's only what it knows // Titanium doesn't have a translator, but we can still safely add stuff under here without issues since client memcpy's only what it knows
// Just wastes some bandwidth sending to tit clients /shrug // Just wastes some bandwidth sending to tit clients /shrug
/*0700*/ float fog_density; /*0700*/ float fog_density;
/*0704*/ uint32 suspend_buffs; /*0704*/ uint32 SuspendBuffs;
/*0708*/ uint32 fast_regen_hp; /*0708*/ uint32 FastRegenHP;
/*0712*/ uint32 fast_regen_mana; /*0712*/ uint32 FastRegenMana;
/*0716*/ uint32 fast_regen_endurance; /*0716*/ uint32 FastRegenEndurance;
/*0720*/ uint32 npc_aggro_max_dist; /*0720*/ uint32 NPCAggroMaxDist;
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld /*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
/*0728*/ uint32 lava_damage; // Seen 50 /*0728*/ uint32 LavaDamage; // Seen 50
/*0732*/ uint32 min_lava_damage; // Seen 10 /*0732*/ uint32 MinLavaDamage; // Seen 10
/*0736*/ /*0736*/
}; };
@@ -448,7 +448,6 @@ struct ManaChange_Struct
/*08*/ uint32 spell_id; /*08*/ uint32 spell_id;
/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? /*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting?
/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like /*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like
/*16*/ int32 slot; // -1 normal, otherwise clear ETA and GCD
}; };
struct SwapSpell_Struct struct SwapSpell_Struct
@@ -2192,19 +2191,11 @@ struct QuestReward_Struct
/*068*/ /*068*/
}; };
struct CashReward_Struct
{
/*000*/ uint32 copper;
/*004*/ uint32 silver;
/*008*/ uint32 gold;
/*012*/ uint32 platinum;
};
// Size: 8 // Size: 8
struct Camera_Struct struct Camera_Struct
{ {
uint32 duration; // Duration in ms uint32 duration; // Duration in ms
float intensity; uint32 intensity; // Between 1023410176 and 1090519040
}; };
struct ZonePoint_Entry { struct ZonePoint_Entry {
@@ -2324,12 +2315,9 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle; /*004*/ uint8 hairstyle;
/*005*/ uint8 beard; /*005*/ uint8 beard;
/*006*/ uint8 face; /*006*/ uint8 face;
/*007*/ uint8 unused_padding; /*007*/ uint32 drakkin_heritage;
/*008*/ uint32 drakkin_heritage; /*011*/ uint32 drakkin_tattoo;
/*012*/ uint32 drakkin_tattoo; /*015*/ uint32 drakkin_details;
/*016*/ uint32 drakkin_details;
/*020*/ uint32 entity_id;
/*024*/
//there are only 10 faces for barbs changing woad just //there are only 10 faces for barbs changing woad just
//increase the face value by ten so if there were 8 woad //increase the face value by ten so if there were 8 woad
//designs then there would be 80 barb faces //designs then there would be 80 barb faces
@@ -2773,7 +2761,7 @@ struct EnvDamage2_Struct {
/*0004*/ uint16 unknown4; /*0004*/ uint16 unknown4;
/*0006*/ uint32 damage; /*0006*/ uint32 damage;
/*0010*/ uint8 unknown10[12]; /*0010*/ uint8 unknown10[12];
/*0022*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap /*0022*/ uint8 dmgtype; //FA = Lava; FC = Falling
/*0023*/ uint8 unknown2[4]; /*0023*/ uint8 unknown2[4];
/*0027*/ uint16 constant; //Always FFFF /*0027*/ uint16 constant; //Always FFFF
/*0029*/ uint16 unknown29; /*0029*/ uint16 unknown29;
@@ -3640,9 +3628,6 @@ struct MerchantList {
uint16 alt_currency_cost; uint16 alt_currency_cost;
uint32 classes_required; uint32 classes_required;
uint8 probability; uint8 probability;
std::string bucket_name;
std::string bucket_value;
uint8 bucket_comparison;
}; };
struct TempMerchantList { struct TempMerchantList {
@@ -5006,7 +4991,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair /*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id; /*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 dz_switch_id; /*008*/ uint32 unknown008;
/*012*/ float y; /*012*/ float y;
/*016*/ float x; /*016*/ float x;
/*020*/ float z; /*020*/ float z;
@@ -5163,10 +5148,10 @@ struct AltCurrencySelectItemReply_Struct {
/*000*/ uint32 unknown000; /*000*/ uint32 unknown000;
/*004*/ uint8 unknown004; //0xff /*004*/ uint8 unknown004; //0xff
/*005*/ uint8 unknown005; //0xff /*005*/ uint8 unknown005; //0xff
/*006*/ uint16 unknown006; //0xffff /*006*/ uint8 unknown006; //0xff
/*008*/ uint16 unknown008; //0xffff /*007*/ uint8 unknown007; //0xff
/*010*/ char item_name[64]; /*008*/ char item_name[64];
/*074*/ uint16 unknown074; /*072*/ uint32 unknown074;
/*076*/ uint32 cost; /*076*/ uint32 cost;
/*080*/ uint32 unknown080; /*080*/ uint32 unknown080;
/*084*/ uint32 unknown084; /*084*/ uint32 unknown084;
@@ -5596,11 +5581,6 @@ struct SayLinkBodyFrame_Struct {
/*056*/ /*056*/
}; };
struct Checksum_Struct {
uint64 checksum;
uint8 data[2048];
};
struct UpdateMovementEntry { struct UpdateMovementEntry {
/* 00 */ float Y; /* 00 */ float Y;
/* 04 */ float X; /* 04 */ float X;
+1 -1
View File
@@ -23,7 +23,7 @@
#include "op_codes.h" #include "op_codes.h"
#include "crc16.h" #include "crc16.h"
#include "platform.h" #include "platform.h"
#include "strings.h" #include "string_util.h"
#include <string> #include <string>
#include <iomanip> #include <iomanip>
-5
View File
@@ -243,11 +243,6 @@ class EQStream : public EQStreamInterface {
virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; } virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; }
virtual OpcodeManager* GetOpcodeManager() const
{
return (*OpMgr);
};
void CheckTimeout(uint32 now, uint32 timeout=30); void CheckTimeout(uint32 now, uint32 timeout=30);
bool HasOutgoingData(); bool HasOutgoingData();
void Process(const unsigned char *data, const uint32 length); void Process(const unsigned char *data, const uint32 length);
-1
View File
@@ -100,7 +100,6 @@ public:
virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; } virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; }
virtual EQStreamState GetState() = 0; virtual EQStreamState GetState() = 0;
virtual void SetOpcodeManager(OpcodeManager **opm) = 0; virtual void SetOpcodeManager(OpcodeManager **opm) = 0;
virtual OpcodeManager* GetOpcodeManager() const = 0;
virtual const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; } virtual const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; }
virtual Stats GetStats() const = 0; virtual Stats GetStats() const = 0;
virtual void ResetStats() = 0; virtual void ResetStats() = 0;
+5 -6
View File
@@ -38,8 +38,12 @@ void EQStreamProxy::SetOpcodeManager(OpcodeManager **opm)
} }
void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) { void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
if (p == nullptr) { if(p == nullptr)
return; return;
if (p->GetOpcode() != OP_SpecialMesg) {
Log(Logs::General, Logs::PacketServerClient, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
Log(Logs::General, Logs::PacketServerClientWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
} }
EQApplicationPacket *newp = p->Copy(); EQApplicationPacket *newp = p->Copy();
@@ -108,8 +112,3 @@ bool EQStreamProxy::CheckState(EQStreamState state) {
return false; return false;
} }
OpcodeManager *EQStreamProxy::GetOpcodeManager() const
{
return (*m_opcodes);
}
+1 -3
View File
@@ -34,15 +34,13 @@ public:
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats(); virtual void ResetStats();
virtual EQStreamManagerInterface* GetManager() const; virtual EQStreamManagerInterface* GetManager() const;
virtual OpcodeManager* GetOpcodeManager() const;
protected: protected:
std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object. std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object.
const StructStrategy *const m_structs; //we do not own this object. const StructStrategy *const m_structs; //we do not own this object.
//this is a pointer to a pointer to make it less likely that a packet will //this is a pointer to a pointer to make it less likely that a packet will
//reference an invalid opcode manager when they are being reloaded. //reference an invalid opcode manager when they are being reloaded.
OpcodeManager **const m_opcodes; OpcodeManager **const m_opcodes; //we do not own this object.
//we do not own this object.
}; };
#endif /*EQSTREAMPROXY_H_*/ #endif /*EQSTREAMPROXY_H_*/
-4
View File
@@ -100,10 +100,6 @@ void EQEmuConfig::parse_config()
WorldHTTPEnabled = true; WorldHTTPEnabled = true;
} }
if (_root["server"].get("disable_config_checks", "false").asString() == "true") {
DisableConfigChecks = true;
}
/** /**
* UCS * UCS
*/ */
+5 -16
View File
@@ -20,9 +20,7 @@
#include "json/json.h" #include "json/json.h"
#include "linked_list.h" #include "linked_list.h"
#include "path_manager.h"
#include <fstream> #include <fstream>
#include <fmt/format.h>
struct LoginConfig { struct LoginConfig {
std::string LoginHost; std::string LoginHost;
@@ -60,7 +58,6 @@ class EQEmuConfig
uint16 WorldHTTPPort; uint16 WorldHTTPPort;
std::string WorldHTTPMimeFile; std::string WorldHTTPMimeFile;
std::string SharedKey; std::string SharedKey;
bool DisableConfigChecks;
// From <chatserver/> // From <chatserver/>
std::string ChatHost; std::string ChatHost;
@@ -154,31 +151,23 @@ class EQEmuConfig
} }
// Load the config // Load the config
static bool LoadConfig(const std::string& path = "") static bool LoadConfig()
{ {
if (_config != nullptr) { if (_config != nullptr) {
return true; return true;
} }
_config = new EQEmuConfig; _config = new EQEmuConfig;
return parseFile(path); return parseFile();
} }
// Load config file and parse data // Load config file and parse data
static bool parseFile(const std::string& file_path = ".") static bool parseFile() {
{
if (_config == nullptr) { if (_config == nullptr) {
return LoadConfig(file_path); return LoadConfig();
} }
std::string file = fmt::format( std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary);
"{}/{}",
(file_path.empty() ? path.GetServerPath() : file_path),
EQEmuConfig::ConfigFile
);
std::ifstream fconfig(file, std::ifstream::binary);
try { try {
fconfig >> _config->_root; fconfig >> _config->_root;
_config->parse_config(); _config->parse_config();
+294 -354
View File
@@ -21,20 +21,20 @@
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "rulesys.h" #include "rulesys.h"
#include "platform.h" #include "platform.h"
#include "strings.h" #include "string_util.h"
#include "repositories/discord_webhooks_repository.h" #include "misc.h"
#include "repositories/logsys_categories_repository.h" #include "repositories/logsys_categories_repository.h"
#include "termcolor/rang.hpp"
#include <iostream> #include <iostream>
#include <fstream>
#include <string> #include <string>
#include <iomanip>
#include <time.h> #include <time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <algorithm>
std::ofstream process_log; std::ofstream process_log;
#include <filesystem>
#ifdef _WINDOWS #ifdef _WINDOWS
#include <direct.h> #include <direct.h>
#include <conio.h> #include <conio.h>
@@ -46,17 +46,50 @@ std::ofstream process_log;
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <thread>
#endif #endif
/**
* Linux ANSI console color defines
*/
#define LC_RESET "\033[0m"
#define LC_BLACK "\033[30m" /* Black */
#define LC_RED "\033[31m" /* Red */
#define LC_GREEN "\033[32m" /* Green */
#define LC_YELLOW "\033[33m" /* Yellow */
#define LC_BLUE "\033[34m" /* Blue */
#define LC_MAGENTA "\033[35m" /* Magenta */
#define LC_CYAN "\033[36m" /* Cyan */
#define LC_WHITE "\033[37m" /* White */
namespace Console {
enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
LightMagenta = 13,
Yellow = 14,
White = 15
};
}
/** /**
* EQEmuLogSys Constructor * EQEmuLogSys Constructor
*/ */
EQEmuLogSys::EQEmuLogSys() EQEmuLogSys::EQEmuLogSys()
{ {
m_on_log_gmsay_hook = [](uint16 log_type, const char *func, const std::string &) {}; on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
m_on_log_console_hook = [](uint16 log_type, const std::string &) {}; on_log_console_hook = [](uint16 debug_level, uint16 log_type, const std::string &) {};
} }
/** /**
@@ -69,23 +102,28 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/** /**
* Get Executable platform currently running this code (Zone/World/etc) * Get Executable platform currently running this code (Zone/World/etc)
*/ */
m_log_platform = GetExecutablePlatformInt(); log_platform = GetExecutablePlatformInt();
for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) { for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) {
log_settings[log_category_id].log_to_console = 0; log_settings[log_category_id].log_to_console = 0;
log_settings[log_category_id].log_to_file = 0; log_settings[log_category_id].log_to_file = 0;
log_settings[log_category_id].log_to_gmsay = 0; log_settings[log_category_id].log_to_gmsay = 0;
log_settings[log_category_id].log_to_discord = 0;
log_settings[log_category_id].is_category_enabled = 0; log_settings[log_category_id].is_category_enabled = 0;
} }
m_file_logs_enabled = false; file_logs_enabled = false;
/** /**
* Set Defaults * Set Defaults
*/ */
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General); log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General); log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
@@ -94,18 +132,16 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General); log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::CombatRecord].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
/** /**
* RFC 5424 * RFC 5424
*/ */
log_settings[Logs::Emergency].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Alert].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Critical].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Notice].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
/** /**
@@ -115,8 +151,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
const bool log_to_console = log_settings[log_category_id].log_to_console > 0; const bool log_to_console = log_settings[log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[log_category_id].log_to_file > 0; const bool log_to_file = log_settings[log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0; const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0;
const bool log_to_discord = log_settings[log_category_id].log_to_discord > 0; const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord;
if (is_category_enabled) { if (is_category_enabled) {
log_settings[log_category_id].is_category_enabled = 1; log_settings[log_category_id].is_category_enabled = 1;
} }
@@ -125,37 +160,99 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/** /**
* Declare process file names for log writing= * Declare process file names for log writing=
*/ */
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld) { if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) {
m_platform_file_name = "world"; platform_file_name = "world";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformQueryServ) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
m_platform_file_name = "query_server"; platform_file_name = "query_server";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
m_platform_file_name = "zone"; platform_file_name = "zone";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformUCS) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) {
m_platform_file_name = "ucs"; platform_file_name = "ucs";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLogin) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) {
m_platform_file_name = "login"; platform_file_name = "login";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformLaunch) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) {
m_platform_file_name = "launcher"; platform_file_name = "launcher";
} }
else if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformHC) { else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) {
m_platform_file_name = "hc"; platform_file_name = "hc";
} }
return this; return this;
} }
/**
* @param log_category
* @return
*/
bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category)
{
return (
log_category == Logs::Emergency ||
log_category == Logs::Alert ||
log_category == Logs::Critical ||
log_category == Logs::Error ||
log_category == Logs::Warning ||
log_category == Logs::Notice ||
log_category == Logs::Info ||
log_category == Logs::Debug
);
}
/**
* @param log_category
* @param in_message
* @return
*/
std::string EQEmuLogSys::FormatOutMessageString(
uint16 log_category,
const std::string &in_message
)
{
std::string return_string = "[" + GetPlatformName() + "] ";
return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message;
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessGMSay(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
{
/**
* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
*/
if (log_category == Logs::LogCategory::Netcode) {
return;
}
/**
* Processes that actually support hooks
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld
) {
on_log_gmsay_hook(log_category, message);
}
}
/** /**
* @param debug_level * @param debug_level
* @param log_category * @param log_category
* @param message * @param message
*/ */
void EQEmuLogSys::ProcessLogWrite( void EQEmuLogSys::ProcessLogWrite(
uint16 debug_level,
uint16 log_category, uint16 log_category,
const std::string &message const std::string &message
) )
@@ -166,20 +263,79 @@ void EQEmuLogSys::ProcessLogWrite(
std::ofstream crash_log; std::ofstream crash_log;
EQEmuLogSys::MakeDirectory("logs/crashes"); EQEmuLogSys::MakeDirectory("logs/crashes");
crash_log.open( crash_log.open(
StringFormat("logs/crashes/crash_%s_%i.log", m_platform_file_name.c_str(), getpid()), StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out std::ios_base::app | std::ios_base::out
); );
crash_log << time_stamp << " " << message << "\n"; crash_log << time_stamp << " " << message << "\n";
crash_log.close(); crash_log.close();
} }
if (process_log) {
char time_stamp[80]; char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp); EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
if (process_log) {
process_log << time_stamp << " " << message << std::endl; process_log << time_stamp << " " << message << std::endl;
} }
} }
/**
* @param log_category
* @return
*/
uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) {
case Logs::Status:
case Logs::Normal:
return Console::Color::Yellow;
case Logs::MySQLError:
case Logs::Error:
return Console::Color::LightRed;
case Logs::MySQLQuery:
case Logs::Debug:
return Console::Color::LightGreen;
case Logs::Quests:
return Console::Color::LightCyan;
case Logs::Commands:
case Logs::Mercenaries:
return Console::Color::LightMagenta;
case Logs::Crash:
return Console::Color::LightRed;
default:
return Console::Color::Yellow;
}
}
/**
* @param log_category
* @return
*/
std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) {
case Logs::Status:
case Logs::Normal:
return LC_YELLOW;
case Logs::MySQLError:
case Logs::Warning:
case Logs::Critical:
case Logs::Error:
return LC_RED;
case Logs::MySQLQuery:
case Logs::Debug:
return LC_GREEN;
case Logs::Quests:
return LC_CYAN;
case Logs::Commands:
case Logs::Mercenaries:
return LC_MAGENTA;
case Logs::Crash:
return LC_RED;
default:
return LC_YELLOW;
}
}
/** /**
* @param log_category * @param log_category
* @return * @return
@@ -187,8 +343,10 @@ void EQEmuLogSys::ProcessLogWrite(
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
{ {
switch (log_category) { switch (log_category) {
case Logs::Status:
case Logs::Normal:
return Chat::Yellow;
case Logs::MySQLError: case Logs::MySQLError:
case Logs::QuestErrors:
case Logs::Error: case Logs::Error:
return Chat::Red; return Chat::Red;
case Logs::MySQLQuery: case Logs::MySQLQuery:
@@ -206,146 +364,30 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
} }
} }
/** /**
* @param debug_level * @param debug_level
* @param log_category * @param log_category
* @param message * @param message
*/ */
void EQEmuLogSys::ProcessConsoleMessage( void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message)
uint16 log_category,
const std::string &message,
const char *file,
const char *func,
int line
)
{ {
bool is_error = ( #ifdef _WINDOWS
log_category == Logs::LogCategory::Error || HANDLE console_handle;
log_category == Logs::LogCategory::MySQLError || console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
log_category == Logs::LogCategory::Crash || CONSOLE_FONT_INFOEX info = { 0 };
log_category == Logs::LogCategory::QuestErrors info.cbSize = sizeof(info);
); info.dwFontSize.Y = 12; // leave X as zero
bool is_warning = ( info.FontWeight = FW_NORMAL;
log_category == Logs::LogCategory::Warning wcscpy(info.FaceName, L"Lucida Console");
); SetCurrentConsoleFontEx(console_handle, NULL, &info);
SetConsoleTextAttribute(console_handle, EQEmuLogSys::GetWindowsConsoleColorFromCategory(log_category));
std::cout << message << "\n";
SetConsoleTextAttribute(console_handle, Console::Color::White);
#else
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
#endif
(!is_error ? std::cout : std::cerr) on_log_console_hook(debug_level, log_category, message);
<< ""
<< rang::fgB::black
<< rang::style::bold
<< fmt::format("{:>6}", GetPlatformName().substr(0, 6))
<< rang::style::reset
<< rang::fgB::gray
<< " | "
<< ((is_error || is_warning) ? rang::fgB::red : rang::fgB::gray)
<< rang::style::bold
<< fmt::format("{:^10}", fmt::format("{}", Logs::LogCategoryName[log_category]).substr(0, 10))
<< rang::style::reset
<< rang::fgB::gray
<< " | "
<< rang::fgB::gray
<< rang::style::bold
<< fmt::format("{}", func)
<< rang::style::reset
<< rang::fgB::gray
<< " ";
if (RuleB(Logging, PrintFileFunctionAndLine)) {
(!is_error ? std::cout : std::cerr)
<< ""
<< rang::fgB::green
<< rang::style::bold
<< fmt::format("{:}", fmt::format("{}:{}:{}", std::filesystem::path(file).filename().string(), func, line))
<< rang::style::reset
<< " | ";
}
if (log_category == Logs::LogCategory::MySQLQuery) {
auto s = Strings::Split(message, "--");
if (s.size() > 1) {
std::string query = Strings::Trim(s[0]);
std::string meta = Strings::Trim(s[1]);
std::cout <<
rang::fgB::green
<<
query
<<
rang::style::reset;
std::cout <<
rang::fgB::black
<<
" -- "
<<
meta
<<
rang::style::reset;
}
}
else if (Strings::Contains(message, "[")) {
for (auto &e: Strings::Split(message, " ")) {
if (Strings::Contains(e, "[") && Strings::Contains(e, "]")) {
e = Strings::Replace(e, "[", "");
e = Strings::Replace(e, "]", "");
bool is_upper = false;
for (int i = 0; i < strlen(e.c_str()); i++) {
if (isupper(e[i])) {
is_upper = true;
}
}
if (!is_upper) {
(!is_error ? std::cout : std::cerr)
<< rang::fgB::gray
<< "["
<< rang::style::bold
<< rang::fgB::yellow
<< e
<< rang::fgB::gray
<< "] "
;
}
else {
(!is_error ? std::cout : std::cerr) << rang::fgB::gray << "[" << e << "] ";
}
}
else {
(!is_error ? std::cout : std::cerr)
<< (is_error ? rang::fgB::red : rang::fgB::gray)
<< e
<< " ";
}
}
}
else {
(!is_error ? std::cout : std::cerr)
<< (is_error ? rang::fgB::red : rang::fgB::gray)
<< message
<< " ";
}
if (!origination_info.zone_short_name.empty()) {
(!is_error ? std::cout : std::cerr)
<<
rang::fgB::black
<<
"-- "
<<
fmt::format(
"[{}] ({}) inst_id [{}]",
origination_info.zone_short_name,
origination_info.zone_long_name,
origination_info.instance_id
);
}
(!is_error ? std::cout : std::cerr) << rang::style::reset << std::endl;
m_on_log_console_hook(log_category, message);
} }
/** /**
@@ -357,6 +399,33 @@ constexpr const char *str_end(const char *str)
return *str ? str_end(str + 1) : str; return *str ? str_end(str + 1) : str;
} }
/**
* @param str
* @return
*/
constexpr bool str_slant(const char *str)
{
return *str == '/' ? true : (*str ? str_slant(str + 1) : false);
}
/**
* @param str
* @return
*/
constexpr const char *r_slant(const char *str)
{
return *str == '/' ? (str + 1) : r_slant(str - 1);
}
/**
* @param str
* @return
*/
constexpr const char *base_file_name(const char *str)
{
return str_slant(str) ? r_slant(str_end(str)) : str;
}
/** /**
* Core logging function * Core logging function
* *
@@ -375,55 +444,47 @@ void EQEmuLogSys::Out(
... ...
) )
{ {
auto l = GetLogsEnabled(debug_level, log_category); bool log_to_console = true;
if (log_settings[log_category].log_to_console < debug_level) {
log_to_console = false;
}
// bail out if nothing to log bool log_to_file = true;
if (!l.log_enabled) { if (log_settings[log_category].log_to_file < debug_level) {
log_to_file = false;
}
bool log_to_gmsay = true;
if (log_settings[log_category].log_to_gmsay < debug_level) {
log_to_gmsay = false;
}
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
if (nothing_to_log) {
return; return;
} }
std::string prefix; std::string prefix;
if (RuleB(Logging, PrintFileFunctionAndLine)) { if (RuleB(Logging, PrintFileFunctionAndLine)) {
prefix = fmt::format("[{0}::{1}:{2}] ", std::filesystem::path(file).filename().string(), func, line); prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
} }
// remove this when we remove all legacy logs
bool ignore_log_legacy_format = (
log_category == Logs::Netcode ||
log_category == Logs::PacketServerClient ||
log_category == Logs::PacketClientServer ||
log_category == Logs::PacketServerToServer
);
// remove this when we remove all legacy logs
std::string output_message = message;
if (!ignore_log_legacy_format) {
va_list args; va_list args;
va_start(args, message); va_start(args, message);
output_message = vStringFormat(message, args); std::string output_message = vStringFormat(message, args);
va_end(args); va_end(args);
}
if (l.log_to_console_enabled) { std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message);
EQEmuLogSys::ProcessConsoleMessage(
log_category, if (log_to_console) {
output_message, EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
file,
func,
line
);
} }
if (l.log_to_gmsay_enabled) { if (log_to_gmsay) {
m_on_log_gmsay_hook(log_category, func, output_message); EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
} }
if (l.log_to_file_enabled) { if (log_to_file) {
EQEmuLogSys::ProcessLogWrite( EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
log_category,
fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message)
);
}
if (l.log_to_discord_enabled && m_on_log_discord_hook) {
m_on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message);
} }
} }
@@ -436,7 +497,7 @@ void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp)
struct tm *time_info; struct tm *time_info;
time(&raw_time); time(&raw_time);
time_info = localtime(&raw_time); time_info = localtime(&raw_time);
strftime(time_stamp, 80, "[%m-%d-%Y %H:%M:%S]", time_info); strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info);
} }
/** /**
@@ -475,45 +536,53 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
/** /**
* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... * When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one...
*/ */
if (!m_file_logs_enabled) { if (!file_logs_enabled) {
return; return;
} }
/** /**
* Zone * Zone
*/ */
if (EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone) { if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
if (!log_name.empty()) { if (!log_name.empty()) {
m_platform_file_name = log_name; platform_file_name = log_name;
} }
if (m_platform_file_name.empty()) { if (platform_file_name.empty()) {
return; return;
} }
LogInfo("Starting File Log [{}/zone/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid()); LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid());
// Make directory if not exists /**
EQEmuLogSys::MakeDirectory(fmt::format("{}/zone", GetLogPath())); * Make directory if not exists
*/
EQEmuLogSys::MakeDirectory("logs/zone");
// Open file pointer /**
* Open file pointer
*/
process_log.open( process_log.open(
fmt::format("{}/zone/{}_{}.log", GetLogPath(), m_platform_file_name, getpid()), StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out std::ios_base::app | std::ios_base::out
); );
} }
else { else {
// All other processes /**
if (m_platform_file_name.empty()) { * All other processes
*/
if (platform_file_name.empty()) {
return; return;
} }
LogInfo("Starting File Log [{}/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid()); LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid());
// Open file pointer /**
* Open file pointer
*/
process_log.open( process_log.open(
fmt::format("{}/{}_{}.log", GetLogPath(), m_platform_file_name.c_str(), getpid()), StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out std::ios_base::app | std::ios_base::out
); );
} }
@@ -528,8 +597,6 @@ void EQEmuLogSys::SilenceConsoleLogging()
log_settings[log_index].log_to_console = 0; log_settings[log_index].log_to_console = 0;
log_settings[log_index].is_category_enabled = 0; log_settings[log_index].is_category_enabled = 0;
} }
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
} }
/** /**
@@ -545,8 +612,6 @@ void EQEmuLogSys::EnableConsoleLogging()
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings() EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
{ {
InjectTablesIfNotExist();
auto categories = LogsysCategoriesRepository::GetWhere( auto categories = LogsysCategoriesRepository::GetWhere(
*m_database, *m_database,
"TRUE ORDER BY log_category_id" "TRUE ORDER BY log_category_id"
@@ -565,17 +630,13 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
log_settings[c.log_category_id].log_to_console = static_cast<uint8>(c.log_to_console); log_settings[c.log_category_id].log_to_console = static_cast<uint8>(c.log_to_console);
log_settings[c.log_category_id].log_to_file = static_cast<uint8>(c.log_to_file); log_settings[c.log_category_id].log_to_file = static_cast<uint8>(c.log_to_file);
log_settings[c.log_category_id].log_to_gmsay = static_cast<uint8>(c.log_to_gmsay); log_settings[c.log_category_id].log_to_gmsay = static_cast<uint8>(c.log_to_gmsay);
log_settings[c.log_category_id].log_to_discord = static_cast<uint8>(c.log_to_discord);
log_settings[c.log_category_id].discord_webhook_id = c.discord_webhook_id;
// Determine if any output method is enabled for the category // Determine if any output method is enabled for the category
// and set it to 1 so it can used to check if category is enabled // and set it to 1 so it can used to check if category is enabled
const bool log_to_console = log_settings[c.log_category_id].log_to_console > 0; const bool log_to_console = log_settings[c.log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[c.log_category_id].log_to_file > 0; const bool log_to_file = log_settings[c.log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[c.log_category_id].log_to_gmsay > 0; const bool log_to_gmsay = log_settings[c.log_category_id].log_to_gmsay > 0;
const bool log_to_discord = log_settings[c.log_category_id].log_to_discord > 0 && const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
log_settings[c.log_category_id].discord_webhook_id > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay || log_to_discord;
if (is_category_enabled) { if (is_category_enabled) {
log_settings[c.log_category_id].is_category_enabled = 1; log_settings[c.log_category_id].is_category_enabled = 1;
@@ -585,7 +646,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
// If we go through this whole loop and nothing is set to any debug level, there // If we go through this whole loop and nothing is set to any debug level, there
// is no point to create a file or keep anything open // is no point to create a file or keep anything open
if (log_settings[c.log_category_id].log_to_file > 0) { if (log_settings[c.log_category_id].log_to_file > 0) {
LogSys.m_file_logs_enabled = true; LogSys.file_logs_enabled = true;
} }
db_categories.emplace_back(c.log_category_id); db_categories.emplace_back(c.log_category_id);
@@ -593,32 +654,18 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
// Auto inject categories that don't exist in the database... // Auto inject categories that don't exist in the database...
for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) { for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) {
if (std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end()) {
bool is_missing_in_database = std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end();
bool is_deprecated_category = Strings::Contains(fmt::format("{}", Logs::LogCategoryName[i]), "Deprecated");
if (!is_missing_in_database && is_deprecated_category) {
LogInfo( LogInfo(
"Logging category [{}] ({}) is now deprecated, deleting from database", "Automatically adding new log category [{0}]",
Logs::LogCategoryName[i], Logs::LogCategoryName[i]
i
);
LogsysCategoriesRepository::DeleteOne(*m_database, i);
}
if (is_missing_in_database && !is_deprecated_category) {
LogInfo(
"Automatically adding new log category [{}] ({})",
Logs::LogCategoryName[i],
i
); );
auto new_category = LogsysCategoriesRepository::NewEntity(); auto new_category = LogsysCategoriesRepository::NewEntity();
new_category.log_category_id = i; new_category.log_category_id = i;
new_category.log_category_description = Strings::Escape(Logs::LogCategoryName[i]); new_category.log_category_description = EscapeString(Logs::LogCategoryName[i]);
new_category.log_to_console = log_settings[i].log_to_console; new_category.log_to_console = log_settings[i].log_to_console;
new_category.log_to_gmsay = log_settings[i].log_to_gmsay; new_category.log_to_gmsay = log_settings[i].log_to_gmsay;
new_category.log_to_file = log_settings[i].log_to_file; new_category.log_to_file = log_settings[i].log_to_file;
new_category.log_to_discord = log_settings[i].log_to_discord;
LogsysCategoriesRepository::InsertOne(*m_database, new_category); LogsysCategoriesRepository::InsertOne(*m_database, new_category);
} }
@@ -626,19 +673,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
LogInfo("Loaded [{}] log categories", categories.size()); LogInfo("Loaded [{}] log categories", categories.size());
auto webhooks = DiscordWebhooksRepository::GetWhere(*m_database, fmt::format("id < {}", MAX_DISCORD_WEBHOOK_ID));
if (!webhooks.empty()) {
for (auto &w: webhooks) {
m_discord_webhooks[w.id] = {w.id, w.webhook_name, w.webhook_url};
}
LogInfo("Loaded [{}] Discord webhooks", webhooks.size());
}
// force override this setting
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_file = static_cast<uint8>(Logs::General);
return this; return this;
} }
@@ -648,97 +682,3 @@ EQEmuLogSys *EQEmuLogSys::SetDatabase(Database *db)
return this; return this;
} }
void EQEmuLogSys::InjectTablesIfNotExist()
{
// do not run injections for zone as its unnecessary hits every time a zone boots
// other processes less frequently ran can pick up injection
if (m_log_platform == EQEmuExePlatform::ExePlatformZone) {
return;
}
// inject discord_webhooks
if (!m_database->DoesTableExist("discord_webhooks")) {
LogInfo("Creating table [discord_webhooks]");
m_database->QueryDatabase(
SQL(
CREATE TABLE discord_webhooks
(
id INT auto_increment primary key NULL,
webhook_name varchar(100) NULL,
webhook_url varchar(255) NULL,
created_at DATETIME NULL,
deleted_at DATETIME NULL
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;
)
);
}
// inject logsys_categories
if (!m_database->DoesTableExist("logsys_categories")) {
LogInfo("Creating table [logsys_categories]");
m_database->QueryDatabase(
SQL(
CREATE TABLE `logsys_categories` (
`log_category_id` int(11) NOT NULL,
`log_category_description` varchar(150) DEFAULT NULL,
`log_to_console` smallint(11) DEFAULT 0,
`log_to_file` smallint(11) DEFAULT 0,
`log_to_gmsay` smallint(11) DEFAULT 0,
`log_to_discord` smallint(11) DEFAULT 0,
`discord_webhook_id` int(11) DEFAULT 0,
PRIMARY KEY (`log_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
)
);
}
}
const EQEmuLogSys::DiscordWebhooks *EQEmuLogSys::GetDiscordWebhooks() const
{
return m_discord_webhooks;
}
EQEmuLogSys::LogEnabled EQEmuLogSys::GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
auto e = LogEnabled{};
e.log_to_console_enabled = log_settings[log_category].log_to_console > 0 &&
log_settings[log_category].log_to_console >= debug_level;
e.log_to_file_enabled = log_settings[log_category].log_to_file > 0 &&
log_settings[log_category].log_to_file >= debug_level;
e.log_to_gmsay_enabled = log_settings[log_category].log_to_gmsay > 0 &&
log_settings[log_category].log_to_gmsay >= debug_level &&
log_category != Logs::LogCategory::Netcode &&
(EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld);
e.log_to_discord_enabled = EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone &&
log_settings[log_category].log_to_discord > 0 &&
log_settings[log_category].log_to_discord >= debug_level &&
log_settings[log_category].discord_webhook_id > 0 &&
log_settings[log_category].discord_webhook_id < MAX_DISCORD_WEBHOOK_ID;
e.log_enabled =
e.log_to_console_enabled || e.log_to_file_enabled || e.log_to_gmsay_enabled || e.log_to_discord_enabled;
return e;
}
bool EQEmuLogSys::IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
return GetLogsEnabled(debug_level, log_category).log_enabled;
}
const std::string &EQEmuLogSys::GetLogPath() const
{
return m_log_path;
}
EQEmuLogSys *EQEmuLogSys::SetLogPath(const std::string &log_path)
{
EQEmuLogSys::m_log_path = log_path;
return this;
}
+61 -120
View File
@@ -39,7 +39,8 @@
namespace Logs { namespace Logs {
enum DebugLevel { enum DebugLevel {
General = 1, // 1 - Low-Level general debugging, useful info on single line General = 1, // 1 - Low-Level general debugging, useful info on single line
Detail // 2 - Use this for very chatty logging you want to leave in but don't want on by default Moderate, // 2 - Informational based, used in functions, when particular things load
Detail // 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication
}; };
/** /**
@@ -53,7 +54,7 @@ namespace Logs {
AI, AI,
Aggro, Aggro,
Attack, Attack,
DeprecatedCS, // deprecated PacketClientServer,
Combat, Combat,
Commands, Commands,
Crash, Crash,
@@ -64,36 +65,36 @@ namespace Logs {
Inventory, Inventory,
Launcher, Launcher,
Netcode, Netcode,
Normal, // deprecated Normal,
Object, Object,
Pathing, Pathing,
QSServer, // deprecated QSServer,
Quests, Quests,
Rules, Rules,
Skills, Skills,
Spawns, Spawns,
Spells, Spells,
Status, // deprecated Status,
TCPConnection, TCPConnection,
Tasks, Tasks,
Tradeskills, Tradeskills,
Trading, Trading,
Tribute, Tribute,
UCSServer, // deprecated UCSServer,
WebInterfaceServer, // deprecated WebInterfaceServer,
WorldServer, // deprecated WorldServer,
ZoneServer, // deprecated ZoneServer,
MySQLError, MySQLError,
MySQLQuery, MySQLQuery,
Mercenaries, Mercenaries,
QuestDebug, QuestDebug,
DeprecatedSC, // deprecated PacketServerClient,
DeprecatedCSU, // deprecated PacketClientServerUnhandled,
DeprecatedSCD, // deprecated PacketServerClientWithDump,
DeprecatedCSD, // deprecated PacketClientServerWithDump,
Loginserver, // deprecated Loginserver,
ClientLogin, ClientLogin,
HeadlessClient, // deprecated HeadlessClient,
HPUpdate, HPUpdate,
FixZ, FixZ,
Food, Food,
@@ -103,10 +104,10 @@ namespace Logs {
MobAppearance, MobAppearance,
Info, Info,
Warning, Warning,
Critical, // deprecated Critical,
Emergency, // deprecated Emergency,
Alert, // deprecated Alert,
Notice, // deprecated Notice,
AIScanClose, AIScanClose,
AIYellForHelp, AIYellForHelp,
AICastBeneficialClose, AICastBeneficialClose,
@@ -126,16 +127,6 @@ namespace Logs {
DiaWind, DiaWind,
HTTP, HTTP,
Saylink, Saylink,
ChecksumVerification,
CombatRecord,
Hate,
Discord,
Faction,
PacketServerClient,
PacketClientServer,
PacketServerToServer,
Bugs,
QuestErrors,
MaxCategoryID /* Don't Remove this */ MaxCategoryID /* Don't Remove this */
}; };
@@ -148,7 +139,7 @@ namespace Logs {
"AI", "AI",
"Aggro", "Aggro",
"Attack", "Attack",
"Deprecated", "Packet :: Client -> Server",
"Combat", "Combat",
"Commands", "Commands",
"Crash", "Crash",
@@ -159,36 +150,36 @@ namespace Logs {
"Inventory", "Inventory",
"Launcher", "Launcher",
"Netcode", "Netcode",
"Normal (Deprecated)", "Normal",
"Object", "Object",
"Pathing", "Pathing",
"QS Server (Deprecated)", "QS Server",
"Quests", "Quests",
"Rules", "Rules",
"Skills", "Skills",
"Spawns", "Spawns",
"Spells", "Spells",
"Status (Deprecated)", "Status",
"TCP Connection", "TCP Connection",
"Tasks", "Tasks",
"Tradeskills", "Tradeskills",
"Trading", "Trading",
"Tribute", "Tribute",
"UCS Server (Deprecated)", "UCS Server",
"Web Interface (Deprecated)", "WebInterface Server",
"World Server (Deprecated)", "World Server",
"Zone Server (Deprecated)", "Zone Server",
"QueryErr", "MySQL Error",
"Query", "MySQL Query",
"Mercenaries", "Mercenaries",
"Quest Debug", "Quest Debug",
"Legacy Packet Logging (Deprecated)", "Packet :: Server -> Client",
"Legacy Packet Logging (Deprecated)", "Packet :: Client -> Server Unhandled",
"Legacy Packet Logging (Deprecated)", "Packet :: Server -> Client (Dump)",
"Legacy Packet Logging (Deprecated)", "Packet :: Client -> Server (Dump)",
"Login Server (Deprecated)", "Login Server",
"Client Login", "Client Login",
"Headless Client (Deprecated)", "Headless Client",
"HP Update", "HP Update",
"FixZ", "FixZ",
"Food", "Food",
@@ -198,13 +189,13 @@ namespace Logs {
"Mob Appearance", "Mob Appearance",
"Info", "Info",
"Warning", "Warning",
"Critical (Deprecated)", "Critical",
"Emergency (Deprecated)", "Emergency",
"Alert (Deprecated)", "Alert",
"Notice (Deprecated)", "Notice",
"AI Scan", "AI Scan Close",
"AI Yell", "AI Yell For Help",
"AI CastBeneficial", "AI Cast Beneficial Close",
"AOE Cast", "AOE Cast",
"Entity Management", "Entity Management",
"Flee", "Flee",
@@ -221,16 +212,6 @@ namespace Logs {
"DialogueWindow", "DialogueWindow",
"HTTP", "HTTP",
"Saylink", "Saylink",
"ChecksumVer",
"CombatRecord",
"Hate",
"Discord",
"Faction",
"Packet S->C",
"Packet C->S",
"Packet S->S",
"Bugs",
"QuestErrors"
}; };
} }
@@ -238,8 +219,6 @@ namespace Logs {
class Database; class Database;
constexpr uint16 MAX_DISCORD_WEBHOOK_ID = 300;
class EQEmuLogSys { class EQEmuLogSys {
public: public:
EQEmuLogSys(); EQEmuLogSys();
@@ -302,19 +281,9 @@ public:
uint8 log_to_file; uint8 log_to_file;
uint8 log_to_console; uint8 log_to_console;
uint8 log_to_gmsay; uint8 log_to_gmsay;
uint8 log_to_discord;
int discord_webhook_id;
uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */ uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */
}; };
struct OriginationInfo {
std::string zone_short_name;
std::string zone_long_name;
int instance_id;
};
OriginationInfo origination_info{};
/** /**
* Internally used memory reference for all log settings per category * Internally used memory reference for all log settings per category
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults * These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
@@ -322,78 +291,50 @@ public:
*/ */
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{}; LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
struct LogEnabled { bool file_logs_enabled = false;
bool log_to_file_enabled;
bool log_to_console_enabled;
bool log_to_gmsay_enabled;
bool log_to_discord_enabled;
bool log_enabled;
};
LogEnabled GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category); int log_platform = 0;
bool IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category); std::string platform_file_name;
struct DiscordWebhooks {
int id;
std::string webhook_name;
std::string webhook_url;
};
const DiscordWebhooks *GetDiscordWebhooks() const;
// gmsay // gmsay
uint16 GetGMSayColorFromCategory(uint16 log_category); uint16 GetGMSayColorFromCategory(uint16 log_category);
EQEmuLogSys *SetGMSayHandler(const std::function<void(uint16 log_type, const char *func, const std::string &)>& f) EQEmuLogSys * SetGMSayHandler(std::function<void(uint16 log_type, const std::string &)> f) {
{ on_log_gmsay_hook = f;
m_on_log_gmsay_hook = f;
return this;
}
EQEmuLogSys *SetDiscordHandler(std::function<void(uint16 log_category, int webhook_id, const std::string &)> f)
{
m_on_log_discord_hook = f;
return this; return this;
} }
// console // console
void SetConsoleHandler( void SetConsoleHandler(
std::function<void( std::function<void(
uint16 debug_level,
uint16 log_type, uint16 log_type,
const std::string & const std::string &
)> f )> f
) { m_on_log_console_hook = f; } ) { on_log_console_hook = f; }
void SilenceConsoleLogging(); void SilenceConsoleLogging();
void EnableConsoleLogging(); void EnableConsoleLogging();
// database // database
EQEmuLogSys *SetDatabase(Database *db); EQEmuLogSys *SetDatabase(Database *db);
[[nodiscard]] const std::string &GetLogPath() const;
EQEmuLogSys * SetLogPath(const std::string &log_path);
private: private:
// reference to database // reference to database
Database *m_database; Database *m_database;
std::function<void(uint16 log_category, const char *func, const std::string &)> m_on_log_gmsay_hook;
std::function<void(uint16 log_category, int webhook_id, const std::string &)> m_on_log_discord_hook;
std::function<void(uint16 log_category, const std::string &)> m_on_log_console_hook;
DiscordWebhooks m_discord_webhooks[MAX_DISCORD_WEBHOOK_ID]{};
bool m_file_logs_enabled = false;
int m_log_platform = 0;
std::string m_platform_file_name;
std::string m_log_path;
void ProcessConsoleMessage( std::function<void(uint16 log_category, const std::string &)> on_log_gmsay_hook;
uint16 log_category, std::function<void(uint16 debug_level, uint16 log_category, const std::string &)> on_log_console_hook;
const std::string &message,
const char *file, std::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
const char *func, std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
int line uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
);
void ProcessLogWrite(uint16 log_category, const std::string &message); void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message);
void InjectTablesIfNotExist(); void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
bool IsRfc5424LogCategory(uint16 log_category);
}; };
extern EQEmuLogSys LogSys; extern EQEmuLogSys LogSys;
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,14 +1,14 @@
#pragma once #pragma once
#include <any>
#include <functional> #include <functional>
#include <exception> #include <exception>
#include "event_loop.h" #include "event_loop.h"
#include "../any.h"
namespace EQ { namespace EQ {
class Task class Task
{ {
public: public:
typedef std::function<void(const std::any&)> ResolveFn; typedef std::function<void(const EQ::Any&)> ResolveFn;
typedef std::function<void(const std::exception&)> RejectFn; typedef std::function<void(const std::exception&)> RejectFn;
typedef std::function<void()> FinallyFn; typedef std::function<void()> FinallyFn;
typedef std::function<void(ResolveFn, RejectFn)> TaskFn; typedef std::function<void(ResolveFn, RejectFn)> TaskFn;
@@ -19,7 +19,7 @@ namespace EQ {
RejectFn on_catch; RejectFn on_catch;
FinallyFn on_finally; FinallyFn on_finally;
bool has_result; bool has_result;
std::any result; EQ::Any result;
bool has_error; bool has_error;
std::exception error; std::exception error;
}; };
@@ -63,7 +63,7 @@ namespace EQ {
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) { uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
TaskBaton *baton = (TaskBaton*)req->data; TaskBaton *baton = (TaskBaton*)req->data;
baton->fn([baton](const std::any& result) { baton->fn([baton](const EQ::Any& result) {
baton->has_error = false; baton->has_error = false;
baton->has_result = true; baton->has_result = true;
baton->result = result; baton->result = result;
+2 -2
View File
@@ -60,8 +60,8 @@ namespace EQ
} }
template<typename Fn, typename... Args> template<typename Fn, typename... Args>
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::invoke_result<Fn, Args...>::type> { auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
using return_type = typename std::invoke_result<Fn, Args...>::type; using return_type = typename std::result_of<Fn(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>( auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...) std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
+1 -1
View File
@@ -19,7 +19,7 @@
*/ */
#include "expedition_lockout_timer.h" #include "expedition_lockout_timer.h"
#include "../common/strings.h" #include "../common/string_util.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/util/uuid.h" #include "../common/util/uuid.h"
#include <fmt/format.h> #include <fmt/format.h>
+24 -24
View File
@@ -20,31 +20,31 @@
#include "races.h" #include "races.h"
#include "rulesys.h" #include "rulesys.h"
const char *FactionValueToString(FACTION_VALUE faction_value) const char *FactionValueToString(FACTION_VALUE fv)
{ {
switch (faction_value) { switch (fv) {
case FACTION_ALLY: case FACTION_ALLY:
return "Ally"; return ("Ally");
case FACTION_WARMLY: case FACTION_WARMLY:
return "Warmly"; return ("Warmly");
case FACTION_KINDLY: case FACTION_KINDLY:
return "Kindly"; return ("Kindly");
case FACTION_AMIABLY: case FACTION_AMIABLE:
return "Amiably"; return ("Amiable");
case FACTION_INDIFFERENTLY: case FACTION_INDIFFERENT:
return "Indifferently"; return ("Indifferent");
case FACTION_APPREHENSIVELY: case FACTION_APPREHENSIVE:
return "Apprehensively"; return ("Apprehensive");
case FACTION_DUBIOUSLY: case FACTION_DUBIOUS:
return "Dubiously"; return ("Dubious");
case FACTION_THREATENINGLY: case FACTION_THREATENLY:
return "Threateningly"; return ("Threatenly");
case FACTION_SCOWLS: case FACTION_SCOWLS:
return "Scowls"; return ("Scowls, ready to attack.");
default: default:
break; break;
} }
return "Unknown"; return ("Unknown Faction Con");
} }
@@ -70,19 +70,19 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
return FACTION_KINDLY; return FACTION_KINDLY;
} }
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) { if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) {
return FACTION_AMIABLY; return FACTION_AMIABLE;
} }
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) { if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) {
return FACTION_INDIFFERENTLY; return FACTION_INDIFFERENT;
} }
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) { if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) {
return FACTION_APPREHENSIVELY; return FACTION_APPREHENSIVE;
} }
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) { if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) {
return FACTION_DUBIOUSLY; return FACTION_DUBIOUS;
} }
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) { if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) {
return FACTION_THREATENINGLY; return FACTION_THREATENLY;
} }
return FACTION_SCOWLS; return FACTION_SCOWLS;
} }
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
// TODO: add more values // TODO: add more values
switch (r1) { switch (r1) {
case DARK_ELF: case DARK_ELF:
if (r2 == RACE_NERIAK_CITIZEN_77) { if (r2 == 77) {
return true; return true;
} }
break; break;
case BARBARIAN: case BARBARIAN:
if (r2 == RACE_HALAS_CITIZEN_90) { if (r2 == 90) {
return true; return true;
} }
} }
+6 -23
View File
@@ -27,13 +27,13 @@ enum FACTION_VALUE {
FACTION_ALLY = 1, FACTION_ALLY = 1,
FACTION_WARMLY = 2, FACTION_WARMLY = 2,
FACTION_KINDLY = 3, FACTION_KINDLY = 3,
FACTION_AMIABLY = 4, FACTION_AMIABLE = 4,
FACTION_INDIFFERENTLY = 5, FACTION_INDIFFERENT = 5,
FACTION_APPREHENSIVELY = 6, FACTION_APPREHENSIVE = 6,
FACTION_DUBIOUSLY = 7, FACTION_DUBIOUS = 7,
FACTION_THREATENINGLY = 8, FACTION_THREATENLY = 8,
FACTION_SCOWLS = 9 FACTION_SCOWLS = 9
}; };
@@ -75,23 +75,6 @@ struct NPCFaction
uint8 temp; uint8 temp;
}; };
// Faction Associations give a much more live like faction system const char *FactionValueToString(FACTION_VALUE fv);
// Basically the primary faction and magnitude of a faction hit will generate the rest of them
// Largest faction I could find quickly was Lord Inquisitor Seru with 9 total hits (8 associations) so 8 + 2 for max for now
#define MAX_FACTION_ASSOC 10
// this is the ID of a faction association and it's multiplier
struct FactionAssociationHit {
int id;
float multiplier;
};
struct FactionAssociations {
// maybe there should be more data here, fine for now
FactionAssociationHit hits[MAX_FACTION_ASSOC];
};
const char *FactionValueToString(FACTION_VALUE faction_value);
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value); FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
#endif #endif
+1 -1
View File
@@ -204,7 +204,7 @@ enum { //some random constants
#define MIN_LEVEL_ALCHEMY 25 #define MIN_LEVEL_ALCHEMY 25
//chance ratio that a //chance ratio that a
#define THREATENINGLY_AGGRO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly #define THREATENLY_ARRGO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
//max factions per npc faction list //max factions per npc faction list
#define MAX_NPC_FACTIONS 20 #define MAX_NPC_FACTIONS 20
+17 -32
View File
@@ -19,7 +19,7 @@
*/ */
#include <fstream> #include <fstream>
#include "file.h" #include "file_util.h"
#ifdef _WINDOWS #ifdef _WINDOWS
#include <direct.h> #include <direct.h>
@@ -35,48 +35,33 @@
#endif #endif
#include <fmt/format.h>
#include <filesystem>
namespace fs = std::filesystem;
/** /**
* @param name * @param name
* @return * @return
*/ */
bool File::Exists(const std::string &name) bool FileUtil::exists(const std::string &name)
{ {
return fs::exists(fs::path{name}); std::ifstream f(name.c_str());
return f.good();
} }
/** /**
* @param directory_name * @param directory_name
*/ */
void File::Makedir(const std::string &directory_name) void FileUtil::mkdir(const std::string& directory_name)
{ {
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
}
std::string File::FindEqemuConfigPath() #ifdef _WINDOWS
{ struct _stat st;
if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) { if (_stat(directory_name.c_str(), &st) == 0) // exists
return File::GetCwd(); return;
_mkdir(directory_name.c_str());
#else
struct stat st{};
if (stat(directory_name.c_str(), &st) == 0) { // exists
return;
} }
else if (File::Exists(fs::path{File::GetCwd() + "/../eqemu_config.json"}.string())) { ::mkdir(directory_name.c_str(), 0755);
return canonical(fs::path{File::GetCwd() + "/../"}).string(); #endif
}
else if (File::Exists(fs::path{File::GetCwd() + "/login.json"}.string())) {
return File::GetCwd();
}
else if (File::Exists(fs::path{File::GetCwd() + "/../login.json"}.string())) {
return canonical(fs::path{File::GetCwd() + "/../"}).string();
}
return {};
}
std::string File::GetCwd()
{
return fs::current_path().string();
} }
+6 -12
View File
@@ -18,21 +18,15 @@
* *
*/ */
#ifndef EQEMU_FILE_H #ifndef EQEMU_FILE_UTIL_H
#define EQEMU_FILE_H #define EQEMU_FILE_UTIL_H
#include <filesystem>
namespace fs = std::filesystem; class FileUtil {
class File {
public: public:
static bool Exists(const std::string &name); static bool exists(const std::string &name);
static void Makedir(const std::string& directory_name); static void mkdir(const std::string& directory_name);
static std::string FindEqemuConfigPath();
static std::string GetCwd();
}; };
bool Exists(const std::string& name);
#endif //EQEMU_FILE_H #endif //EQEMU_FILE_UTIL_H
+22 -70
View File
@@ -20,7 +20,7 @@
#include "database.h" #include "database.h"
//#include "misc_functions.h" //#include "misc_functions.h"
#include "strings.h" #include "string_util.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@@ -63,9 +63,7 @@ bool BaseGuildManager::LoadGuilds() {
for (auto row=results.begin();row!=results.end();++row) for (auto row=results.begin();row!=results.end();++row)
_CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]); _CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]);
LogInfo("Loaded [{}] Guilds", Strings::Commify(std::to_string(results.RowCount()))); query = "SELECT guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
results = m_db->QueryDatabase(query); results = m_db->QueryDatabase(query);
if (!results.Success()) if (!results.Success())
@@ -133,7 +131,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
info = _CreateGuild(guild_id, row[0], atoi(row[1]), atoi(row[2]), row[3], row[4], row[5], row[6]); info = _CreateGuild(guild_id, row[0], atoi(row[1]), atoi(row[2]), row[3], row[4], row[5], row[6]);
query = StringFormat("SELECT guild_id, `rank`, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace " query = StringFormat("SELECT guild_id, rank, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
"FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id); "FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id);
results = m_db->QueryDatabase(query); results = m_db->QueryDatabase(query);
@@ -270,7 +268,7 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length()); m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length());
query = StringFormat("INSERT INTO guild_ranks " query = StringFormat("INSERT INTO guild_ranks "
"(guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)" "(guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)"
" VALUES(%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d)", " VALUES(%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d)",
guild_id, rank, title_esc, guild_id, rank, title_esc,
rankInfo.permissions[GUILD_HEAR], rankInfo.permissions[GUILD_HEAR],
@@ -740,7 +738,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
std::string query; std::string query;
if(guild_id != GUILD_NONE) { if(guild_id != GUILD_NONE) {
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,`rank`,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank); query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
auto results = m_db->QueryDatabase(query); auto results = m_db->QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
@@ -760,7 +758,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
} }
bool BaseGuildManager::DBSetGuildRank(uint32 charid, uint8 rank) { bool BaseGuildManager::DBSetGuildRank(uint32 charid, uint8 rank) {
std::string query = StringFormat("UPDATE guild_members SET `rank`=%d WHERE char_id=%d", rank, charid); std::string query = StringFormat("UPDATE guild_members SET rank=%d WHERE char_id=%d", rank, charid);
return(QueryWithLogging(query, "setting a guild member's rank")); return(QueryWithLogging(query, "setting a guild member's rank"));
} }
@@ -866,11 +864,20 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
return(true); return(true);
} }
//factored out so I dont have to copy this crap.
#ifdef BOTS
#define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt`" \
" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` "
#else
#define GuildMemberBaseQuery \ #define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \ "SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \ " g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt` " \ " g.`banker`, g.`public_note`, g.`alt` " \
" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` " " FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` "
#endif
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) { static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
//fields from `characer_` //fields from `characer_`
into.char_id = atoi(row[0]); into.char_id = atoi(row[0]);
@@ -960,7 +967,12 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
} }
//load up the rank info for each guild. //load up the rank info for each guild.
std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id); std::string query;
#ifdef BOTS
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C' AND c.deleted_at IS NULL", char_id);
#else
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id);
#endif
auto results = m_db->QueryDatabase(query); auto results = m_db->QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return false; return false;
@@ -1196,7 +1208,7 @@ BaseGuildManager::RankInfo::RankInfo() {
BaseGuildManager::GuildInfo::GuildInfo() { BaseGuildManager::GuildInfo::GuildInfo() {
leader_char_id = 0; leader_char_id = 0;
minstatus = AccountStatus::Player; minstatus = 0;
} }
uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID) uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
@@ -1213,66 +1225,6 @@ uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
return results.RowCount(); return results.RowCount();
} }
std::string BaseGuildManager::GetGuildNameByID(uint32 guild_id) const {
if(guild_id == GUILD_NONE) {
return std::string();
}
std::map<uint32, GuildInfo *>::const_iterator res;
res = m_guilds.find(guild_id);
if(res == m_guilds.end()) {
return "Invalid Guild";
}
return res->second->name;
}
std::string BaseGuildManager::GetGuildRankName(uint32 guild_id, uint8 rank) const
{
if(rank > GUILD_MAX_RANK) {
return "Invalid Rank";
}
std::map<uint32, GuildInfo *>::const_iterator res;
res = m_guilds.find(guild_id);
if(res == m_guilds.end()) {
return "Invalid Guild Rank";
}
return res->second->ranks[rank].name;
}
uint32 BaseGuildManager::GetGuildIDByCharacterID(uint32 character_id)
{
if(!m_db) {
return GUILD_NONE;
}
std::string query = fmt::format(
"SELECT `guild_id` FROM `guild_members` WHERE char_id = {} LIMIT 1",
character_id
);
auto results = m_db->QueryDatabase(query);
if(!results.Success() || !results.RowCount()) {
return GUILD_NONE;
}
auto row = results.begin();
auto guild_id = std::stoul(row[0]);
return guild_id;
}
bool BaseGuildManager::IsCharacterInGuild(uint32 character_id, uint32 guild_id)
{
auto current_guild_id = GetGuildIDByCharacterID(character_id);
if (current_guild_id == GUILD_NONE) {
return false;
}
if (guild_id && current_guild_id != guild_id) {
return false;
}
return true;
}
-4
View File
@@ -76,12 +76,8 @@ class BaseGuildManager
bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const; bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const;
const char *GetRankName(uint32 guild_id, uint8 rank) const; const char *GetRankName(uint32 guild_id, uint8 rank) const;
const char *GetGuildName(uint32 guild_id) const; const char *GetGuildName(uint32 guild_id) const;
std::string GetGuildNameByID(uint32 guild_id) const;
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
bool GetGuildNameByID(uint32 guild_id, std::string &into) const; bool GetGuildNameByID(uint32 guild_id, std::string &into) const;
uint32 GetGuildIDByName(const char *GuildName); uint32 GetGuildIDByName(const char *GuildName);
uint32 GetGuildIDByCharacterID(uint32 character_id);
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const; bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const; uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
bool CheckGMStatus(uint32 guild_id, uint8 status) const; bool CheckGMStatus(uint32 guild_id, uint8 status) const;
+1298 -2021
View File
File diff suppressed because it is too large Load Diff
+2 -78
View File
@@ -25,7 +25,7 @@
//#include "races.h" //#include "races.h"
//#include "rulesys.h" //#include "rulesys.h"
//#include "shareddb.h" //#include "shareddb.h"
#include "strings.h" #include "string_util.h"
#include "../common/light_source.h" #include "../common/light_source.h"
@@ -399,7 +399,7 @@ bool EQ::InventoryProfile::SwapItem(
} }
// Remove item from inventory (with memory delete) // Remove item from inventory (with memory delete)
bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) { bool EQ::InventoryProfile::DeleteItem(int16 slot_id, uint8 quantity) {
// Pop item out of inventory map (or queue) // Pop item out of inventory map (or queue)
ItemInstance *item_to_delete = PopItem(slot_id); ItemInstance *item_to_delete = PopItem(slot_id);
@@ -590,68 +590,6 @@ bool EQ::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quan
// Checks that user has at least 'quantity' number of items in a given inventory slot // Checks that user has at least 'quantity' number of items in a given inventory slot
// Returns first slot it was found in, or SLOT_INVALID if not found // Returns first slot it was found in, or SLOT_INVALID if not found
bool EQ::InventoryProfile::HasAugmentEquippedByID(uint32 item_id)
{
bool has_equipped = false;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->ContainsAugmentByID(item_id)) {
has_equipped = true;
break;
}
}
return has_equipped;
}
int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id)
{
int quantity = 0;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->ContainsAugmentByID(item_id)) {
quantity += item->CountAugmentByID(item_id);
}
}
return quantity;
}
bool EQ::InventoryProfile::HasItemEquippedByID(uint32 item_id)
{
bool has_equipped = false;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->GetID() == item_id) {
has_equipped = true;
break;
}
}
return has_equipped;
}
int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id)
{
int quantity = 0;
ItemInstance* item = nullptr;
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
item = GetItem(slot_id);
if (item && item->GetID() == item_id) {
quantity += item->IsStackable() ? item->GetCharges() : 1;
}
}
return quantity;
}
//This function has a flaw in that it only returns the last stack that it looked at //This function has a flaw in that it only returns the last stack that it looked at
//when quantity is greater than 1 and not all of quantity can be found in 1 stack. //when quantity is greater than 1 and not all of quantity can be found in 1 stack.
int16 EQ::InventoryProfile::HasItem(uint32 item_id, uint8 quantity, uint8 where) int16 EQ::InventoryProfile::HasItem(uint32 item_id, uint8 quantity, uint8 where)
@@ -1718,17 +1656,3 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 lo
return EQ::invslot::SLOT_INVALID; return EQ::invslot::SLOT_INVALID;
} }
std::vector<uint32> EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id)
{
std::vector<uint32> augments;
const auto* item = GetItem(slot_id);
if (item) {
for (uint8 i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
augments.push_back(item->GetAugment(i) ? item->GetAugmentItemID(i) : 0);
}
}
return augments;
}
+3 -21
View File
@@ -26,11 +26,8 @@
#include "item_instance.h" #include "item_instance.h"
#include "classes.h"
#include "races.h"
#include <list> #include <list>
#include <vector>
//FatherNitwit: location bits for searching specific //FatherNitwit: location bits for searching specific
@@ -132,10 +129,10 @@ namespace EQ
// Swap items in inventory // Swap items in inventory
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel }; enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = RACE_DOUG_0, uint8 class_id = NO_CLASS, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0); bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0);
// Remove item from inventory // Remove item from inventory
bool DeleteItem(int16 slot_id, int16 quantity = 0); bool DeleteItem(int16 slot_id, uint8 quantity = 0);
// Checks All items in a bag for No Drop // Checks All items in a bag for No Drop
bool CheckNoDrop(int16 slot_id, bool recurse = true); bool CheckNoDrop(int16 slot_id, bool recurse = true);
@@ -143,21 +140,6 @@ namespace EQ
// Remove item from inventory (and take control of memory) // Remove item from inventory (and take control of memory)
ItemInstance* PopItem(int16 slot_id); ItemInstance* PopItem(int16 slot_id);
// Check if player has a specific item equipped by Item ID
bool HasItemEquippedByID(uint32 item_id);
// Check how many of a specific item the player has equipped by Item ID
int CountItemEquippedByID(uint32 item_id);
// Check if player has a specific augment equipped by Item ID
bool HasAugmentEquippedByID(uint32 item_id);
// Check how many of a specific augment the player has equipped by Item ID
int CountAugmentEquippedByID(uint32 item_id);
// Get a list of augments from a specific slot ID
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
// Check whether there is space for the specified number of the specified item. // Check whether there is space for the specified number of the specified item.
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity); bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
@@ -208,7 +190,7 @@ namespace EQ
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value);
void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value);
std::string GetCustomItemData(int16 slot_id, std::string identifier); std::string GetCustomItemData(int16 slot_id, std::string identifier);
static const int GetItemStatValue(uint32 item_id, std::string identifier); static int GetItemStatValue(uint32 item_id, const char* identifier);
protected: protected:
/////////////////////////////// ///////////////////////////////
// Protected Methods // Protected Methods
+1 -1
View File
@@ -19,7 +19,7 @@
#include "inventory_slot.h" #include "inventory_slot.h"
#include "textures.h" #include "textures.h"
#include "strings.h" #include "string_util.h"
int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index) int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index)
-155
View File
@@ -18,17 +18,7 @@
* *
*/ */
#include <cstring>
#include <fmt/format.h>
#include <csignal>
#include <vector>
#include "ip_util.h" #include "ip_util.h"
#include "http/httplib.h"
#include "http/uri.h"
#include "eqemu_logsys.h"
#include "event/event_loop.h"
#include "net/dns.h"
#include "event/task_scheduler.h"
/** /**
* @param ip * @param ip
@@ -80,148 +70,3 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0") IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0")
); );
} }
/**
* Gets local address - pings google to inspect what interface was used locally
* @return
*/
std::string IpUtil::GetLocalIPAddress()
{
char my_ip_address[16];
unsigned int my_port;
struct sockaddr_in server_address{};
struct sockaddr_in my_address{};
int sockfd;
// Connect to server
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return "";
}
// Set server_addr
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("172.217.160.99");
server_address.sin_port = htons(80);
// Connect to server
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
close(sockfd);
return "";
}
// Get my ip address and port
memset(&my_address, 0, sizeof(my_address));
socklen_t len = sizeof(my_address);
getsockname(sockfd, (struct sockaddr *) &my_address, &len);
inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address));
my_port = ntohs(my_address.sin_port);
return fmt::format("{}", my_ip_address);
}
/**
* Gets public address
* Uses various websites as options to return raw public IP back to the client
* @return
*/
std::string IpUtil::GetPublicIPAddress()
{
std::vector<std::string> endpoints = {
"http://ifconfig.me",
"http://api.ipify.org",
"http://ipinfo.io/ip",
"http://ipecho.net/plain",
};
for (auto &s: endpoints) {
// http get request
uri u(s);
httplib::Client r(
fmt::format(
"{}://{}",
u.get_scheme(),
u.get_host()
).c_str()
);
httplib::Headers headers = {
{"Content-type", "text/plain; charset=utf-8"},
{"User-Agent", "curl/7.81.0"}
};
r.set_connection_timeout(1, 0);
r.set_read_timeout(1, 0);
r.set_write_timeout(1, 0);
if (auto res = r.Get(fmt::format("/{}", u.get_path()).c_str(), headers)) {
if (res->status == 200) {
if (res->body.find('.') != std::string::npos) {
return res->body;
}
}
}
}
return {};
}
std::string IpUtil::DNSLookupSync(const std::string &addr, int port)
{
auto task_runner = new EQ::Event::TaskScheduler();
auto res = task_runner->Enqueue(
[&]() -> std::string {
bool running = true;
std::string ret;
EQ::Net::DNSLookup(
addr, port, false, [&](const std::string &addr) {
ret = addr;
if (addr.empty()) {
ret = "";
running = false;
}
return ret;
}
);
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
auto &loop = EQ::EventLoop::Get();
while (running) {
if (!ret.empty()) {
running = false;
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() > 1500) {
LogInfo(
"Deadline exceeded [{}]",
1500
);
running = false;
}
loop.Process();
}
return ret;
}
);
std::string result = res.get();
safe_delete(task_runner);
return result;
}
bool IpUtil::IsIPAddress(const std::string &ip_address)
{
struct sockaddr_in sa{};
int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr));
return result != 0;
}
-7
View File
@@ -30,13 +30,6 @@ public:
static uint32_t IPToUInt(const std::string &ip); static uint32_t IPToUInt(const std::string &ip);
static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask); static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask);
static bool IsIpInPrivateRfc1918(const std::string &ip); static bool IsIpInPrivateRfc1918(const std::string &ip);
static std::string GetLocalIPAddress();
static std::string GetPublicIPAddress();
static std::string DNSLookupSync(
const std::string &addr,
int port
);
static bool IsIPAddress(const std::string &ip_address);
}; };
+6 -4
View File
@@ -30,7 +30,6 @@
#include "types.h" #include "types.h"
#include "eqemu_exception.h" #include "eqemu_exception.h"
#include "eqemu_config.h" #include "eqemu_config.h"
#include "path_manager.h"
namespace EQ { namespace EQ {
struct IPCMutex::Implementation { struct IPCMutex::Implementation {
@@ -41,11 +40,12 @@ namespace EQ {
#endif #endif
}; };
IPCMutex::IPCMutex(const std::string& name) : locked_(false) { IPCMutex::IPCMutex(std::string name) : locked_(false) {
imp_ = new Implementation; imp_ = new Implementation;
#ifdef _WINDOWS #ifdef _WINDOWS
auto Config = EQEmuConfig::get(); auto Config = EQEmuConfig::get();
std::string final_name = fmt::format("{}/EQEmuMutex_{}", Config->SharedMemDir, name); std::string final_name = Config->SharedMemDir + "EQEmuMutex_";
final_name += name;
imp_->mut_ = CreateMutex(nullptr, imp_->mut_ = CreateMutex(nullptr,
FALSE, FALSE,
@@ -55,7 +55,9 @@ namespace EQ {
EQ_EXCEPT("IPC Mutex", "Could not create mutex."); EQ_EXCEPT("IPC Mutex", "Could not create mutex.");
} }
#else #else
std::string final_name = fmt::format("{}/{}.lock", path.GetSharedMemoryPath(), name); auto Config = EQEmuConfig::get();
std::string final_name = Config->SharedMemDir + name;
final_name += ".lock";
#ifdef __DARWIN #ifdef __DARWIN
#if __DARWIN_C_LEVEL < 200809L #if __DARWIN_C_LEVEL < 200809L
+1 -1
View File
@@ -37,7 +37,7 @@ namespace EQ {
Creates a named binary semaphore, basically a semaphore that is init S <- 1 Creates a named binary semaphore, basically a semaphore that is init S <- 1
\param name The name of this mutex. \param name The name of this mutex.
*/ */
IPCMutex(const std::string& name); IPCMutex(std::string name);
//! Destructor //! Destructor
~IPCMutex(); ~IPCMutex();
+2 -24
View File
@@ -169,33 +169,11 @@ uint8 EQ::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit)
bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const bool EQ::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const
{ {
if (!(Races & GetPlayerRaceBit(race_id))) { if (!(Races & GetPlayerRaceBit(race_id)))
return false; return false;
}
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) { if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id))))
return false; return false;
}
return true;
}
bool EQ::ItemData::IsClassEquipable(uint16 class_id) const
{
if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) {
return false;
}
return true;
}
bool EQ::ItemData::IsRaceEquipable(uint16 race_id) const
{
if (!(Races & GetPlayerRaceBit(race_id))) {
return false;
}
return true; return true;
} }
+9 -11
View File
@@ -370,7 +370,7 @@ namespace EQ
uint32 Slots; // Bitfield for which slots this item can be used in uint32 Slots; // Bitfield for which slots this item can be used in
uint32 Price; // Item cost (?) uint32 Price; // Item cost (?)
uint32 Icon; // Icon Number uint32 Icon; // Icon Number
int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295) uint32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
bool LoreFlag; // This will be true if LoreGroup is non-zero bool LoreFlag; // This will be true if LoreGroup is non-zero
bool PendingLoreFlag; bool PendingLoreFlag;
bool ArtifactFlag; bool ArtifactFlag;
@@ -473,14 +473,14 @@ namespace EQ
uint32 LDoNSold; uint32 LDoNSold;
uint32 BaneDmgRaceAmt; uint32 BaneDmgRaceAmt;
uint32 AugRestrict; uint32 AugRestrict;
int32 Endur; uint32 Endur;
int32 DotShielding; uint32 DotShielding;
int32 Attack; uint32 Attack;
int32 Regen; uint32 Regen;
int32 ManaRegen; uint32 ManaRegen;
int32 EnduranceRegen; uint32 EnduranceRegen;
int32 Haste; uint32 Haste;
int32 DamageShield; uint32 DamageShield;
uint32 RecastDelay; uint32 RecastDelay;
int RecastType; int RecastType;
uint32 AugDistiller; uint32 AugDistiller;
@@ -533,8 +533,6 @@ namespace EQ
//BardName //BardName
bool IsEquipable(uint16 Race, uint16 Class) const; bool IsEquipable(uint16 Race, uint16 Class) const;
bool IsClassEquipable(uint16 Class) const;
bool IsRaceEquipable(uint16 Race) const;
bool IsClassCommon() const; bool IsClassCommon() const;
bool IsClassBag() const; bool IsClassBag() const;
bool IsClassBook() const; bool IsClassBook() const;
+24 -111
View File
@@ -23,7 +23,7 @@
//#include "races.h" //#include "races.h"
#include "rulesys.h" #include "rulesys.h"
#include "shareddb.h" #include "shareddb.h"
#include "strings.h" #include "string_util.h"
//#include "../common/light_source.h" //#include "../common/light_source.h"
@@ -263,43 +263,20 @@ bool EQ::ItemInstance::IsCharged() const
// Can item be equipped? // Can item be equipped?
bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const bool EQ::ItemInstance::IsEquipable(uint16 race, uint16 class_) const
{ {
if (!m_item || !m_item->Slots) { if (!m_item || (m_item->Slots == 0))
return false; return false;
}
return m_item->IsEquipable(race, class_); return m_item->IsEquipable(race, class_);
} }
// Can item be equipped by Class?
bool EQ::ItemInstance::IsClassEquipable(uint16 class_) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsClassEquipable(class_);
}
// Can item be equipped by Race?
bool EQ::ItemInstance::IsRaceEquipable(uint16 race) const
{
if (!m_item || !m_item->Slots) {
return false;
}
return m_item->IsRaceEquipable(race);
}
// Can equip at this slot? // Can equip at this slot?
bool EQ::ItemInstance::IsEquipable(int16 slot_id) const bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
{ {
if (!m_item || !m_item->Slots) { if (!m_item)
return false; return false;
}
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) { if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END)
return false; return false;
}
return ((m_item->Slots & (1 << slot_id)) != 0); return ((m_item->Slots & (1 << slot_id)) != 0);
} }
@@ -332,30 +309,19 @@ bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
return (index <= EQ::invslot::EQUIPMENT_END); return (index <= EQ::invslot::EQUIPMENT_END);
} }
int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augtype) const
{ {
if (!m_item || !m_item->IsClassCommon()) { if (!m_item || !m_item->IsClassCommon())
return INVALID_INDEX; return INVALID_INDEX;
}
auto i = invaug::SOCKET_BEGIN; int index = invaug::SOCKET_BEGIN;
for (; i <= invaug::SOCKET_END; ++i) { for (; index <= invaug::SOCKET_END; ++index) {
if (GetItem(i)) { if (GetItem(index)) { continue; }
continue; if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype)))
}
if (
augment_type == -1 ||
(
m_item->AugSlotType[i] &&
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
)
) {
break; break;
} }
}
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX; return (index <= invaug::SOCKET_END) ? index : INVALID_INDEX;
} }
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
@@ -534,11 +500,10 @@ bool EQ::ItemInstance::IsNoneEmptyContainer()
} }
// Retrieve augment inside item // Retrieve augment inside item
EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 augment_index) const EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 slot) const
{ {
if (m_item && m_item->IsClassCommon()) { if (m_item && m_item->IsClassCommon())
return GetItem(augment_index); return GetItem(slot);
}
return nullptr; return nullptr;
} }
@@ -561,7 +526,7 @@ EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugty
{ {
continue; continue;
} }
return GetAugment(i); return this->GetAugment(i);
} }
} }
@@ -664,13 +629,12 @@ bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *C
return false; return false;
} }
uint32 EQ::ItemInstance::GetAugmentItemID(uint8 augment_index) const uint32 EQ::ItemInstance::GetAugmentItemID(uint8 slot) const
{ {
if (!m_item || !m_item->IsClassCommon()) { if (!m_item || !m_item->IsClassCommon())
return 0; return 0;
}
return GetItemID(augment_index); return GetItemID(slot);
} }
// Add an augment to the item // Add an augment to the item
@@ -725,45 +689,6 @@ bool EQ::ItemInstance::IsAugmented()
return false; return false;
} }
bool EQ::ItemInstance::ContainsAugmentByID(uint32 item_id)
{
if (!m_item || !m_item->IsClassCommon()) {
return false;
}
if (!item_id) {
return false;
}
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
if (GetAugmentItemID(augment_slot) == item_id) {
return true;
}
}
return false;
}
int EQ::ItemInstance::CountAugmentByID(uint32 item_id)
{
int quantity = 0;
if (!m_item || !m_item->IsClassCommon()) {
return quantity;
}
if (!item_id) {
return quantity;
}
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
if (GetAugmentItemID(augment_slot) == item_id) {
quantity++;
}
}
return quantity;
}
// Has attack/delay? // Has attack/delay?
bool EQ::ItemInstance::IsWeapon() const bool EQ::ItemInstance::IsWeapon() const
{ {
@@ -1133,7 +1058,7 @@ int EQ::ItemInstance::GetItemElementalFlag(bool augments) const
int EQ::ItemInstance::GetItemElementalDamage(bool augments) const int EQ::ItemInstance::GetItemElementalDamage(bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
damage = item->ElemDmgAmt; damage = item->ElemDmgAmt;
@@ -1198,7 +1123,7 @@ int EQ::ItemInstance::GetItemRequiredLevel(bool augments) const
int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
damage = item->Damage; damage = item->Damage;
@@ -1214,7 +1139,7 @@ int EQ::ItemInstance::GetItemWeaponDamage(bool augments) const
int EQ::ItemInstance::GetItemBackstabDamage(bool augments) const int EQ::ItemInstance::GetItemBackstabDamage(bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
damage = item->BackstabDmg; damage = item->BackstabDmg;
@@ -1251,7 +1176,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
{ {
int race = RACE_DOUG_0; int race = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
race = item->BaneDmgRace; race = item->BaneDmgRace;
@@ -1272,7 +1197,7 @@ int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
if (item->BaneDmgBody == against) if (item->BaneDmgBody == against)
@@ -1289,7 +1214,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) con
int EQ::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) const int EQ::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) const
{ {
int64 damage = 0; int damage = 0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
if (item->BaneDmgRace == against) if (item->BaneDmgRace == against)
@@ -1757,18 +1682,6 @@ int EQ::ItemInstance::GetItemHaste(bool augments) const
return total; return total;
} }
int EQ::ItemInstance::RemoveTaskDeliveredItems()
{
int count = IsStackable() ? GetCharges() : 1;
count -= GetTaskDeliveredCount();
if (IsStackable())
{
SetCharges(count);
}
SetTaskDeliveredCount(0);
return count;
}
// //
// class EvolveInfo // class EvolveInfo
// //
+2 -16
View File
@@ -92,8 +92,6 @@ namespace EQ
// Can item be equipped by/at? // Can item be equipped by/at?
bool IsEquipable(uint16 race, uint16 class_) const; bool IsEquipable(uint16 race, uint16 class_) const;
bool IsClassEquipable(uint16 class_) const;
bool IsRaceEquipable(uint16 race) const;
bool IsEquipable(int16 slot_id) const; bool IsEquipable(int16 slot_id) const;
// //
@@ -127,15 +125,13 @@ namespace EQ
// //
// Augments // Augments
// //
ItemInstance* GetAugment(uint8 augment_index) const; ItemInstance* GetAugment(uint8 slot) const;
uint32 GetAugmentItemID(uint8 augment_index) const; uint32 GetAugmentItemID(uint8 slot) const;
void PutAugment(uint8 slot, const ItemInstance& inst); void PutAugment(uint8 slot, const ItemInstance& inst);
void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id); void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id);
void DeleteAugment(uint8 slot); void DeleteAugment(uint8 slot);
ItemInstance* RemoveAugment(uint8 index); ItemInstance* RemoveAugment(uint8 index);
bool IsAugmented(); bool IsAugmented();
bool ContainsAugmentByID(uint32 item_id);
int CountAugmentByID(uint32 item_id);
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const; ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
bool UpdateOrnamentationInfo(); bool UpdateOrnamentationInfo();
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false); static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
@@ -150,8 +146,6 @@ namespace EQ
const ItemData* GetItem() const; const ItemData* GetItem() const;
const ItemData* GetUnscaledItem() const; const ItemData* GetUnscaledItem() const;
const uint8 GetItemType() const { return m_item ? m_item->ItemType : 255; } // Return 255 so you know there's no valid item
int16 GetCharges() const { return m_charges; } int16 GetCharges() const { return m_charges; }
void SetCharges(int16 charges) { m_charges = charges; } void SetCharges(int16 charges) { m_charges = charges; }
@@ -233,13 +227,6 @@ namespace EQ
void StopTimer(std::string name); void StopTimer(std::string name);
void ClearTimers(); void ClearTimers();
int GetTaskDeliveredCount() const { return m_task_delivered_count; }
void SetTaskDeliveredCount(int count) { m_task_delivered_count = count; }
// This function should only be used by trade return apis
// Removes delivered task items from stack count and returns remaining count
// Return value should be used to determine if an item still exists (for stackable and non-stackable)
int RemoveTaskDeliveredItems();
// Get a total of a stat, including augs // Get a total of a stat, including augs
// These functions should be used in place of other code manually totaling // These functions should be used in place of other code manually totaling
// to centralize where it is done to make future changes easier (ex. whenever powersources come around) // to centralize where it is done to make future changes easier (ex. whenever powersources come around)
@@ -324,7 +311,6 @@ namespace EQ
uint32 m_new_id_file; uint32 m_new_id_file;
uint32 m_ornament_hero_model; uint32 m_ornament_hero_model;
uint32 m_recast_timestamp; uint32 m_recast_timestamp;
int m_task_delivered_count = 0;
// //
// Items inside of this item (augs or contents); // Items inside of this item (augs or contents);
-9
View File
@@ -30,19 +30,11 @@ struct LootTableEntries_Struct {
float probability; float probability;
}; };
struct ContentFlags {
int16 min_expansion;
int16 max_expansion;
char content_flags[100];
char content_flags_disabled[100];
};
struct LootTable_Struct { struct LootTable_Struct {
uint32 mincash; uint32 mincash;
uint32 maxcash; uint32 maxcash;
uint32 avgcoin; uint32 avgcoin;
uint32 NumEntries; uint32 NumEntries;
ContentFlags content_flags;
LootTableEntries_Struct Entries[0]; LootTableEntries_Struct Entries[0];
}; };
@@ -60,7 +52,6 @@ struct LootDropEntries_Struct {
struct LootDrop_Struct { struct LootDrop_Struct {
uint32 NumEntries; uint32 NumEntries;
ContentFlags content_flags;
LootDropEntries_Struct Entries[0]; LootDropEntries_Struct Entries[0];
}; };
#pragma pack() #pragma pack()
+2 -2
View File
@@ -9,7 +9,7 @@
*/ */
#include <string.h> /* for memcpy() */ #include <string.h> /* for memcpy() */
#include "../common/md5.h" #include "../common/md5.h"
#include "../common/strings.h" #include "../common/string_util.h"
#include "../common/seperator.h" #include "../common/seperator.h"
MD5::MD5() { MD5::MD5() {
@@ -194,7 +194,7 @@ void MD5::Final(uint8 digest[16], MD5Context *ctx) {
/* The heart of the MD5 algorithm. */ /* The heart of the MD5 algorithm. */
void MD5::Transform(uint32 hash[4], const uint32 input[16]) { void MD5::Transform(uint32 hash[4], const uint32 input[16]) {
uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3]; register uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
MD5STEP(F1, a, b, c, d, input[ 0]+0xd76aa478, 7); MD5STEP(F1, a, b, c, d, input[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, input[ 1]+0xe8c7b756, 12); MD5STEP(F1, d, a, b, c, input[ 1]+0xe8c7b756, 12);
+2 -2
View File
@@ -71,13 +71,13 @@ namespace EQ
template<typename T> template<typename T>
void Write(T val) { void Write(T val) {
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types."); static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
Write((const char*)&val, sizeof(T)); Write((const char*)&val, sizeof(T));
} }
template<typename T> template<typename T>
T Read() { T Read() {
static_assert(std::is_standard_layout<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types."); static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
T temp; T temp;
Read((uchar*)&temp, sizeof(T)); Read((uchar*)&temp, sizeof(T));
return temp; return temp;
-3
View File
@@ -33,9 +33,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#include <filesystem>
namespace fs = std::filesystem;
namespace EQ { namespace EQ {
struct MemoryMappedFile::Implementation { struct MemoryMappedFile::Implementation {
+1 -7
View File
@@ -10,14 +10,8 @@
#include <iterator> #include <iterator>
#include "types.h" #include "types.h"
class MySQLRequestRow class MySQLRequestRow : public std::iterator<std::input_iterator_tag, MYSQL_ROW>
{ {
public:
using iterator_category = std::input_iterator_tag;
using value_type = MYSQL_ROW;
using difference_type = std::ptrdiff_t;
using pointer = MYSQL_ROW*;
using reference = MYSQL_ROW&;
private: private:
MYSQL_RES* m_Result; MYSQL_RES* m_Result;
+3 -3
View File
@@ -1,5 +1,5 @@
#include "console_server.h" #include "console_server.h"
#include "../strings.h" #include "../string_util.h"
#include <fmt/format.h> #include <fmt/format.h>
EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port) EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
@@ -52,11 +52,11 @@ void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c)
void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd) void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd)
{ {
auto split = Strings::Split(cmd, ' '); auto split = SplitString(cmd, ' ');
if (split.size() > 0) { if (split.size() > 0) {
auto command = split[0]; auto command = split[0];
command = Strings::ToLower(command); ToLowerString(command);
if (command == "help" || command == "?") { if (command == "help" || command == "?") {
c->SendLine("Commands:"); c->SendLine("Commands:");
+17 -16
View File
@@ -15,7 +15,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
memset(m_line, 0, MaxConsoleLineLength); memset(m_line, 0, MaxConsoleLineLength);
m_accept_messages = false; m_accept_messages = false;
m_user_id = 0; m_user_id = 0;
m_admin = AccountStatus::Player; m_admin = 0;
m_connection->OnRead(std::bind(&ConsoleServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); m_connection->OnRead(std::bind(&ConsoleServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1)); m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
@@ -29,7 +29,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
if (addr.find("127.0.0.1") != std::string::npos || addr.find("::0") != std::string::npos) { if (addr.find("127.0.0.1") != std::string::npos || addr.find("::0") != std::string::npos) {
SendLine("Connection established from localhost, assuming admin"); SendLine("Connection established from localhost, assuming admin");
m_status = ConsoleStatusLoggedIn; m_status = ConsoleStatusLoggedIn;
m_admin = AccountStatus::Max; m_admin = 255;
SendPrompt(); SendPrompt();
} }
else { else {
@@ -116,42 +116,43 @@ bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMes
} }
switch (scm->chan_num) { switch (scm->chan_num) {
case ChatChannel_Guild: { case 4: {
QueueMessage(fmt::format("{} tells the guild [{}], '{}'", scm->from, scm->guilddbid, scm->message));
break;
}
case ChatChannel_Auction: {
if (RuleB(Chat, ServerWideAuction)) { if (RuleB(Chat, ServerWideAuction)) {
QueueMessage(fmt::format("{} auctions, '{}'", scm->from, scm->message)); QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
break; break;
} else { // I think we want default action in this case? } else { // I think we want default action in this case?
return false; return false;
} }
} }
case ChatChannel_OOC: {
case 5: {
if (RuleB(Chat, ServerWideOOC)) { if (RuleB(Chat, ServerWideOOC)) {
QueueMessage(fmt::format("{} says ooc, '{}'", scm->from, scm->message)); QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
break; break;
} else { // I think we want default action in this case? } else { // I think we want default action in this case?
return false; return false;
} }
} }
case ChatChannel_Broadcast: {
QueueMessage(fmt::format("{} BROADCASTS, '{}'", scm->from, scm->message)); case 6: {
QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message));
break; break;
} }
case ChatChannel_Tell: {
QueueMessage(fmt::format("[{}] tells {}, '{}'", scm->from, scm->to, scm->message)); case 7: {
QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message));
if (onTell) { if (onTell) {
onTell(); onTell();
} }
break; break;
} }
case ChatChannel_GMSAY: {
QueueMessage(fmt::format("{} GMSAYS, '{}'", scm->from, scm->message)); case 11: {
QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message));
break; break;
} }
default: { default: {
return false; return false;
} }
+1 -19
View File
@@ -3,7 +3,6 @@
#include "../event/task.h" #include "../event/task.h"
#include "../data_verification.h" #include "../data_verification.h"
#include "crc32.h" #include "crc32.h"
#include "../eqemu_logsys.h"
#include <zlib.h> #include <zlib.h>
#include <fmt/format.h> #include <fmt/format.h>
#include <sstream> #include <sstream>
@@ -309,8 +308,6 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_combined[1] = OP_Combined; m_combined[1] = OP_Combined;
m_last_session_stats = Clock::now(); m_last_session_stats = Clock::now();
m_outgoing_budget = owner->m_options.outgoing_data_rate; m_outgoing_budget = owner->m_options.outgoing_data_rate;
LogNetcode("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
} }
//new connection made as client //new connection made as client
@@ -633,8 +630,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
DynamicPacket p; DynamicPacket p;
p.PutSerialize(0, reply); p.PutSerialize(0, reply);
InternalSend(p); InternalSend(p);
LogNetcode("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
} }
break; break;
@@ -652,12 +647,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2; m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
m_max_packet_size = reply.max_packet_size; m_max_packet_size = reply.max_packet_size;
ChangeStatus(StatusConnected); ChangeStatus(StatusConnected);
LogNetcode(
"[OP_SessionResponse] Session [{}] refresh with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
} }
} }
break; break;
@@ -782,12 +771,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
SendDisconnect(); SendDisconnect();
} }
LogNetcode(
"[OP_SessionDisconnect] Session [{}] disconnect with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
ChangeStatus(StatusDisconnecting); ChangeStatus(StatusDisconnecting);
break; break;
} }
@@ -852,7 +835,6 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
} }
if (p.Length() < (size_t)m_crc_bytes) { if (p.Length() < (size_t)m_crc_bytes) {
LogNetcode("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code);
return false; return false;
} }
@@ -1412,7 +1394,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length); first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length);
size_t used = 0; size_t used = 0;
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size() - 1; // -1 for compress flag size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size();
DynamicPacket first_packet; DynamicPacket first_packet;
first_packet.PutSerialize(0, first_header); first_packet.PutSerialize(0, first_header);
first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen); first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen);
-9
View File
@@ -65,15 +65,6 @@ EQ::Net::EQStream::~EQStream()
} }
void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) { void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
LogPacketServerClient(
"[{}] [{:#06x}] Size [{}] {}",
OpcodeManager::EmuToName(p->GetOpcode()),
(*m_opcode_manager)->EmuToEQ(p->GetOpcode()),
p->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
);
if (m_opcode_manager && *m_opcode_manager) { if (m_opcode_manager && *m_opcode_manager) {
uint16 opcode = 0; uint16 opcode = 0;
if (p->GetOpcodeBypass() != 0) { if (p->GetOpcodeBypass() != 0) {
-4
View File
@@ -57,10 +57,6 @@ namespace EQ
virtual void SetOpcodeManager(OpcodeManager **opm) { virtual void SetOpcodeManager(OpcodeManager **opm) {
m_opcode_manager = opm; m_opcode_manager = opm;
} }
virtual OpcodeManager * GetOpcodeManager() const
{
return (*m_opcode_manager);
};
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats(); virtual void ResetStats();
@@ -319,16 +319,6 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
size_t message_len = length; size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len); EQ::Net::StaticPacket packet(&data[0], message_len);
const auto is_detail_enabled = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
if (opcode != ServerOP_KeepAlive || is_detail_enabled) {
LogPacketServerToServer(
"[{:#06x}] Size [{}] {}",
opcode,
packet.Length(),
(is_detail_enabled ? "\n" + packet.ToString() : "")
);
}
auto cb = m_message_callbacks.find(opcode); auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) { if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet); cb->second(opcode, packet);
+2 -3
View File
@@ -5,7 +5,6 @@
#include <map> #include <map>
#include <unordered_set> #include <unordered_set>
#include <array> #include <array>
#include "../emu_constants.h"
struct MethodHandlerEntry struct MethodHandlerEntry
{ {
@@ -175,13 +174,13 @@ Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connectio
auto r = _impl->login_handler(connection, user, pass); auto r = _impl->login_handler(connection, user, pass);
if (r.logged_in) { if (r.logged_in) {
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max); connection->SetAuthorized(true, r.account_name, r.account_id, 255);
ret["status"] = "Ok"; ret["status"] = "Ok";
} }
else if (user == "admin" && (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::")) { else if (user == "admin" && (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::")) {
r.logged_in = true; r.logged_in = true;
r.account_id = 0; r.account_id = 0;
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max); connection->SetAuthorized(true, r.account_name, r.account_id, 255);
ret["status"] = "Ok"; ret["status"] = "Ok";
} }
else { else {
+2 -2
View File
@@ -115,8 +115,8 @@ IN(OP_GMTraining, GMTrainee_Struct);
IN(OP_GMEndTraining, GMTrainEnd_Struct); IN(OP_GMEndTraining, GMTrainEnd_Struct);
IN(OP_GMTrainSkill, GMSkillChange_Struct); IN(OP_GMTrainSkill, GMSkillChange_Struct);
IN(OP_RequestDuel, Duel_Struct); IN(OP_RequestDuel, Duel_Struct);
IN(OP_DuelDecline, DuelResponse_Struct); IN(OP_DuelResponse, DuelResponse_Struct);
IN(OP_DuelAccept, Duel_Struct); IN(OP_DuelResponse2, Duel_Struct);
IN(OP_SpawnAppearance, SpawnAppearance_Struct); IN(OP_SpawnAppearance, SpawnAppearance_Struct);
IN(OP_BazaarInspect, BazaarInspect_Struct); IN(OP_BazaarInspect, BazaarInspect_Struct);
IN(OP_Death, Death_Struct); IN(OP_Death, Death_Struct);
+2 -2
View File
@@ -240,8 +240,8 @@ void load_opcode_names()
opcode_map[0x00a1] = "LiveOP_SaveOnZoneReq"; opcode_map[0x00a1] = "LiveOP_SaveOnZoneReq";
opcode_map[0x0185] = "LiveOP_Logout"; opcode_map[0x0185] = "LiveOP_Logout";
opcode_map[0x0298] = "LiveOP_RequestDuel"; opcode_map[0x0298] = "LiveOP_RequestDuel";
opcode_map[0x0a5d] = "LiveOP_DuelDecline"; opcode_map[0x0a5d] = "LiveOP_DuelResponse";
opcode_map[0x016e] = "LiveOP_DuelAccept"; opcode_map[0x016e] = "LiveOP_DuelResponse2";
opcode_map[0x007c] = "LiveOP_InstillDoubt"; opcode_map[0x007c] = "LiveOP_InstillDoubt";
opcode_map[0x00ac] = "LiveOP_SafeFallSuccess"; opcode_map[0x00ac] = "LiveOP_SafeFallSuccess";
opcode_map[0x02fb] = "LiveOP_DisciplineUpdate"; opcode_map[0x02fb] = "LiveOP_DisciplineUpdate";
-3
View File
@@ -184,9 +184,6 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
MOpcodes.lock(); MOpcodes.lock();
res = emu_to_eq[emu_op]; res = emu_to_eq[emu_op];
MOpcodes.unlock(); MOpcodes.unlock();
LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res);
#ifdef DEBUG_TRANSLATE #ifdef DEBUG_TRANSLATE
fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res); fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
#endif #endif
+66 -25
View File
@@ -28,12 +28,10 @@
#include "../eq_packet_structs.h" #include "../eq_packet_structs.h"
#include "../misc_functions.h" #include "../misc_functions.h"
#include "../strings.h" #include "../string_util.h"
#include "../inventory_profile.h" #include "../inventory_profile.h"
#include "rof_structs.h" #include "rof_structs.h"
#include "../rulesys.h" #include "../rulesys.h"
#include "../path_manager.h"
#include "../races.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@@ -77,8 +75,12 @@ namespace RoF
{ {
//create our opcode manager if we havent already //create our opcode manager if we havent already
if (opcodes == nullptr) { if (opcodes == nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
//load up the opcode manager. //load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches... //TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager(); opcodes = new RegularOpcodeManager();
@@ -116,7 +118,12 @@ namespace RoF
//we need to go to every stream and replace it's manager. //we need to go to every stream and replace it's manager.
if (opcodes != nullptr) { if (opcodes != nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
if (!opcodes->ReloadOpcodes(opfile.c_str())) { if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return; return;
@@ -665,7 +672,7 @@ namespace RoF
ENCODE(OP_DeleteCharge) ENCODE(OP_DeleteCharge)
{ {
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)"); Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem); ENCODE_FORWARD(OP_MoveItem);
} }
@@ -729,6 +736,30 @@ namespace RoF
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning) ENCODE(OP_DzExpeditionEndsWarning)
{ {
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1593,7 +1624,7 @@ namespace RoF
ENCODE_LENGTH_EXACT(LootingItem_Struct); ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_LootItem)");
OUT(lootee); OUT(lootee);
OUT(looter); OUT(looter);
@@ -1603,6 +1634,20 @@ namespace RoF
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_ManaChange)
{
ENCODE_LENGTH_EXACT(ManaChange_Struct);
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
OUT(new_mana);
OUT(stamina);
OUT(spell_id);
OUT(keepcasting);
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
FINISH_ENCODE();
}
ENCODE(OP_MercenaryDataResponse) ENCODE(OP_MercenaryDataResponse)
{ {
//consume the packet //consume the packet
@@ -1751,7 +1796,7 @@ namespace RoF
ENCODE_LENGTH_EXACT(MoveItem_Struct); ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToRoFSlot(emu->from_slot); eq->from_slot = ServerToRoFSlot(emu->from_slot);
eq->to_slot = ServerToRoFSlot(emu->to_slot); eq->to_slot = ServerToRoFSlot(emu->to_slot);
@@ -1807,10 +1852,10 @@ namespace RoF
OUT_str(zone_short_name2); OUT_str(zone_short_name2);
OUT(zone_id); OUT(zone_id);
OUT(zone_instance); OUT(zone_instance);
OUT(suspend_buffs); OUT(SuspendBuffs);
OUT(fast_regen_hp); OUT(FastRegenHP);
OUT(fast_regen_mana); OUT(FastRegenMana);
OUT(fast_regen_endurance); OUT(FastRegenEndurance);
OUT(underworld_teleport_index); OUT(underworld_teleport_index);
eq->FogDensity = emu->fog_density; eq->FogDensity = emu->fog_density;
@@ -1818,8 +1863,8 @@ namespace RoF
/*fill in some unknowns with observed values, hopefully it will help */ /*fill in some unknowns with observed values, hopefully it will help */
eq->unknown800 = -1; eq->unknown800 = -1;
eq->unknown844 = 600; eq->unknown844 = 600;
OUT(lava_damage); OUT(LavaDamage);
OUT(min_lava_damage); OUT(MinLavaDamage);
eq->unknown888 = 1; eq->unknown888 = 1;
eq->unknown889 = 0; eq->unknown889 = 0;
eq->unknown890 = 1; eq->unknown890 = 1;
@@ -3831,9 +3876,7 @@ namespace RoF
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{ {
PacketSize += 60; PacketSize += 60;
@@ -3965,9 +4008,7 @@ namespace RoF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{ {
@@ -4822,7 +4863,7 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::LootingItem_Struct); DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_LootItem)");
IN(lootee); IN(lootee);
IN(looter); IN(looter);
@@ -4837,7 +4878,7 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF::DECODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF::DECODE(OP_MoveItem)");
emu->from_slot = RoFToServerSlot(eq->from_slot); emu->from_slot = RoFToServerSlot(eq->from_slot);
emu->to_slot = RoFToServerSlot(eq->to_slot); emu->to_slot = RoFToServerSlot(eq->to_slot);
@@ -6096,7 +6137,7 @@ namespace RoF
return; return;
} }
auto segments = Strings::Split(serverSayLink, '\x12'); auto segments = SplitString(serverSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
@@ -6135,7 +6176,7 @@ namespace RoF
return; return;
} }
auto segments = Strings::Split(rofSayLink, '\x12'); auto segments = SplitString(rofSayLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
+82 -45
View File
@@ -28,13 +28,10 @@
#include "../eq_packet_structs.h" #include "../eq_packet_structs.h"
#include "../misc_functions.h" #include "../misc_functions.h"
#include "../strings.h" #include "../string_util.h"
#include "../inventory_profile.h" #include "../inventory_profile.h"
#include "rof2_structs.h" #include "rof2_structs.h"
#include "../rulesys.h" #include "../rulesys.h"
#include "../path_manager.h"
#include "../classes.h"
#include "../races.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@@ -79,9 +76,12 @@ namespace RoF2
{ {
//create our opcode manager if we havent already //create our opcode manager if we havent already
if (opcodes == nullptr) { if (opcodes == nullptr) {
//TODO: get this file name from the config file
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
//load up the opcode manager. //load up the opcode manager.
//TODO: figure out how to support shared memory with multiple patches... //TODO: figure out how to support shared memory with multiple patches...
opcodes = new RegularOpcodeManager(); opcodes = new RegularOpcodeManager();
@@ -122,7 +122,12 @@ namespace RoF2
//we need to go to every stream and replace it's manager. //we need to go to every stream and replace it's manager.
if (opcodes != nullptr) { if (opcodes != nullptr) {
std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //TODO: get this file name from the config file
auto Config = EQEmuConfig::get();
std::string opfile = Config->PatchDir;
opfile += "patch_";
opfile += name;
opfile += ".conf";
if (!opcodes->ReloadOpcodes(opfile.c_str())) { if (!opcodes->ReloadOpcodes(opfile.c_str())) {
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
return; return;
@@ -716,7 +721,7 @@ namespace RoF2
ENCODE(OP_DeleteCharge) ENCODE(OP_DeleteCharge)
{ {
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_DeleteCharge)");
ENCODE_FORWARD(OP_MoveItem); ENCODE_FORWARD(OP_MoveItem);
} }
@@ -780,6 +785,30 @@ namespace RoF2
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_DzCompass)
{
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
sizeof(structs::DynamicZoneCompass_Struct) +
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
);
OUT(client_id);
OUT(count);
for (uint32 i = 0; i < emu->count; ++i)
{
OUT(entries[i].dz_zone_id);
OUT(entries[i].dz_instance_id);
OUT(entries[i].dz_type);
OUT(entries[i].x);
OUT(entries[i].y);
OUT(entries[i].z);
}
FINISH_ENCODE();
}
ENCODE(OP_DzExpeditionEndsWarning) ENCODE(OP_DzExpeditionEndsWarning)
{ {
ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); ENCODE_LENGTH_EXACT(ExpeditionExpireWarning);
@@ -1644,7 +1673,7 @@ namespace RoF2
ENCODE_LENGTH_EXACT(LootingItem_Struct); ENCODE_LENGTH_EXACT(LootingItem_Struct);
SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_LootItem)");
OUT(lootee); OUT(lootee);
OUT(looter); OUT(looter);
@@ -1654,6 +1683,20 @@ namespace RoF2
FINISH_ENCODE(); FINISH_ENCODE();
} }
ENCODE(OP_ManaChange)
{
ENCODE_LENGTH_EXACT(ManaChange_Struct);
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
OUT(new_mana);
OUT(stamina);
OUT(spell_id);
OUT(keepcasting);
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
FINISH_ENCODE();
}
ENCODE(OP_MercenaryDataResponse) ENCODE(OP_MercenaryDataResponse)
{ {
//consume the packet //consume the packet
@@ -1802,7 +1845,7 @@ namespace RoF2
ENCODE_LENGTH_EXACT(MoveItem_Struct); ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::ENCODE(OP_MoveItem)");
eq->from_slot = ServerToRoF2Slot(emu->from_slot); eq->from_slot = ServerToRoF2Slot(emu->from_slot);
eq->to_slot = ServerToRoF2Slot(emu->to_slot); eq->to_slot = ServerToRoF2Slot(emu->to_slot);
@@ -1858,13 +1901,13 @@ namespace RoF2
OUT_str(zone_short_name2); OUT_str(zone_short_name2);
OUT(zone_id); OUT(zone_id);
OUT(zone_instance); OUT(zone_instance);
OUT(suspend_buffs); OUT(SuspendBuffs);
OUT(fast_regen_hp); OUT(FastRegenHP);
OUT(fast_regen_mana); OUT(FastRegenMana);
OUT(fast_regen_endurance); OUT(FastRegenEndurance);
OUT(underworld_teleport_index); OUT(underworld_teleport_index);
eq->fog_density = emu->fog_density; eq->FogDensity = emu->fog_density;
/*fill in some unknowns with observed values, hopefully it will help */ /*fill in some unknowns with observed values, hopefully it will help */
eq->ZoneTimeZone = 0; eq->ZoneTimeZone = 0;
@@ -1876,8 +1919,8 @@ namespace RoF2
eq->SkyRelated2 = -1; eq->SkyRelated2 = -1;
eq->NPCAggroMaxDist = 600; eq->NPCAggroMaxDist = 600;
eq->FilterID = 2008; // Guild Lobby observed value eq->FilterID = 2008; // Guild Lobby observed value
OUT(lava_damage); OUT(LavaDamage);
OUT(min_lava_damage); OUT(MinLavaDamage);
eq->bDisallowManaStone = 1; eq->bDisallowManaStone = 1;
eq->bNoBind = 0; eq->bNoBind = 0;
eq->bNoAttack = 0; eq->bNoAttack = 0;
@@ -1886,12 +1929,12 @@ namespace RoF2
eq->bNoFear = 0; eq->bNoFear = 0;
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
eq->unknown895 = 0; eq->unknown895 = 0;
eq->can_place_campsite = 2; eq->CanPlaceCampsite = 2;
eq->can_place_guild_banner = 2; eq->CanPlaceGuildBanner = 2;
eq->fishing_related = -1; // Set from PoK Example eq->FishingRelated = -1; // Set from PoK Example
eq->forage_related = -1; // Set from PoK Example eq->ForageRelated = -1; // Set from PoK Example
eq->b_no_levitate = 0; eq->bNoLevitate = 0;
eq->blooming = 1.0; // Set from PoK Example eq->Blooming = 1.0; // Set from PoK Example
FINISH_ENCODE(); FINISH_ENCODE();
} }
@@ -3946,7 +3989,7 @@ namespace RoF2
if (strlen(emu->suffix)) if (strlen(emu->suffix))
PacketSize += strlen(emu->suffix) + 1; PacketSize += strlen(emu->suffix) + 1;
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) if (emu->DestructibleObject || emu->class_ == 62)
{ {
if (emu->DestructibleObject) if (emu->DestructibleObject)
PacketSize = PacketSize - 4; // No bodytype PacketSize = PacketSize - 4; // No bodytype
@@ -3967,9 +4010,7 @@ namespace RoF2
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
)
{ {
PacketSize += 60; PacketSize += 60;
@@ -4036,19 +4077,17 @@ namespace RoF2
// actually part of bitfields // actually part of bitfields
uint8 OtherData = 0; uint8 OtherData = 0;
if (emu->class_ == LDON_TREASURE) //LDoN Chest if (emu->class_ == 62) //LDoN Chest
{
OtherData = OtherData | 0x04; OtherData = OtherData | 0x04;
}
if (strlen(emu->title)) { if (strlen(emu->title))
OtherData = OtherData | 16; OtherData = OtherData | 16;
}
if (strlen(emu->suffix)) { if (strlen(emu->suffix))
OtherData = OtherData | 32; OtherData = OtherData | 32;
}
if (emu->DestructibleObject) { if (emu->DestructibleObject)
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
// float EmitterScalingRadius // float EmitterScalingRadius
@@ -4064,7 +4103,7 @@ namespace RoF2
// int DefaultEmitterID // int DefaultEmitterID
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
if (emu->DestructibleObject || emu->class_ == LDON_TREASURE) if (emu->DestructibleObject || emu->class_ == 62)
{ {
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel);
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2);
@@ -4172,9 +4211,7 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) || if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
)
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
{ {
@@ -5023,7 +5060,7 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::LootingItem_Struct); DECODE_LENGTH_EXACT(structs::LootingItem_Struct);
SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_LootItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_LootItem)");
IN(lootee); IN(lootee);
IN(looter); IN(looter);
@@ -5038,7 +5075,7 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)"); Log(Logs::Moderate, Logs::Netcode, "RoF2::DECODE(OP_MoveItem)");
emu->from_slot = RoF2ToServerSlot(eq->from_slot); emu->from_slot = RoF2ToServerSlot(eq->from_slot);
emu->to_slot = RoF2ToServerSlot(eq->to_slot); emu->to_slot = RoF2ToServerSlot(eq->to_slot);
@@ -6323,7 +6360,7 @@ namespace RoF2
return; return;
} }
auto segments = Strings::Split(server_saylink, '\x12'); auto segments = SplitString(server_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
@@ -6355,7 +6392,7 @@ namespace RoF2
return; return;
} }
auto segments = Strings::Split(rof2_saylink, '\x12'); auto segments = SplitString(rof2_saylink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) { if (segment_iter & 1) {
+1 -1
View File
@@ -19,7 +19,7 @@
#include "rof2_limits.h" #include "rof2_limits.h"
#include "../strings.h" #include "../string_util.h"
int16 RoF2::invtype::GetInvTypeSize(int16 inv_type) int16 RoF2::invtype::GetInvTypeSize(int16 inv_type)
+2
View File
@@ -59,6 +59,7 @@ E(OP_DeleteItem)
E(OP_DeleteSpawn) E(OP_DeleteSpawn)
E(OP_DisciplineUpdate) E(OP_DisciplineUpdate)
E(OP_DzChooseZone) E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo) E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite) E(OP_DzExpeditionInvite)
@@ -92,6 +93,7 @@ E(OP_ItemVerifyReply)
E(OP_LeadershipExpUpdate) E(OP_LeadershipExpUpdate)
E(OP_LogServer) E(OP_LogServer)
E(OP_LootItem) E(OP_LootItem)
E(OP_ManaChange)
E(OP_MercenaryDataResponse) E(OP_MercenaryDataResponse)
E(OP_MercenaryDataUpdate) E(OP_MercenaryDataUpdate)
E(OP_MoveItem) E(OP_MoveItem)
+20 -25
View File
@@ -630,9 +630,9 @@ struct NewZone_Struct {
/*0864*/ uint32 scriptIDSomething; /*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions /*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3; /*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 suspend_buffs; // padded bool /*0876*/ uint32 SuspendBuffs; // padded bool
/*0880*/ uint32 lava_damage; // lava_damage value /*0880*/ uint32 LavaDamage; // LavaDamage value
/*0884*/ uint32 min_lava_damage; // min cap after resist calcs /*0884*/ uint32 MinLavaDamage; // min cap after resist calcs
/*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone /*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone
/*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can! /*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can!
/*0890*/ uint8 bNoAttack; // non-attack zone /*0890*/ uint8 bNoAttack; // non-attack zone
@@ -641,19 +641,19 @@ struct NewZone_Struct {
/*0893*/ uint8 bNoFear; // fear spells no worky /*0893*/ uint8 bNoFear; // fear spells no worky
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber /*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber
/*0895*/ uint8 unknown895; // padding /*0895*/ uint8 unknown895; // padding
/*0896*/ uint32 fast_regen_hp; // percentage I think? /*0896*/ uint32 FastRegenHP; // percentage I think?
/*0900*/ uint32 fast_regen_mana; // percentage I think? /*0900*/ uint32 FastRegenMana; // percentage I think?
/*0904*/ uint32 fast_regen_endurance; // percentage I think? /*0904*/ uint32 FastRegenEndurance; // percentage I think?
/*0908*/ uint32 can_place_campsite; // 0 = no, 1 = can place, 2 = place and goto /*0908*/ uint32 CanPlaceCampsite; // 0 = no, 1 = can place, 2 = place and goto
/*0912*/ uint32 can_place_guild_banner; // ^ /*0912*/ uint32 CanPlaceGuildBanner; // ^
/*0916*/ float fog_density; // Most zones have this set to 0.33 Blightfire had 0.16 /*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
/*0920*/ uint32 b_adjust_gamma; // padded bool /*0920*/ uint32 bAdjustGamma; // padded bool
/*0924*/ uint32 time_string_id; // Seen 0 /*0924*/ uint32 TimeStringID; // Seen 0
/*0928*/ uint32 b_no_mercenaries; // padded bool /*0928*/ uint32 bNoMercenaries; // padded bool
/*0932*/ int32 fishing_related; // Seen -1 idk /*0932*/ int32 FishingRelated; // Seen -1 idk
/*0936*/ int32 forage_related; // Seen -1 idk /*0936*/ int32 ForageRelated; // Seen -1 idk
/*0940*/ uint32 b_no_levitate; // padded bool /*0940*/ uint32 bNoLevitate; // padded bool
/*0944*/ float blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby /*0944*/ float Blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
/*0948*/ /*0948*/
}; };
@@ -2649,11 +2649,11 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle; /*004*/ uint8 hairstyle;
/*005*/ uint8 beard; /*005*/ uint8 beard;
/*006*/ uint8 face; /*006*/ uint8 face;
/*007*/ uint8 unused_padding; /*007*/ uint8 unknown007;
/*008*/ uint32 drakkin_heritage; /*008*/ uint32 drakkin_heritage;
/*012*/ uint32 drakkin_tattoo; /*012*/ uint32 drakkin_tattoo;
/*016*/ uint32 drakkin_details; /*016*/ uint32 drakkin_details;
/*020*/ uint32 entity_id; /*020*/ uint32 unknown020;
/*024*/ /*024*/
}; };
//there are only 10 faces for barbs changing woad just //there are only 10 faces for barbs changing woad just
@@ -3061,7 +3061,7 @@ struct EnvDamage2_Struct {
/*0006*/ uint32 damage; /*0006*/ uint32 damage;
/*0010*/ float unknown10; // New to Underfoot - Seen 1 /*0010*/ float unknown10; // New to Underfoot - Seen 1
/*0014*/ uint8 unknown14[12]; /*0014*/ uint8 unknown14[12];
/*0026*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap /*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling
/*0027*/ uint8 unknown27[4]; /*0027*/ uint8 unknown27[4];
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66 /*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
/*0033*/ uint16 constant; // Always FFFF /*0033*/ uint16 constant; // Always FFFF
@@ -4989,7 +4989,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair /*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id; /*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 dz_switch_id; /*008*/ uint32 unknown008;
/*012*/ float y; /*012*/ float y;
/*016*/ float x; /*016*/ float x;
/*020*/ float z; /*020*/ float z;
@@ -5218,11 +5218,6 @@ struct SayLinkBodyFrame_Struct {
/*056*/ /*056*/
}; };
struct Checksum_Struct {
uint64_t checksum;
uint8_t data[2048];
};
}; /*structs*/ }; /*structs*/
}; /*RoF2*/ }; /*RoF2*/
+1 -1
View File
@@ -19,7 +19,7 @@
#include "rof_limits.h" #include "rof_limits.h"
#include "../strings.h" #include "../string_util.h"
int16 RoF::invtype::GetInvTypeSize(int16 inv_type) int16 RoF::invtype::GetInvTypeSize(int16 inv_type)
+2
View File
@@ -45,6 +45,7 @@ E(OP_DeleteItem)
E(OP_DeleteSpawn) E(OP_DeleteSpawn)
E(OP_DisciplineUpdate) E(OP_DisciplineUpdate)
E(OP_DzChooseZone) E(OP_DzChooseZone)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo) E(OP_DzExpeditionInfo)
E(OP_DzExpeditionInvite) E(OP_DzExpeditionInvite)
@@ -78,6 +79,7 @@ E(OP_ItemVerifyReply)
E(OP_LeadershipExpUpdate) E(OP_LeadershipExpUpdate)
E(OP_LogServer) E(OP_LogServer)
E(OP_LootItem) E(OP_LootItem)
E(OP_ManaChange)
E(OP_MercenaryDataResponse) E(OP_MercenaryDataResponse)
E(OP_MercenaryDataUpdate) E(OP_MercenaryDataUpdate)
E(OP_MoveItem) E(OP_MoveItem)
+10 -10
View File
@@ -580,9 +580,9 @@ struct NewZone_Struct {
/*0864*/ uint32 scriptIDSomething; /*0864*/ uint32 scriptIDSomething;
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions /*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
/*0872*/ uint32 scriptIDSomething3; /*0872*/ uint32 scriptIDSomething3;
/*0876*/ uint32 suspend_buffs; /*0876*/ uint32 SuspendBuffs;
/*0880*/ uint32 lava_damage; // Seen 50 /*0880*/ uint32 LavaDamage; // Seen 50
/*0884*/ uint32 min_lava_damage; // Seen 10 /*0884*/ uint32 MinLavaDamage; // Seen 10
/*0888*/ uint8 unknown888; // Seen 1 /*0888*/ uint8 unknown888; // Seen 1
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj) /*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
/*0890*/ uint8 unknown890; // Seen 1 /*0890*/ uint8 unknown890; // Seen 1
@@ -591,9 +591,9 @@ struct NewZone_Struct {
/*0893*/ uint8 unknown893; // Seen 0 - 00 /*0893*/ uint8 unknown893; // Seen 0 - 00
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off /*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
/*0895*/ uint8 unknown895; // Seen 0 - 00 /*0895*/ uint8 unknown895; // Seen 0 - 00
/*0896*/ uint32 fast_regen_hp; // Seen 180 /*0896*/ uint32 FastRegenHP; // Seen 180
/*0900*/ uint32 fast_regen_mana; // Seen 180 /*0900*/ uint32 FastRegenMana; // Seen 180
/*0904*/ uint32 fast_regen_endurance; // Seen 180 /*0904*/ uint32 FastRegenEndurance; // Seen 180
/*0908*/ uint32 unknown908; // Seen 2 /*0908*/ uint32 unknown908; // Seen 2
/*0912*/ uint32 unknown912; // Seen 2 /*0912*/ uint32 unknown912; // Seen 2
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16 /*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
@@ -2622,11 +2622,11 @@ struct FaceChange_Struct {
/*004*/ uint8 hairstyle; /*004*/ uint8 hairstyle;
/*005*/ uint8 beard; /*005*/ uint8 beard;
/*006*/ uint8 face; /*006*/ uint8 face;
/*007*/ uint8 unused_padding; /*007*/ uint8 unknown007;
/*008*/ uint32 drakkin_heritage; /*008*/ uint32 drakkin_heritage;
/*012*/ uint32 drakkin_tattoo; /*012*/ uint32 drakkin_tattoo;
/*016*/ uint32 drakkin_details; /*016*/ uint32 drakkin_details;
/*020*/ uint32 entity_id; /*020*/ uint32 unknown020;
/*024*/ /*024*/
}; };
//there are only 10 faces for barbs changing woad just //there are only 10 faces for barbs changing woad just
@@ -3032,7 +3032,7 @@ struct EnvDamage2_Struct {
/*0006*/ uint32 damage; /*0006*/ uint32 damage;
/*0010*/ float unknown10; // New to Underfoot - Seen 1 /*0010*/ float unknown10; // New to Underfoot - Seen 1
/*0014*/ uint8 unknown14[12]; /*0014*/ uint8 unknown14[12];
/*0026*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap /*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling
/*0027*/ uint8 unknown27[4]; /*0027*/ uint8 unknown27[4];
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66 /*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
/*0033*/ uint16 constant; // Always FFFF /*0033*/ uint16 constant; // Always FFFF
@@ -4921,7 +4921,7 @@ struct DynamicZoneCompassEntry_Struct
/*000*/ uint16 dz_zone_id; // target dz id pair /*000*/ uint16 dz_zone_id; // target dz id pair
/*002*/ uint16 dz_instance_id; /*002*/ uint16 dz_instance_id;
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) /*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
/*008*/ uint32 dz_switch_id; /*008*/ uint32 unknown008;
/*012*/ float y; /*012*/ float y;
/*016*/ float x; /*016*/ float x;
/*020*/ float z; /*020*/ float z;

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