Compare commits

..

2 Commits

Author SHA1 Message Date
Akkadius 63c2f20cb0 Update content_filter_criteria.h 2024-02-17 14:49:33 -06:00
Akkadius fa46cbb539 [Expansions] Fix content filter criteria for max_expansions 2024-02-17 14:19:58 -06:00
720 changed files with 44609 additions and 98847 deletions
-6
View File
@@ -1,6 +0,0 @@
!Makefile
base/*.sql
base/*.zip
base/db/
base/maps/
!base/expansion/Makefile
@@ -1,9 +0,0 @@
# This is a "dev" image for running eqemu in development, also for dev containers
ARG USERNAME=user-name-goes-here
ARG USER_UID=1000
ARG USER_GID=$USER_UID
FROM --platform=linux/arm64 mcr.microsoft.com/devcontainers/base:debian
RUN sudo apt update && sudo apt install -y --no-install-recommends build-essential libtool cmake curl debconf-utils git libluabind-dev libsodium-dev liblua5.2-0 liblua5.2-dev libmariadb-dev libssl-dev minizip make mariadb-client locales nano open-vm-tools unzip uuid-dev iputils-ping wget libcurl4-openssl-dev gdb libyaml-cpp-dev ccache ninja-build pv mariadb-server libperl-dev libjson-perl libio-stringy-perl liblua5.1-dev libluabind-dev libboost-dev mariadb-server valgrind telnet libgoogle-perftools-dev google-perftools
USER $USERNAME
-9
View File
@@ -1,9 +0,0 @@
# This is a "dev" image for running eqemu in development, also for dev containers
ARG USERNAME=user-name-goes-here
ARG USER_UID=1000
ARG USER_GID=$USER_UID
FROM mcr.microsoft.com/devcontainers/base:debian
RUN sudo apt update && sudo apt install -y --no-install-recommends build-essential libtool cmake curl debconf-utils git libluabind-dev libsodium-dev liblua5.2-0 liblua5.2-dev libmariadb-dev libssl-dev minizip make mariadb-client locales nano open-vm-tools unzip uuid-dev iputils-ping wget libcurl4-openssl-dev gdb libyaml-cpp-dev ccache ninja-build pv mariadb-server libperl-dev libjson-perl libio-stringy-perl liblua5.1-dev libluabind-dev libboost-dev mariadb-server valgrind telnet libgoogle-perftools-dev google-perftools
USER $USERNAME
-284
View File
@@ -1,284 +0,0 @@
NAME := eqemu-server
.ONESHELL:
DOCKER_ARGS := --rm --name ${NAME} -v $$PWD:/src -w /src ${NAME}
DOCKER_ARM64_ARGS := --rm --platform linux/arm64 --name ${NAME}-arm64 -v $$PWD:/src -w /src ${NAME}-arm64
.PHONY: build
build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile build --no-print-directory
exit
endif
cd build$$BUILD_SUFFIX && cmake --build . --config Release --target all --
.PHONY: cmake
cmake:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile cmake --no-print-directory
exit
endif
@echo "working directory: $$PWD"
mkdir -p build$$BUILD_SUFFIX
@cd build$$BUILD_SUFFIX && cmake -DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_TESTS=ON \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja ..
clean:
ifneq (,$(findstring .devcontainer,$$PWD))
@make -C ../ -f .devcontainer/Makefile clean --no-print-directory
endif
rm -rf build
docker-cmake:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-cmake --no-print-directory
exit
endif
@echo "working directory: $$PWD"
git submodule update --init --recursive
docker run ${DOCKER_ARGS} make cmake
docker-build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-build --no-print-directory
exit
endif
docker run ${DOCKER_ARGS} make build
# Build image if it doesn't exist
docker-image-build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-image-build --no-print-directory
exit
endif
ifeq ($(shell docker images -q ${NAME} 2> /dev/null),)
@echo "Docker image not found. Building..."
docker build -f Dockerfile.debian.dev -t ${NAME} .
endif
docker-arm-cmake: docker-arm-image-build
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-arm-cmake --no-print-directory
exit
endif
git submodule update --init --recursive
docker run ${DOCKER_ARM64_ARGS} make cmake BUILD_SUFFIX=arm64
docker-arm-build: docker-arm-image-build
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-arm-build --no-print-directory
exit
endif
docker run ${DOCKER_ARM64_ARGS} make build BUILD_SUFFIX=arm64
docker-arm-image-build:
ifeq ($(shell docker images -q ${NAME}-arm64 2> /dev/null),)
@echo "Docker image not found. Building..."
docker build -f Dockerfile.debian.arm.dev -t ${NAME}-arm64 .
endif
docker-clean: clean
.PHONY: prep
prep:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile prep --no-print-directory
exit
endif
@echo "Preparing build/bin for usage..."
mkdir -p build/bin/assets/patches
cp -R -u -p .devcontainer/base/eqemu_config.json build/bin/eqemu_config.json
cp -R -u -p .devcontainer/base/login.json build/bin/login.json
cp -R -u -p loginserver/login_util/* build/bin/assets/patches/
mkdir -p build/bin/assets
cp -R -u -p utils/patches build/bin/assets/
-unlink build/bin/lua_modules
cd build/bin && ln -s quests/lua_modules lua_modules
-unlink build/bin/mods
cd build/bin && ln -s quests/mods mods
-unlink build/bin/maps
cd build/bin && ln -s ../../base/maps maps
mkdir -p build/bin/logs
mkdir -p build/bin/shared
@echo "Eqemu is prepared. Edit build/bin/eqemu_config.json to configure."
maps:
@echo "Downloading maps..."
@mkdir -p base/maps
@cd base/maps && wget -nc https://github.com/Akkadius/eqemu-maps/archive/refs/heads/master.zip
@cd base/maps && unzip -o master.zip
@cd base/maps && mv eqemu-maps-master/* .
@cd base/maps && rm -rf eqemu-maps-master
@echo "Maps downloaded."
quests:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile quests --no-print-directory
exit
endif
@cd build/bin && git clone https://github.com/ProjectEQ/projecteqquests.git quests
# Runs tests
.PHONY: test
test:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile test --no-print-directory
exit
endif
cd build/bin && ./tests
# Runs login binary
.PHONY: login
login:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile login --no-print-directory
exit
endif
cd build/bin && ./loginserver
# Runs shared_memory binary
.PHONY: shared
shared:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile shared --no-print-directory
exit
endif
cd build/bin && ./shared_memory
# Runs zone binary
.PHONY: zone
zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile zone --no-print-directory
exit
endif
@-rm build/bin/logs/zone/zone*.log
cd build/bin && ./zone
# Runs world binary
.PHONY: world
world:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile world --no-print-directory
exit
endif
@-rm build/bin/logs/world*.log
cd build/bin && ./world
# Runs ucs binary
.PHONY: ucs
ucs:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile ucs --no-print-directory
exit
endif
@-rm build/bin/logs/ucs*.log
cd build/bin && ./ucs
# Runs queryserv binary
.PHONY: queryserv
queryserv:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile queryserv --no-print-directory
exit
endif
@-rm build/bin/logs/query_server*.log
cd build/bin && ./queryserv
valgrind-%:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile valgrind --no-print-directory
exit
endif
cd build/bin && valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=logs/$*.valgrind.log ./$*
# Start mariaDB standalone
.PHONY: mariadb
mariadb:
@sudo service mariadb start
.PHONY: inject-mariadb
inject-mariadb:
-sudo service mariadb start
-mkdir -p base/db/
-sudo mariadb -e 'DROP DATABASE IF EXISTS peq;'
-sudo mariadb -e 'CREATE DATABASE peq;'
-sudo mariadb -e "CREATE USER 'peq'@'127.0.0.1' IDENTIFIED BY 'peqpass';"
-sudo mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'peq'@'127.0.0.1';"
ifeq (,$(wildcard base/db/db.sql.zip))
@echo "base/db.sql.zip not found. Downloading latest from https://db.projecteq.net/"
wget -nc https://db.projecteq.net/latest -O base/db/db.sql.zip
-cd base/db && unzip db.sql.zip
endif
@echo "Sourcing db may take a while, please wait..."
@cd base/db/peq-dump && sudo mariadb --database peq -e "source create_all_tables.sql"
@echo "MariaDB is now injected."
.PHONY: gm-%
gm-%:
sudo mariadb --database peq -e "UPDATE account SET status=255 WHERE name = '$*';"
@echo "Account $* is now a GM. /camp to have it go into effect."
depends:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile depends --no-print-directory
exit
endif
sudo apt install graphviz pip time
pip3 install graphviz
mkdir -p build/depends
@if [ ! -f "build/depends/dependency_graph.py" ]; then \
wget https://raw.githubusercontent.com/pvigier/dependency-graph/master/dependency_graph.py -O build/depends/dependency_graph.py; \
fi
@echo "Generating dependency graphs (This may take a while)..."
@echo "Login..."
time python3 build/depends/dependency_graph.py -f png login build/depends/login.dot
@echo "World..."
time python3 build/depends/dependency_graph.py -f png world build/depends/world.dot
@echo "Zone..."
time python3 build/depends/dependency_graph.py -f png zone build/depends/zone.dot
@echo "Common..."
time python3 build/depends/dependency_graph.py -f png common build/depends/common.dot
backup:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile backup --no-print-directory
exit
endif
@mkdir -p build/bin/backup
cd build/bin && ./world database:dump --compress --player-tables --state-tables --system-tables --query-serv-tables
cpu-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile cpu-zone --no-print-directory
exit
endif
@cd build/bin && mkdir -p tmp
cd build/bin && CPUPROFILE=prof.out ./zone
pprof-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-zone --no-print-directory
exit
endif
cd build/bin && google-pprof --pdf zone prof.out > prof.pdf
pprof-web-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-web-zone --no-print-directory
exit
endif
cd build/bin && google-pprof --web zone prof.out
pprof-gv-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-gv-zone --no-print-directory
exit
endif
cd build/bin && google-pprof --gv zone prof.out > prof.gv
heap-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile heap-zone --no-print-directory
exit
endif
@cd build/bin && mkdir -p tmp
cd build/bin && HEAPPROFILE=prof.out ./zone
-73
View File
@@ -1,73 +0,0 @@
{
"server": {
"zones": {
"defaultstatus": "0",
"ports": {
"low": "7000",
"high": "7400"
}
},
"qsdatabase": {
"host": "127.0.0.1",
"port": "3306",
"username": "peq",
"password": "peqpass",
"db": "peq"
},
"chatserver": {
"port": "7778",
"host": ""
},
"mailserver": {
"host": "",
"port": "7778"
},
"webinterface": {
"port": "9081"
},
"world": {
"longname": "New Devbox",
"address": "192.168.1.100",
"localaddress": "192.168.1.100",
"loginserver1": {
"account": "",
"password": "",
"legacy": 0,
"host": "login.projecteq.net",
"port": "5998"
},
"tcp": {
"ip": "127.0.0.1",
"port": "9001"
},
"telnet": {
"ip": "0.0.0.0",
"port": "9000",
"enabled": "true"
},
"key": "random-generate-here",
"http": {
"port": "9080",
"enabled": "true",
"mimefile": "mime.types"
},
"shortname": "dev"
},
"database": {
"db": "peq",
"host": "127.0.0.1",
"port": "3306",
"username": "peq",
"password": "peqpass"
},
"files": {
"opcodes": "assets/patches/opcodes.conf",
"mail_opcodes": "assets/patches/mail_opcodes.conf"
},
"directories": {
"patches": "assets/patches/",
"opcodes": "assets/patches/",
"plugins": "quests/plugins/"
}
}
}
-37
View File
@@ -1,37 +0,0 @@
{
"database": {
"host": "127.0.0.1",
"port": "3306",
"db": "peq",
"user": "peq",
"password": "peqpass"
},
"account": {
"auto_create_accounts": true
},
"worldservers": {
"unregistered_allowed": true,
"reject_duplicate_servers": false
},
"web_api": {
"enabled": true,
"port": 6000
},
"security": {
"mode": 14,
"allow_password_login": true,
"allow_token_login": true
},
"logging": {
"trace": false,
"world_trace": false,
"dump_packets_in": false,
"dump_packets_out": false
},
"client_configuration": {
"titanium_port": 5998,
"titanium_opcodes": "assets/patches/login_opcodes.conf",
"sod_port": 5999,
"sod_opcodes": "assets/patches/login_opcodes_sod.conf"
}
}
-49
View File
@@ -1,49 +0,0 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
{
"name": "eqemu",
"build": {
"dockerfile": "Dockerfile.debian.dev"
},
"appPort": [
"5998:5998/udp",
"7000:7000/udp",
"7001:7001/udp",
"7002:7002/udp",
"7003:7003/udp",
"7004:7004/udp",
"7005:7005/udp",
"9000:9000/udp",
"9001:9001/udp"
],
"forwardPorts": [
3306
],
"remoteEnv": {
"LOCALWSF": "${localWorkspaceFolder}",
"CONTAINERWSF": "${containerWorkspaceFolder}"
},
"containerUser": "vscode",
// add ptrace
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools-extension-pack",
"vilicvane.sensitive-replace",
"maattdd.gitless",
"bibhasdn.unique-lines",
"GitHub.copilot",
"xackery.make-magic",
"Gruntfuggly.todo-tree",
"ms-vscode.cmake-tools"
]
}
},
"workspaceFolder": "/src",
"workspaceMount": "source=${localWorkspaceFolder},target=/src,type=bind,consistency=cached"
}
+3 -1
View File
@@ -61,6 +61,9 @@ bin/
compile_flags.txt
.cache/
# vscode generated settings
.vscode/
# Build pipeline
!utils/scripts/build/
!utils/scripts/build/should-release/should-release
@@ -68,4 +71,3 @@ compile_flags.txt
# CMake Files
cmake-build-relwithdebinfo/*
skill-caps.diff
-23
View File
@@ -1,23 +0,0 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${default}",
"${workspaceFolder}/submodules/fmt/include",
"${workspaceFolder}/submodules/cereal/include",
"${workspaceFolder}/submodules/glm",
"${workspaceFolder}/submodules/libuv/include"
],
"defines": [
"LUA_EQEMU=1"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
-173
View File
@@ -1,173 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) attach",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/build/bin/world",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) shared_memory",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/shared_memory",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) world",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/world",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) zone",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/zone",
"cwd": "${workspaceFolder}/build/bin",
"args": [
"",
],
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) zone neriakb",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/zone",
"cwd": "${workspaceFolder}/build/bin",
"args": [
"neriakb",
],
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) login",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/loginserver",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) ucs",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/ucs",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) queryserv",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/queryserv",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
-136
View File
@@ -1,136 +0,0 @@
{
"editor.detectIndentation": false,
"editor.insertSpaces": false,
"editor.tabSize": 4,
"editor.autoIndent": "full",
"editor.trimAutoWhitespace": true,
"files.trimTrailingWhitespace": true,
//"editor.formatOnSave": true,
"search.exclude": {
"dependencies": false,
},
"C_Cpp.default.includePath": [
"/usr/include/x86_64-linux-gnu",
"/usr/include/lua5.2",
"/usr/include/mariadb",
"${workspaceFolder}/dependencies/curl_x64/include",
"${workspaceFolder}/dependencies/fmt/include",
"${workspaceFolder}/dependencies/glm",
"${workspaceFolder}/dependencies/libuv/include",
"${workspaceFolder}/dependencies/sol2",
"${workspaceFolder}/dependencies/zlibng"
],
"telemetry.enableTelemetry": false,
"cmake.buildDirectory": "${workspaceFolder}/build",
"cmake.configureArgs": [
"-DEQEMU_BUILD_LOGIN=ON",
"-DEQEMU_BUILD_TESTS=ON",
"-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",
"-DEQEMU_ADD_PROFILER=ON",
"Ninja"
],
"cmake.skipConfigureIfCachePresent": true,
"cmake.configureOnOpen": false,
"files.associations": {
"*.ipp": "cpp",
"functional": "cpp",
"string": "cpp",
"iostream": "cpp",
"map": "cpp",
"fstream": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"cstring": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"strstream": "cpp",
"bit": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"coroutine": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"list": "cpp",
"set": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"source_location": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"semaphore": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cfenv": "cpp",
"cinttypes": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"csetjmp": "cpp",
"charconv": "cpp",
"format": "cpp",
"ranges": "cpp",
"span": "cpp"
},
"cmake.statusbar.advanced": {
"kit": {
"visibility": "hidden",
},
"debug": {
"visibility": "hidden",
},
"buildTarget": {
"visibility": "hidden",
},
"launch": {
"visibility": "hidden",
},
"ctest": {
"visibility": "icon",
}
}
}
+13 -1536
View File
File diff suppressed because it is too large Load Diff
-10
View File
@@ -31,16 +31,6 @@ IF (EQEMU_BUILD_STATIC)
ENDIF ()
ENDIF (EQEMU_BUILD_STATIC)
# Requires libgoogle-perftools-dev google-perftools packages for linux (debian)
IF(EQEMU_ADD_PROFILER)
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed")
ENDIF(EQEMU_ADD_PROFILER)
IF(USE_MAP_MMFS)
ADD_DEFINITIONS(-DUSE_MAP_MMFS)
ENDIF (USE_MAP_MMFS)
IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-DNOMINMAX)
+154 -54
View File
@@ -29,21 +29,11 @@
#include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
#include "../../common/repositories/base_data_repository.h"
#include "../../common/repositories/db_str_repository.h"
#include "../../common/repositories/skill_caps_repository.h"
#include "../../common/repositories/spells_new_repository.h"
#include "../../common/file.h"
#include "../../common/events/player_event_logs.h"
#include "../../common/skill_caps.h"
#include "../../common/evolving_items.h"
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
PlayerEventLogs player_event_logs;
EvolvingItemsManager evolving_items_manager;
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ExportSpells(SharedDatabase *db);
void ExportSkillCaps(SharedDatabase *db);
@@ -104,22 +94,25 @@ int main(int argc, char **argv)
->LoadLogDatabaseSettings()
->StartFileLogs();
std::string export_type;
std::string arg_1;
if (argv[1]) {
export_type = argv[1];
arg_1 = argv[1];
}
if (Strings::EqualFold(export_type, "spells")) {
if (arg_1 == "spells") {
ExportSpells(&content_db);
return 0;
} else if (Strings::EqualFold(export_type, "skills")) {
}
if (arg_1 == "skills") {
ExportSkillCaps(&content_db);
return 0;
} else if (Strings::EqualFold(export_type, "basedata") || Strings::EqualFold(export_type, "base_data")) {
}
if (arg_1 == "basedata") {
ExportBaseData(&content_db);
return 0;
} else if (Strings::EqualFold(export_type, "dbstr") || Strings::EqualFold(export_type, "dbstring")) {
}
if (arg_1 == "dbstring") {
ExportDBStrings(&database);
return 0;
}
@@ -134,79 +127,186 @@ int main(int argc, char **argv)
return 0;
}
void ExportSpells(SharedDatabase* db)
void ExportSpells(SharedDatabase *db)
{
std::ofstream file(fmt::format("{}/export/spells_us.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
LogInfo("Exporting Spells");
std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/spells_us.txt to write, skipping.");
return;
}
const auto& lines = SpellsNewRepository::GetSpellFileLines(*db);
const std::string query = "SELECT * FROM spells_new ORDER BY id";
auto results = db->QueryDatabase(query);
const std::string& file_string = Strings::Implode("\n", lines);
if (results.Success()) {
for (auto row = results.begin(); row != results.end(); ++row) {
std::string line;
unsigned int fields = results.ColumnCount();
for (unsigned int i = 0; i < fields; ++i) {
if (i != 0) {
line.push_back('^');
}
file << file_string;
if (row[i] != nullptr) {
line += row[i];
}
}
file.close();
fprintf(f, "%s\n", line.c_str());
}
}
else {
}
LogInfo("Exported [{}] Spell{}", lines.size(), lines.size() != 1 ? "s" : "");
fclose(f);
}
void ExportSkillCaps(SharedDatabase* db)
bool SkillUsable(SharedDatabase *db, int skill_id, int class_id)
{
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
bool res = false;
std::string query = StringFormat(
"SELECT max(cap) FROM skill_caps WHERE class=%d AND skillID=%d",
class_id, skill_id
);
auto results = db->QueryDatabase(query);
if (!results.Success()) {
return false;
}
if (results.RowCount() == 0) {
return false;
}
auto row = results.begin();
if (row[0] && Strings::ToInt(row[0]) > 0) {
return true;
}
return false;
}
int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level)
{
std::string query = StringFormat(
"SELECT cap FROM skill_caps WHERE class=%d AND skillID=%d AND level=%d",
class_id, skill_id, level
);
auto results = db->QueryDatabase(query);
if (!results.Success()) {
return 0;
}
if (results.RowCount() == 0) {
return 0;
}
auto row = results.begin();
return Strings::ToInt(row[0]);
}
void ExportSkillCaps(SharedDatabase *db)
{
LogInfo("Exporting Skill Caps");
std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
return;
}
const auto& lines = SkillCapsRepository::GetSkillCapFileLines(*db);
for (int cl = 1; cl <= 16; ++cl) {
for (int skill = 0; skill <= 77; ++skill) {
if (SkillUsable(db, skill, cl)) {
int previous_cap = 0;
for (int level = 1; level <= 100; ++level) {
int cap = GetSkill(db, skill, cl, level);
if (cap < previous_cap) {
cap = previous_cap;
}
const std::string& file_string = Strings::Implode("\n", lines);
fprintf(f, "%d^%d^%d^%d^0\n", cl, skill, level, cap);
previous_cap = cap;
}
}
}
}
file << file_string;
file.close();
LogInfo("Exported [{}] Skill Cap{}", lines.size(), lines.size() != 1 ? "s" : "");
fclose(f);
}
void ExportBaseData(SharedDatabase *db)
{
std::ofstream file(fmt::format("{}/export/BaseData.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
LogInfo("Exporting Base Data");
std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/BaseData.txt to write, skipping.");
return;
}
const auto& lines = BaseDataRepository::GetBaseDataFileLines(*db);
const std::string query = "SELECT * FROM base_data ORDER BY level, class";
auto results = db->QueryDatabase(query);
if (results.Success()) {
for (auto row = results.begin(); row != results.end(); ++row) {
std::string line;
unsigned int fields = results.ColumnCount();
for (unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
if (rowIndex != 0) {
line.push_back('^');
}
const std::string& file_string = Strings::Implode("\n", lines);
if (row[rowIndex] != nullptr) {
line += row[rowIndex];
}
}
file << file_string;
fprintf(f, "%s\n", line.c_str());
}
}
file.close();
LogInfo("Exported [{}] Base Data Entr{}", lines.size(), lines.size() != 1 ? "ies" : "y");
fclose(f);
}
void ExportDBStrings(SharedDatabase *db)
{
std::ofstream file(fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
LogInfo("Exporting DB Strings");
std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
return;
}
const auto& lines = DbStrRepository::GetDBStrFileLines(*db);
fprintf(f, "Major^Minor^String(New)\n");
const std::string query = "SELECT * FROM db_str ORDER BY id, type";
auto results = db->QueryDatabase(query);
if (results.Success()) {
for (auto row = results.begin(); row != results.end(); ++row) {
std::string line;
unsigned int fields = results.ColumnCount();
for (unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
if (rowIndex != 0) {
line.push_back('^');
}
const std::string& file_string = Strings::Implode("\n", lines);
if (row[rowIndex] != nullptr) {
line += row[rowIndex];
}
}
file << file_string;
fprintf(f, "%s\n", line.c_str());
}
}
file.close();
LogInfo("Exported [{}] Database String{}", lines.size(), lines.size() != 1 ? "s" : "");
fclose(f);
}
+4 -8
View File
@@ -29,15 +29,11 @@
#include "../../common/path_manager.h"
#include "../../common/repositories/base_data_repository.h"
#include "../../common/file.h"
#include "../../common/events/player_event_logs.h"
#include "../../common/evolving_items.h"
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
PlayerEventLogs player_event_logs;
EvolvingItemsManager evolving_items_manager;
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
void ImportSpells(SharedDatabase *db);
void ImportSkillCaps(SharedDatabase *db);
+16 -60
View File
@@ -2,8 +2,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
SET(common_sources
base_packet.cpp
bazaar.cpp
bodytypes.cpp
classes.cpp
cli/eqemu_command_handler.cpp
compression.cpp
@@ -22,7 +20,6 @@ SET(common_sources
dbcore.cpp
deity.cpp
dynamic_zone_base.cpp
dynamic_zone_lockout.cpp
emu_constants.cpp
emu_limits.cpp
emu_opcodes.cpp
@@ -40,7 +37,7 @@ SET(common_sources
event_sub.cpp
events/player_event_logs.cpp
events/player_event_discord_formatter.cpp
evolving_items.cpp
expedition_lockout_timer.cpp
extprofile.cpp
discord/discord_manager.cpp
faction.cpp
@@ -63,7 +60,6 @@ SET(common_sources
mutex.cpp
mysql_request_result.cpp
mysql_request_row.cpp
mysql_stmt.cpp
opcode_map.cpp
opcodemgr.cpp
packet_dump.cpp
@@ -87,9 +83,7 @@ SET(common_sources
shared_tasks.cpp
shareddb.cpp
skills.cpp
skill_caps.cpp
spdat.cpp
spdat_bot.cpp
strings.cpp
struct_strategy.cpp
textures.cpp
@@ -99,7 +93,6 @@ SET(common_sources
json/json.hpp
json/jsoncpp.cpp
zone_store.cpp
memory/ksm.hpp
net/console_server.cpp
net/console_server_connection.cpp
net/crc32.cpp
@@ -162,7 +155,6 @@ SET(repositories
repositories/base/base_bugs_repository.h
repositories/base/base_bug_reports_repository.h
repositories/base/base_buyer_repository.h
repositories/base/base_buyer_trade_items_repository.h
repositories/base/base_character_activities_repository.h
repositories/base/base_character_alternate_abilities_repository.h
repositories/base/base_character_alt_currency_repository.h
@@ -175,7 +167,6 @@ SET(repositories
repositories/base/base_character_currency_repository.h
repositories/base/base_character_data_repository.h
repositories/base/base_character_disciplines_repository.h
repositories/base/base_character_evolving_items_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
@@ -185,8 +176,6 @@ SET(repositories
repositories/base/base_character_leadership_abilities_repository.h
repositories/base/base_character_material_repository.h
repositories/base/base_character_memmed_spells_repository.h
repositories/base/base_character_parcels_repository.h
repositories/base/base_character_parcels_containers_repository.h
repositories/base/base_character_peqzone_flags_repository.h
repositories/base/base_character_pet_buffs_repository.h
repositories/base/base_character_pet_info_repository.h
@@ -213,9 +202,10 @@ SET(repositories
repositories/base/base_discovered_items_repository.h
repositories/base/base_doors_repository.h
repositories/base/base_dynamic_zones_repository.h
repositories/base/base_dynamic_zone_lockouts_repository.h
repositories/base/base_dynamic_zone_members_repository.h
repositories/base/base_dynamic_zone_templates_repository.h
repositories/base/base_expeditions_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_list_repository.h
@@ -243,7 +233,6 @@ SET(repositories
repositories/base/base_inventory_snapshots_repository.h
repositories/base/base_ip_exemptions_repository.h
repositories/base/base_items_repository.h
repositories/base/base_items_evolving_details_repository.h
repositories/base/base_ldon_trap_entries_repository.h
repositories/base/base_ldon_trap_templates_repository.h
repositories/base/base_level_exp_mods_repository.h
@@ -281,20 +270,8 @@ SET(repositories
repositories/base/base_pets_equipmentset_repository.h
repositories/base/base_pets_equipmentset_entries_repository.h
repositories/base/base_player_titlesets_repository.h
repositories/base/base_player_event_aa_purchase_repository.h
repositories/base/base_player_event_killed_npc_repository.h
repositories/base/base_player_event_killed_named_npc_repository.h
repositories/base/base_player_event_killed_raid_npc_repository.h
repositories/base/base_player_event_log_settings_repository.h
repositories/base/base_player_event_logs_repository.h
repositories/base/base_player_event_loot_items_repository.h
repositories/base/base_player_event_merchant_purchase_repository.h
repositories/base/base_player_event_merchant_sell_repository.h
repositories/base/base_player_event_npc_handin_repository.h
repositories/base/base_player_event_npc_handin_entries_repository.h
repositories/base/base_player_event_speech_repository.h
repositories/base/base_player_event_trade_repository.h
repositories/base/base_player_event_trade_entries_repository.h
repositories/base/base_quest_globals_repository.h
repositories/base/base_raid_details_repository.h
repositories/base/base_raid_members_repository.h
@@ -357,8 +334,7 @@ SET(repositories
repositories/books_repository.h
repositories/bugs_repository.h
repositories/bug_reports_repository.h
repositories/buyer_buy_lines_repository.h
repositories/buyer_trade_items_repository.h
repositories/buyer_repository.h
repositories/character_activities_repository.h
repositories/character_alternate_abilities_repository.h
repositories/character_alt_currency_repository.h
@@ -371,7 +347,6 @@ SET(repositories
repositories/character_currency_repository.h
repositories/character_data_repository.h
repositories/character_disciplines_repository.h
repositories/character_evolving_items_repository.h
repositories/character_expedition_lockouts_repository.h
repositories/character_exp_modifiers_repository.h
repositories/character_inspect_messages_repository.h
@@ -381,8 +356,6 @@ SET(repositories
repositories/character_leadership_abilities_repository.h
repositories/character_material_repository.h
repositories/character_memmed_spells_repository.h
repositories/character_parcels_repository.h
repositories/character_parcels_containers_repository.h
repositories/character_peqzone_flags_repository.h
repositories/character_pet_buffs_repository.h
repositories/character_pet_info_repository.h
@@ -409,9 +382,10 @@ SET(repositories
repositories/discovered_items_repository.h
repositories/doors_repository.h
repositories/dynamic_zones_repository.h
repositories/dynamic_zone_lockouts_repository.h
repositories/dynamic_zone_members_repository.h
repositories/dynamic_zone_templates_repository.h
repositories/expeditions_repository.h
repositories/expedition_lockouts_repository.h
repositories/faction_association_repository.h
repositories/faction_base_data_repository.h
repositories/faction_list_repository.h
@@ -439,7 +413,6 @@ SET(repositories
repositories/inventory_snapshots_repository.h
repositories/ip_exemptions_repository.h
repositories/items_repository.h
repositories/items_evolving_details_repository.h
repositories/ldon_trap_entries_repository.h
repositories/ldon_trap_templates_repository.h
repositories/level_exp_mods_repository.h
@@ -477,20 +450,8 @@ SET(repositories
repositories/pets_equipmentset_repository.h
repositories/pets_equipmentset_entries_repository.h
repositories/player_titlesets_repository.h
repositories/player_event_aa_purchase_repository.h
repositories/player_event_killed_npc_repository.h
repositories/player_event_killed_named_npc_repository.h
repositories/player_event_killed_raid_npc_repository.h
repositories/player_event_log_settings_repository.h
repositories/player_event_logs_repository.h
repositories/player_event_loot_items_repository.h
repositories/player_event_merchant_purchase_repository.h
repositories/player_event_merchant_sell_repository.h
repositories/player_event_npc_handin_repository.h
repositories/player_event_npc_handin_entries_repository.h
repositories/player_event_speech_repository.h
repositories/player_event_trade_repository.h
repositories/player_event_trade_entries_repository.h
repositories/quest_globals_repository.h
repositories/raid_details_repository.h
repositories/raid_members_repository.h
@@ -531,11 +492,10 @@ SET(repositories
repositories/zone_repository.h
repositories/zone_points_repository.h
)
)
SET(common_headers
additive_lagged_fibonacci_engine.h
bazaar.h
base_packet.h
bodytypes.h
classes.h
@@ -559,7 +519,6 @@ SET(common_headers
discord/discord.h
discord/discord_manager.h
dynamic_zone_base.h
dynamic_zone_lockout.h
emu_constants.h
emu_limits.h
emu_opcodes.h
@@ -585,7 +544,7 @@ SET(common_headers
events/player_event_discord_formatter.h
events/player_events.h
event_sub.h
evolving_items.h
expedition_lockout_timer.h
extprofile.h
faction.h
file.h
@@ -617,7 +576,6 @@ SET(common_headers
mutex.h
mysql_request_result.h
mysql_request_row.h
mysql_stmt.h
op_codes.h
opcode_dispatch.h
opcodemgr.h
@@ -634,7 +592,7 @@ SET(common_headers
ptimer.h
queue.h
races.h
raid.h
raid.h
random.h
rdtsc.h
rulesys.h
@@ -645,11 +603,9 @@ SET(common_headers
server_event_scheduler.h
serverinfo.h
servertalk.h
server_reload_types.h
shared_tasks.h
shareddb.h
skills.h
skill_caps.h
spdat.h
strings.h
struct_strategy.h
@@ -725,13 +681,13 @@ SOURCE_GROUP(Event FILES
event/event_loop.h
event/timer.h
event/task.h
)
)
SOURCE_GROUP(Json FILES
json/json.h
json/jsoncpp.cpp
json/json-forwards.h
)
)
SOURCE_GROUP(Net FILES
net/console_server.cpp
@@ -768,7 +724,7 @@ SOURCE_GROUP(Net FILES
net/websocket_server.h
net/websocket_server_connection.cpp
net/websocket_server_connection.h
)
)
SOURCE_GROUP(Patches FILES
patches/patches.h
@@ -812,12 +768,12 @@ SOURCE_GROUP(Patches FILES
patches/titanium_limits.cpp
patches/uf.cpp
patches/uf_limits.cpp
)
)
SOURCE_GROUP(StackWalker FILES
StackWalker/StackWalker.h
StackWalker/StackWalker.cpp
)
)
SOURCE_GROUP(Util FILES
util/memory_stream.h
@@ -825,7 +781,7 @@ SOURCE_GROUP(Util FILES
util/directory.h
util/uuid.cpp
util/uuid.h
)
)
INCLUDE_DIRECTORIES(Patches SocketLib StackWalker)
@@ -838,6 +794,6 @@ ENDIF (UNIX)
IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
ENDIF ()
ENDIF()
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
-333
View File
@@ -1,333 +0,0 @@
#include "bazaar.h"
#include "../../common/item_instance.h"
#include "repositories/trader_repository.h"
#include <memory>
std::vector<BazaarSearchResultsFromDB_Struct>
Bazaar::GetSearchResults(
Database &db,
Database &content_db,
BazaarSearchCriteria_Struct search,
uint32 char_zone_id,
int32 char_zone_instance_id
)
{
LogTrading(
"Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] "
"max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] "
"search_scope [{}] char_zone_id [{}], char_zone_instance_id [{}]",
search.item_name,
search.min_cost,
search.max_cost,
search.min_level,
search.max_level,
search.max_results,
search.prestige,
search.augment,
search.trader_entity_id,
search.trader_id,
search.search_scope,
char_zone_id,
char_zone_instance_id
);
static std::map<uint8, uint32> item_slot_searches_new = {
{EQ::invslot::slotCharm, 1},
{EQ::invslot::slotEar1, 2},
{EQ::invslot::slotHead, 4},
{EQ::invslot::slotFace, 8},
{EQ::invslot::slotEar2, 16},
{EQ::invslot::slotNeck, 32},
{EQ::invslot::slotShoulders, 64},
{EQ::invslot::slotArms, 128},
{EQ::invslot::slotBack, 256},
{EQ::invslot::slotWrist1, 512},
{EQ::invslot::slotWrist2, 1024},
{EQ::invslot::slotRange, 2048},
{EQ::invslot::slotHands, 4096},
{EQ::invslot::slotPrimary, 8192},
{EQ::invslot::slotSecondary, 16384},
{EQ::invslot::slotFinger1, 32768},
{EQ::invslot::slotFinger2, 65536},
{EQ::invslot::slotChest, 131072},
{EQ::invslot::slotLegs, 262144},
{EQ::invslot::slotFeet, 524288},
{EQ::invslot::slotWaist, 1048576},
{EQ::invslot::slotPowerSource, 2097152},
{EQ::invslot::slotAmmo, 4194304},
};
struct ItemSearchType {
EQ::item::ItemType type;
std::string condition;
};
std::vector<ItemSearchType> item_search_types_new = {
{EQ::item::ItemType::ItemTypeBook, " AND (items.itemclass = 2 or items.itemclass = 31)"},
{EQ::item::ItemType::ItemTypeContainer, " AND (items.itemclass = 1 or items.itemclass = 67)"},
{EQ::item::ItemType::ItemTypeAllEffects, " AND (items.scrolleffect > 0 && items.scrolleffect < 65000)"},
{EQ::item::ItemType::ItemTypeUnknown9, " AND items.worneffect = 998"},
{EQ::item::ItemType::ItemTypeUnknown10, " AND (items.worneffect >= 1298 && items.worneffect <= 1307)"},
{EQ::item::ItemType::ItemTypeFocusEffect, " AND items.focuseffect > 0"},
{EQ::item::ItemType::ItemTypeArmor, " AND items.itemtype = 10"},
{EQ::item::ItemType::ItemType1HBlunt, " AND items.itemtype = 3"},
{EQ::item::ItemType::ItemType1HPiercing, " AND items.itemtype = 2"},
{EQ::item::ItemType::ItemType1HSlash, " AND items.itemtype = 0"},
{EQ::item::ItemType::ItemType2HBlunt, " AND items.itemtype = 4"},
{EQ::item::ItemType::ItemType2HSlash, " AND items.itemtype = 1"},
{EQ::item::ItemType::ItemTypeBow, " AND items.itemtype = 5"},
{EQ::item::ItemType::ItemTypeShield, " AND items.itemtype = 8"},
{EQ::item::ItemType::ItemTypeMisc, " AND items.itemtype = 11"},
{EQ::item::ItemType::ItemTypeFood, " AND items.itemtype = 14"},
{EQ::item::ItemType::ItemTypeDrink, " AND items.itemtype = 15"},
{EQ::item::ItemType::ItemTypeLight, " AND items.itemtype = 16"},
{EQ::item::ItemType::ItemTypeCombinable, " AND items.itemtype = 17"},
{EQ::item::ItemType::ItemTypeBandage, " AND items.itemtype = 18"},
{EQ::item::ItemType::ItemTypeSmallThrowing, " AND (items.itemtype = 19 OR items.itemtype = 7)"},
{EQ::item::ItemType::ItemTypeSpell, " AND items.itemtype = 20"},
{EQ::item::ItemType::ItemTypePotion, " AND items.itemtype = 21"},
{EQ::item::ItemType::ItemTypeBrassInstrument, " AND items.itemtype = 25"},
{EQ::item::ItemType::ItemTypeWindInstrument, " AND items.itemtype = 23"},
{EQ::item::ItemType::ItemTypeStringedInstrument, " AND items.itemtype = 24"},
{EQ::item::ItemType::ItemTypePercussionInstrument, " AND items.itemtype = 26"},
{EQ::item::ItemType::ItemTypeArrow, " AND items.itemtype = 27"},
{EQ::item::ItemType::ItemTypeJewelry, " AND items.itemtype = 29"},
{EQ::item::ItemType::ItemTypeNote, " AND items.itemtype = 32"},
{EQ::item::ItemType::ItemTypeKey, " AND items.itemtype = 33"},
{EQ::item::ItemType::ItemType2HPiercing, " AND items.itemtype = 35"},
{EQ::item::ItemType::ItemTypeAlcohol, " AND items.itemtype = 38"},
{EQ::item::ItemType::ItemTypeMartial, " AND items.itemtype = 45"},
{EQ::item::ItemType::ItemTypeAugmentation, " AND items.itemtype = 54"},
{EQ::item::ItemType::ItemTypeAlternateAbility, " AND items.itemtype = 57"},
{EQ::item::ItemType::ItemTypeCount, " AND items.itemtype = 65"},
{EQ::item::ItemType::ItemTypeCollectible, " AND items.itemtype = 66"}
};
// item stat searches
struct ItemStatSearch {
std::string query_string;
EQ::skills::SkillType skill_type;
};
std::map<uint32, ItemStatSearch> item_stat_searches_new = {
{STAT_AC, {" items.ac" , static_cast<EQ::skills::SkillType>(0)} },
{STAT_AGI, {" items.aagi", static_cast<EQ::skills::SkillType>(0)} },
{STAT_CHA, {" items.acha", static_cast<EQ::skills::SkillType>(0)} },
{STAT_DEX, {" items.adex", static_cast<EQ::skills::SkillType>(0)} },
{STAT_INT, {" items.aint", static_cast<EQ::skills::SkillType>(0)} },
{STAT_STA, {" items.asta", static_cast<EQ::skills::SkillType>(0)} },
{STAT_STR, {" items.astr", static_cast<EQ::skills::SkillType>(0)} },
{STAT_WIS, {" items.awis", static_cast<EQ::skills::SkillType>(0)} },
{STAT_COLD, {" items.cr", static_cast<EQ::skills::SkillType>(0)} },
{STAT_DISEASE, {" items.dr", static_cast<EQ::skills::SkillType>(0)} },
{STAT_FIRE, {" items.fr", static_cast<EQ::skills::SkillType>(0)} },
{STAT_MAGIC, {" items.mr", static_cast<EQ::skills::SkillType>(0)} },
{STAT_POISON, {" items.pr", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HP, {" items.hp", static_cast<EQ::skills::SkillType>(0)} },
{STAT_MANA, {" items.mana", static_cast<EQ::skills::SkillType>(0)} },
{STAT_ENDURANCE, {" items.endur", static_cast<EQ::skills::SkillType>(0)} },
{STAT_ATTACK, {" items.attack", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HP_REGEN, {" items.regen", static_cast<EQ::skills::SkillType>(0)} },
{STAT_MANA_REGEN, {" items.manaregen", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HASTE, {" items.haste", static_cast<EQ::skills::SkillType>(0)} },
{STAT_DAMAGE_SHIELD, {" items.damageshield", static_cast<EQ::skills::SkillType>(0)} },
{STAT_DS_MITIGATION, {" items.dsmitigation", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEAL_AMOUNT, {" items.healamt", static_cast<EQ::skills::SkillType>(0)} },
{STAT_SPELL_DAMAGE, {" items.spelldmg", static_cast<EQ::skills::SkillType>(0)} },
{STAT_CLAIRVOYANCE, {" items.clairvoyance", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEROIC_AGILITY, {" items.heroic_agi", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEROIC_CHARISMA, {" items.heroic_cha", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEROIC_DEXTERITY, {" items.heroic_dex", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEROIC_INTELLIGENCE, {" items.heroic_int", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEROIC_STAMINA, {" items.heroic_sta", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEROIC_STRENGTH, {" items.heroic_str", static_cast<EQ::skills::SkillType>(0)} },
{STAT_HEROIC_WISDOM, {" items.heroic_wis", static_cast<EQ::skills::SkillType>(0)} },
{STAT_BASH, {" items.skillmodvalue", EQ::skills::SkillBash} },
{STAT_BACKSTAB, {" items.backstabdmg", EQ::skills::SkillBackstab} },
{STAT_DRAGON_PUNCH, {" items.skillmodvalue", EQ::skills::SkillDragonPunch} },
{STAT_EAGLE_STRIKE, {" items.skillmodvalue", EQ::skills::SkillEagleStrike} },
{STAT_FLYING_KICK, {" items.skillmodvalue", EQ::skills::SkillFlyingKick} },
{STAT_KICK, {" items.skillmodvalue", EQ::skills::SkillKick} },
{STAT_ROUND_KICK, {" items.skillmodvalue", EQ::skills::SkillRoundKick} },
{STAT_TIGER_CLAW, {" items.skillmodvalue", EQ::skills::SkillTigerClaw} },
{STAT_FRENZY, {" items.skillmodvalue", EQ::skills::SkillFrenzy} },
};
bool convert = false;
std::string search_criteria_trader("TRUE");
std::string field_criteria_items("FALSE");
std::string where_criteria_items(" TRUE ");
if (search.search_scope == NonRoFBazaarSearchScope) {
search_criteria_trader.append(
fmt::format(
" AND trader.char_entity_id = {} AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
search.trader_entity_id,
Zones::BAZAAR,
char_zone_instance_id
)
);
}
else if (search.search_scope == Local_Scope) {
search_criteria_trader.append(fmt::format(
" AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
char_zone_id,
char_zone_instance_id)
);
}
else if (search.trader_id > 0) {
if (RuleB(Bazaar, UseAlternateBazaarSearch)) {
if (search.trader_id >= TraderRepository::TRADER_CONVERT_ID) {
convert = true;
search_criteria_trader.append(fmt::format(
" AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}",
Zones::BAZAAR,
search.trader_id - TraderRepository::TRADER_CONVERT_ID)
);
}
else {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
}
}
else {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
}
}
if (search.min_cost != 0) {
search_criteria_trader.append(fmt::format(" AND trader.item_cost >= {}", search.min_cost * 1000));
}
if (search.max_cost != 0) {
search_criteria_trader.append(fmt::format(" AND trader.item_cost <= {}", (uint64) search.max_cost * 1000));
}
if (search.slot != std::numeric_limits<uint32>::max()) {
if (item_slot_searches_new.contains(search.slot)) {
where_criteria_items.append(
fmt::format(" AND items.slots & {0} = {0}", item_slot_searches_new[search.slot]));
}
}
if (search.type != std::numeric_limits<uint32>::max()) {
for (auto const &[type, condition]: item_search_types_new) {
if (type == search.type) {
where_criteria_items.append(condition);
break;
}
}
}
if (search.race != std::numeric_limits<uint32>::max()) {
where_criteria_items.append(
fmt::format(" AND items.races & {0} = {0}", GetPlayerRaceBit(GetRaceIDFromPlayerRaceValue(search.race))));
}
if (search._class != std::numeric_limits<uint32>::max()) {
where_criteria_items.append(fmt::format(" AND items.classes & {0} = {0}", GetPlayerClassBit(search._class)));
}
if (search.item_stat != std::numeric_limits<uint32>::max()) {
if (item_stat_searches_new.contains(search.item_stat)) {
field_criteria_items = fmt::format("{}", item_stat_searches_new[search.item_stat].query_string);
if (item_stat_searches_new[search.item_stat].skill_type) {
where_criteria_items.append(
fmt::format(" AND items.skillmodtype = {} ", item_stat_searches_new[search.item_stat].skill_type));
}
else {
where_criteria_items.append(
fmt::format(" AND {} > 0 ", item_stat_searches_new[search.item_stat].query_string));
}
}
}
if (search.augment) {
where_criteria_items.append(fmt::format(
" AND (items.augslot1type = {0} OR "
"items.augslot2type = {0} OR "
"items.augslot3type = {0} OR "
"items.augslot4type = {0} OR "
"items.augslot5type = {0} OR "
"items.augslot6type = {0})",
search.augment)
);
}
if (search.min_level != 1) {
where_criteria_items.append(fmt::format(" AND items.reclevel >= {}", search.min_level));
}
if (search.max_level != 100) {
where_criteria_items.append(fmt::format(" AND items.reclevel <= {}", search.max_level));
}
std::vector<BazaarSearchResultsFromDB_Struct> all_entries;
std::vector<std::string> trader_items_ids{};
auto const trader_results = TraderRepository::GetBazaarTraderDetails(db, search_criteria_trader);
if (trader_results.empty()) {
LogTradingDetail("Bazaar - No traders found in bazaar search.");
return all_entries;
}
for (auto const &i: trader_results) {
trader_items_ids.push_back(std::to_string(i.trader.item_id));
}
auto const item_results = ItemsRepository::GetItemsForBazaarSearch(
content_db,
trader_items_ids,
std::string(search.item_name),
field_criteria_items,
where_criteria_items
);
if (item_results.empty()) {
LogTradingDetail("Bazaar - No items found in bazaar search.");
return all_entries;
}
all_entries.reserve(trader_results.size());
for (auto const& t:trader_results) {
if (!item_results.contains(t.trader.item_id)) {
continue;
}
BazaarSearchResultsFromDB_Struct r{};
r.count = 1;
r.trader_id = t.trader.char_id;
r.serial_number = t.trader.item_sn;
r.cost = t.trader.item_cost;
r.slot_id = t.trader.slot_id;
r.charges = t.trader.item_charges;
r.stackable = item_results.at(t.trader.item_id).stackable;
r.icon_id = item_results.at(t.trader.item_id).icon;
r.trader_zone_id = t.trader.char_zone_id;
r.trader_zone_instance_id = t.trader.char_zone_instance_id;
r.trader_entity_id = t.trader.char_entity_id;
r.serial_number_RoF = fmt::format("{:016}\0", t.trader.item_sn);
r.item_name = fmt::format("{:.63}\0", item_results.at(t.trader.item_id).name);
r.trader_name = fmt::format("{:.63}\0", t.trader_name);
r.item_stat = item_results.at(t.trader.item_id).stats;
if (RuleB(Bazaar, UseAlternateBazaarSearch)) {
if (convert ||
char_zone_id != Zones::BAZAAR ||
(char_zone_id == Zones::BAZAAR && r.trader_zone_instance_id != char_zone_instance_id)
) {
r.trader_id = TraderRepository::TRADER_CONVERT_ID + r.trader_zone_instance_id;
}
}
all_entries.push_back(r);
}
if (all_entries.size() > search.max_results) {
all_entries.resize(search.max_results);
}
LogTrading("Returning [{}] items from search results", all_entries.size());
return all_entries;
}
-16
View File
@@ -1,16 +0,0 @@
#ifndef EQEMU_BAZAAR_H
#define EQEMU_BAZAAR_H
#include <vector>
#include "shareddb.h"
#include "../../common/item_instance.h"
class Bazaar {
public:
static std::vector<BazaarSearchResultsFromDB_Struct>
GetSearchResults(Database &content_db, Database &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id, int char_zone_instance_id);
};
#endif //EQEMU_BAZAAR_H
-12
View File
@@ -1,12 +0,0 @@
#include "../common/global_define.h"
#include "../common/bodytypes.h"
std::string BodyType::GetName(uint8 body_type_id)
{
return IsValid(body_type_id) ? body_type_names[body_type_id] : "UNKNOWN BODY TYPE";
}
bool BodyType::IsValid(uint8 body_type_id)
{
return body_type_names.find(body_type_id) != body_type_names.end();
}
+46 -90
View File
@@ -18,96 +18,52 @@
#ifndef BODYTYPES_H
#define BODYTYPES_H
#include "types.h"
#include <map>
#include <string>
typedef enum {
BT_Humanoid = 1,
BT_Lycanthrope = 2,
BT_Undead = 3,
BT_Giant = 4,
BT_Construct = 5,
BT_Extraplanar = 6,
BT_Magical = 7, //this name might be a bit off,
BT_SummonedUndead = 8,
BT_RaidGiant = 9, //Velious era Raid Giant
BT_RaidColdain = 10, //Velious era Raid Coldain
BT_NoTarget = 11, //no name, can't target this bodytype
BT_Vampire = 12,
BT_Atenha_Ra = 13,
BT_Greater_Akheva = 14,
BT_Khati_Sha = 15,
BT_Seru = 16,
BT_Grieg_Veneficus = 17,
BT_Draz_Nurakk = 18,
BT_Zek = 19, //"creatures from the Plane of War."
BT_Luggald = 20,
BT_Animal = 21,
BT_Insect = 22,
BT_Monster = 23,
BT_Summoned = 24, //Elemental?
BT_Plant = 25,
BT_Dragon = 26,
BT_Summoned2 = 27,
BT_Summoned3 = 28,
BT_Dragon2 = 29, //database data indicates this is a dragon type (kunark and DoN?)
BT_VeliousDragon = 30, //might not be a tight set
BT_Familiar = 31,
BT_Dragon3 = 32,
BT_Boxes = 33,
BT_Muramite = 34, //tribal dudes
// ...
BT_NoTarget2 = 60,
// ...
BT_SwarmPet = 63, //Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general.
BT_MonsterSummon = 64,
// 65, trap or effect related?
BT_InvisMan = 66, //no name, seen on 'InvisMan', can be /targeted
BT_Special = 67
} bodyType;
/* bodytypes above 64 make the mob not show up */
// body types above 64 make the mob invisible
namespace BodyType {
constexpr uint8 Humanoid = 1;
constexpr uint8 Lycanthrope = 2;
constexpr uint8 Undead = 3;
constexpr uint8 Giant = 4;
constexpr uint8 Construct = 5;
constexpr uint8 Extraplanar = 6;
constexpr uint8 Magical = 7; // this name might be a bit off,
constexpr uint8 SummonedUndead = 8;
constexpr uint8 RaidGiant = 9; // Velious era Raid Giant
constexpr uint8 RaidColdain = 10; // Velious era Raid Coldain
constexpr uint8 NoTarget = 11; // no name, can't target this bodytype
constexpr uint8 Vampire = 12;
constexpr uint8 AtenHaRa = 13;
constexpr uint8 GreaterAkheva = 14;
constexpr uint8 KhatiSha = 15;
constexpr uint8 Seru = 16;
constexpr uint8 GriegVeneficus = 17;
constexpr uint8 DrazNurakk = 18;
constexpr uint8 Zek = 19; //"creatures from the Plane of War."
constexpr uint8 Luggald = 20;
constexpr uint8 Animal = 21;
constexpr uint8 Insect = 22;
constexpr uint8 Monster = 23;
constexpr uint8 Summoned = 24; // Elemental?
constexpr uint8 Plant = 25;
constexpr uint8 Dragon = 26;
constexpr uint8 Summoned2 = 27;
constexpr uint8 Summoned3 = 28;
constexpr uint8 Dragon2 = 29; // database data indicates this is a dragon type (Kunark and DoN?)
constexpr uint8 VeliousDragon = 30; // might not be a tight set
constexpr uint8 Familiar = 31;
constexpr uint8 Dragon3 = 32;
constexpr uint8 Boxes = 33;
constexpr uint8 Muramite = 34; // tribal dudes
constexpr uint8 NoTarget2 = 60;
constexpr uint8 SwarmPet = 63; // Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general.
constexpr uint8 MonsterSummon = 64;
constexpr uint8 InvisibleMan = 66; // no name, seen on 'InvisMan', can be /targeted
constexpr uint8 Special = 67;
std::string GetName(uint8 body_type_id);
bool IsValid(uint8 body_type_id);
}
static std::map<uint8, std::string> body_type_names = {
{ BodyType::Humanoid, "Humanoid" },
{ BodyType::Lycanthrope, "Lycanthrope" },
{ BodyType::Undead, "Undead" },
{ BodyType::Giant, "Giant" },
{ BodyType::Construct, "Construct" },
{ BodyType::Extraplanar, "Extraplanar" },
{ BodyType::Magical, "Magical" },
{ BodyType::SummonedUndead, "Summoned Undead" },
{ BodyType::RaidGiant, "Raid Giant" },
{ BodyType::RaidColdain, "Raid Coldain" },
{ BodyType::NoTarget, "Untargetable" },
{ BodyType::Vampire, "Vampire" },
{ BodyType::AtenHaRa, "Aten Ha Ra" },
{ BodyType::GreaterAkheva, "Greater Akheva" },
{ BodyType::KhatiSha, "Khati Sha" },
{ BodyType::Seru, "Seru" },
{ BodyType::GriegVeneficus, "Grieg Veneficus" },
{ BodyType::DrazNurakk, "Draz Nurakk" },
{ BodyType::Zek, "Zek" },
{ BodyType::Luggald, "Luggald" },
{ BodyType::Animal, "Animal" },
{ BodyType::Insect, "Insect" },
{ BodyType::Monster, "Monster" },
{ BodyType::Summoned, "Summoned" },
{ BodyType::Plant, "Plant" },
{ BodyType::Dragon, "Dragon" },
{ BodyType::Summoned2, "Summoned 2" },
{ BodyType::Summoned3, "Summoned 3" },
{ BodyType::Dragon2, "Dragon 2" },
{ BodyType::VeliousDragon, "Velious Dragon" },
{ BodyType::Familiar, "Familiar" },
{ BodyType::Dragon3, "Dragon 3" },
{ BodyType::Boxes, "Boxes" },
{ BodyType::Muramite, "Muramite" },
{ BodyType::NoTarget2, "Untargetable 2" },
{ BodyType::SwarmPet, "Swarm Pet" },
{ BodyType::MonsterSummon, "Monster Summon" },
{ BodyType::InvisibleMan, "Invisible Man" },
{ BodyType::Special, "Special" },
};
constexpr int format_as(bodyType type) { return static_cast<int>(type); }
#endif
-2
View File
@@ -131,8 +131,6 @@ static std::map<uint8, std::string> class_names = {
#define ARMOR_TYPE_LAST ARMOR_TYPE_PLATE
#define ARMOR_TYPE_COUNT 5
#define BOT_CLASS_BASE_ID_PREFIX 3000
const char* GetClassIDName(uint8 class_id, uint8 level = 0);
+25 -134
View File
@@ -1,12 +1,28 @@
#include "world_content_service.h"
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <utility>
#include <glm/vec3.hpp>
#include "world_content_service.h"
#include "../database.h"
#include "../rulesys.h"
#include "../eqemu_logsys.h"
#include "../repositories/instance_list_repository.h"
#include "../zone_store.h"
#include "../repositories/content_flags_repository.h"
WorldContentService::WorldContentService()
@@ -103,7 +119,7 @@ std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
/**
* @param content_flags
*/
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags> &content_flags)
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags)
{
WorldContentService::content_flags = content_flags;
}
@@ -151,14 +167,14 @@ bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f)
}
// if we don't have any enabled flag in enabled flags, we fail
for (const auto &flag: Strings::Split(f.content_flags)) {
for (const auto& flag: 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)) {
for (const auto& flag: Strings::Split(f.content_flags_disabled)) {
if (!Strings::Contains(GetContentFlagsDisabled(), flag)) {
return false;
}
@@ -179,13 +195,11 @@ void WorldContentService::ReloadContentFlags()
LogInfo(
"Loaded content flag [{}] [{}]",
f.flag_name,
(f.enabled ? "enabled" : "disabled")
(f.enabled ? "Enabled" : "Disabled")
);
}
SetContentFlags(set_content_flags);
LoadStaticGlobalZoneInstances();
zone_store.LoadZones(*m_content_database);
}
Database *WorldContentService::GetDatabase() const
@@ -200,18 +214,6 @@ WorldContentService *WorldContentService::SetDatabase(Database *database)
return this;
}
Database *WorldContentService::GetContentDatabase() const
{
return m_content_database;
}
WorldContentService *WorldContentService::SetContentDatabase(Database *database)
{
WorldContentService::m_content_database = database;
return this;
}
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
{
auto flags = ContentFlagsRepository::GetWhere(
@@ -236,114 +238,3 @@ void WorldContentService::SetContentFlag(const std::string &content_flag_name, b
ReloadContentFlags();
}
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
{
auto r = FindZone(zc->zoneID, zc->instanceID);
if (r.zone_id == 0) {
return;
}
zc->instanceID = r.instance.id;
}
// LoadStaticGlobalZoneInstances loads all static global zone instances
// these are zones that are never set to expire and are global
// these are used commonly in v1/v2/v3 versions of the same zone for expansion routing
WorldContentService *WorldContentService::LoadStaticGlobalZoneInstances()
{
m_zone_static_instances = InstanceListRepository::GetWhere(
*GetDatabase(),
fmt::format("never_expires = 1 AND is_global = 1")
);
LogInfo("Loaded [{}] zone_instances", m_zone_static_instances.size());
return this;
}
// FindZone handles content and context aware zone routing (middleware)
//
// this is a middleware function that is meant to be used in the zone change process
// this hooks all core zone changes within the server and routes the player to the correct zone
// returning a zone_id of non-zero means the middleware will route the player
// returning a zone_id of 0 means the middleware will not route the player
// this is useful for handling multiple versions of the same zone
//
// implementation >
// the zoning and process spawning logic already is handled by two keys "zone_id" and "instance_id"
// we leverage static, never expires instances to handle this and client still sees it as a normal zone
//
// content awareness >
// simply use the zone_id, server content settings and the middleware will handle the rest
// you don't have to think about instances in any data tables (use instance_id 0)
// you don't have to keep track of instance ids in scripts (use instance_id 0)
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
// we decide to route the client to the correct version of the zone based on the current server side expansion
//
// example >
// we want to route players to the correct version of lavastorm based on the current server side expansion (DoesZonePassContentFiltering)
// lavastorm (pre-don) version 0 (classic)
// zone table entry for version = 0, min_expansion = 0, max_expansion = 8
// instance_list table entry for lavastorm has version = 0, is_global = 1, never_expires = 1
// lavastorm (don) version 1
// zone table entry for version = 1, min_expansion = 9, max_expansion = 99
// instance_list table entry for lavastorm has version = 1, is_global = 1, never_expires = 1
WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
{
for (const auto &z: zone_store.GetZones()) {
for (auto &i: m_zone_static_instances) {
if (
z.zoneidnumber == zone_id &&
DoesZonePassContentFiltering(z) &&
i.zone == zone_id &&
i.version == z.version) {
if (instance_id > 0 && i.id != instance_id) {
continue;
}
LogInfo(
"Routed player to public static instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
i.id,
z.short_name,
z.zoneidnumber,
z.version,
z.long_name,
i.notes
);
return WorldContentService::FindZoneResult{
.zone_id = static_cast<uint32>(z.zoneidnumber),
.instance = i,
.zone = z
};
}
}
}
return WorldContentService::FindZoneResult{.zone_id = 0};
}
bool WorldContentService::IsInPublicStaticInstance(uint32 instance_id)
{
for (auto &i: m_zone_static_instances) {
if (i.id == instance_id) {
return true;
}
}
return false;
}
bool WorldContentService::DoesZonePassContentFiltering(const ZoneRepository::Zone &z)
{
auto f = ContentFlags{
.min_expansion = z.min_expansion,
.max_expansion = z.max_expansion,
.content_flags = z.content_flags,
.content_flags_disabled = z.content_flags_disabled
};
return DoesPassContentFiltering(f);
}
+20 -22
View File
@@ -1,11 +1,29 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_WORLD_CONTENT_SERVICE_H
#define EQEMU_WORLD_CONTENT_SERVICE_H
#include <string>
#include <vector>
#include "../repositories/content_flags_repository.h"
#include "../repositories/zone_repository.h"
#include "../repositories/instance_list_repository.h"
class Database;
@@ -160,38 +178,18 @@ public:
WorldContentService * SetExpansionContext();
bool DoesPassContentFiltering(const ContentFlags& f);
bool DoesZonePassContentFiltering(const ZoneRepository::Zone& z);
WorldContentService * SetDatabase(Database *database);
Database *GetDatabase() const;
WorldContentService * SetContentDatabase(Database *database);
Database *GetContentDatabase() const;
void SetContentFlag(const std::string &content_flag_name, bool enabled);
void HandleZoneRoutingMiddleware(ZoneChange_Struct *zc);
struct FindZoneResult {
uint32 zone_id = 0;
InstanceListRepository::InstanceList instance;
ZoneRepository::Zone zone;
};
FindZoneResult FindZone(uint32 zone_id, uint32 instance_id);
bool IsInPublicStaticInstance(uint32 instance_id);
private:
int current_expansion{};
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
// reference to database
Database *m_database;
Database *m_content_database;
// holds a record of the zone table from the database
WorldContentService *LoadStaticGlobalZoneInstances();
std::vector<InstanceListRepository::InstanceList> m_zone_static_instances;
};
extern WorldContentService content_service;
+1 -3
View File
@@ -15,7 +15,7 @@
#include <cstdio>
#include <vector>
#ifdef _WINDOWS
#if WINDOWS
#define popen _popen
#endif
@@ -294,8 +294,6 @@ void print_trace()
SendCrashReport(crash_report);
}
LogSys.CloseFileLogs();
exit(1);
}
+1615 -1396
View File
File diff suppressed because it is too large Load Diff
+138 -155
View File
@@ -18,8 +18,8 @@
#ifndef EQEMU_DATABASE_H
#define EQEMU_DATABASE_H
#define AUTHENTICATION_TIMEOUT 60
#define INVALID_ID 0xFFFFFFFF
#define AUTHENTICATION_TIMEOUT 60
#define INVALID_ID 0xFFFFFFFF
#include "global_define.h"
#include "eqemu_logsys.h"
@@ -38,7 +38,8 @@
class MySQLRequestResult;
class Client;
namespace EQ {
namespace EQ
{
class InventoryProfile;
}
@@ -51,11 +52,10 @@ struct npcDecayTimes_Struct {
struct VarCache_Struct {
std::map<std::string, std::string> m_cache;
uint32 last_update;
uint32 last_update;
VarCache_Struct() : last_update(0) { }
void Add(const std::string& key, const std::string& value) { m_cache[key] = value; }
const std::string* Get(const std::string& key)
{
void Add(const std::string &key, const std::string &value) { m_cache[key] = value; }
const std::string *Get(const std::string &key) {
auto it = m_cache.find(key);
return (it != m_cache.end() ? &it->second : nullptr);
}
@@ -76,34 +76,37 @@ class PTimerList;
#define SQL(...) #__VA_ARGS__
class LogSettings;
class Database : public DBcore {
public:
Database();
Database(
const std::string& host,
const std::string& user,
const std::string& password,
const std::string& database,
uint32 port
);
bool Connect(
const std::string& host,
const std::string& user,
const std::string& password,
const std::string& database,
uint32 port,
std::string connection_label = "default"
);
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port, std::string connection_label = "default");
~Database();
/* Character Creation */
bool DeleteCharacter(const std::string& name);
bool MoveCharacterToZone(const std::string& name, uint32 zone_id);
bool CreateCharacter(
uint32 account_id,
char *name,
uint16 gender,
uint16 race,
uint16 class_,
uint8 str,
uint8 sta,
uint8 cha,
uint8 dex,
uint8 int_,
uint8 agi,
uint8 wis,
uint8 face
);
bool DeleteCharacter(char *character_name);
bool MoveCharacterToZone(const char *charname, uint32 zone_id);
bool MoveCharacterToZone(uint32 character_id, uint32 zone_id);
bool ReserveName(uint32 account_id, const std::string& name);
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
bool UpdateName(const std::string& old_name, const std::string& new_name);
bool UpdateNameByID(const int character_id, const std::string& new_name);
bool ReserveName(uint32 account_id, char *name);
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp);
bool UpdateName(const char *oldname, const char *newname);
bool CopyCharacter(
const std::string& source_character_name,
const std::string& destination_character_name,
@@ -111,181 +114,161 @@ public:
);
/* General Information Queries */
bool AddBannedIP(const std::string& banned_ip, const std::string& notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(const std::string& name);
bool CheckBannedIPs(const std::string& login_ip); //Check incoming connection against banned IP table.
bool CheckGMIPs(const std::string& login_ip, uint32 account_id);
bool CheckNameFilter(const std::string& name, bool surname = false);
bool IsNameUsed(const std::string& name);
bool IsPetNameUsed(const std::string& name);
uint32 GetAccountIDByChar(const std::string& name, uint32* character_id = 0);
uint32 GetAccountIDByChar(uint32 character_id);
uint32 GetAccountIDByName(const std::string& account_name, const std::string& loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const std::string& name);
uint32 GetGuildIDByCharID(uint32 character_id);
uint32 GetGroupIDByCharID(uint32 character_id);
uint32 GetRaidIDByCharID(uint32 character_id);
bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(std::string name);
bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table.
bool CheckGMIPs(std::string login_ip, uint32 account_id);
bool CheckNameFilter(std::string name, bool surname = false);
bool CheckUsedName(std::string name);
const std::string GetAccountName(uint32 account_id, uint32* lsaccount_id = 0);
const std::string GetCharName(uint32 character_id);
const std::string GetCharNameByID(uint32 character_id);
const std::string GetNPCNameByID(uint32 npc_id);
const std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 account_id, const std::string& login_ip);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id);
uint32 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id);
uint32 GetRaidIDByCharID(uint32 char_id);
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
void GetCharName(uint32 char_id, char* name);
std::string GetCharNameByID(uint32 char_id);
std::string GetNPCNameByID(uint32 npc_id);
std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 account_id, std::string login_ip);
/* Instancing */
bool AddClientToInstance(uint16 instance_id, uint32 character_id);
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id);
bool CheckInstanceExists(uint16 instance_id);
bool CheckInstanceExpired(uint16 instance_id);
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
bool GetUnusedInstanceID(uint16& instance_id);
bool TryGetUnusedInstanceID(uint16& instance_id);
bool GetUnusedInstanceID(uint16 &instance_id);
bool IsGlobalInstance(uint16 instance_id);
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
bool RemoveClientsFromInstance(uint16 instance_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id);
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
uint16 GetInstanceID(uint32 zone, uint32 character_id, int16 version);
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_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);
void AssignGroupToInstance(uint32 group_id, uint32 instance_id);
void AssignRaidToInstance(uint32 raid_id, uint32 instance_id);
void AssignGroupToInstance(uint32 gid, uint32 instance_id);
void AssignRaidToInstance(uint32 rid, uint32 instance_id);
void DeleteInstance(uint16 instance_id);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32>& character_ids);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids);
void PurgeExpiredInstances();
void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
void CleanupInstanceCorpses();
/* Adventure related. */
void UpdateAdventureStatsEntry(uint32 character_id, uint8 theme_id, bool is_win = false, bool is_remove = false);
bool GetAdventureStats(uint32 character_id, AdventureStats_Struct* as);
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win = false, bool remove = false);
bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
/* Account Related */
const std::string GetLiveChar(uint32 account_id);
bool SetAccountStatus(const std::string& account_name, int16 status);
bool SetLocalPassword(uint32 account_id, const std::string& password);
bool UpdateLiveChar(const std::string& name, uint32 account_id);
int16 GetAccountStatus(uint32 account_id);
void SetAccountCRCField(uint32 account_id, const std::string& field_name, uint64 checksum);
uint32 CheckLogin(const std::string& name, const std::string& password, const std::string& loginserver, int16* status = 0);
uint32 CreateAccount(
const std::string& name,
const std::string& password,
int16 status,
const std::string& loginserver,
uint32 lsaccount_id
);
uint32 GetAccountIDFromLSID(
const std::string& in_loginserver_id,
uint32 in_loginserver_account_id,
char* in_account_name = 0,
int16* in_status = 0
);
uint8 GetAgreementFlag(uint32 account_id);
void SetAgreementFlag(uint32 account_id);
bool DeleteAccount(const char *name, const char* loginserver);
bool GetLiveChar(uint32 account_id, char* cname);
bool SetAccountStatus(const char* name, int16 status);
bool SetAccountStatus(const std::string& account_name, int16 status);
bool SetLocalPassword(uint32 accid, const char* password);
bool UpdateLiveChar(char* charname, uint32 account_id);
int GetIPExemption(const std::string& account_ip);
void SetIPExemption(const std::string& account_ip, int exemption_amount);
int16 CheckStatus(uint32 account_id);
int GetInstanceID(uint32 character_id, uint32 zone_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 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
uint8 GetAgreementFlag(uint32 account_id);
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 account_id);
int GetIPExemption(std::string account_ip);
void SetIPExemption(std::string account_ip, int exemption_amount);
int GetInstanceID(uint32 char_id, uint32 zone_id);
/* Groups */
std::string GetGroupLeaderForLogin(const std::string& character_name);
char* GetGroupLeadershipInfo(
uint32 group_id,
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
);
std::string GetGroupLeaderName(uint32 group_id);
uint32 GetGroupID(const std::string& name);
void ClearGroup(uint32 group_id = 0);
void ClearGroupLeader(uint32 group_id = 0);
void SetGroupLeaderName(uint32 group_id, const std::string& name);
std::string GetGroupLeaderForLogin(std::string character_name);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
uint32 GetGroupID(const char* name);
void ClearGroup(uint32 gid = 0);
void ClearGroupLeader(uint32 gid = 0);
void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false);
void SetGroupLeaderName(uint32 gid, const char* name);
/* Raids */
const std::string GetRaidLeaderName(uint32 raid_id);
uint32 GetRaidID(const std::string& name);
void ClearRaid(uint32 raid_id = 0);
void ClearRaidDetails(uint32 raid_id = 0);
void ClearRaidLeader(uint32 group_id = std::numeric_limits<uint32>::max(), uint32 raid_id = 0);
void GetGroupLeadershipInfo(
uint32 group_id,
uint32 raid_id,
char* maintank = nullptr,
char* assist = nullptr,
char* puller = nullptr,
char* marknpc = nullptr,
char* mentoree = nullptr,
int* mentor_percent = nullptr,
GroupLeadershipAA_Struct* GLAA = nullptr
);
void GetRaidLeadershipInfo(
uint32 raid_id,
char* maintank = nullptr,
char* assist = nullptr,
char* puller = nullptr,
char* marknpc = nullptr,
RaidLeadershipAA_Struct* RLAA = nullptr
);
void SetRaidGroupLeaderInfo(uint32 group_id, uint32 raid_id);
void PurgeAllDeletedDataBuckets();
void ClearGuildOnlineStatus();
void ClearTraderDetails();
void ClearBuyerDetails();
const char *GetRaidLeaderName(uint32 rid);
uint32 GetRaidID(const char* name);
void ClearRaid(uint32 rid = 0);
void ClearRaidDetails(uint32 rid = 0);
void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0);
void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, RaidLeadershipAA_Struct* RLAA = nullptr);
void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid);
void PurgeAllDeletedDataBuckets();
/* Database Variables */
bool GetVariable(const std::string& name, std::string& value);
bool SetVariable(const std::string& name, const std::string& value);
bool LoadVariables();
uint8 GetPEQZone(uint32 zone_id, uint32 version);
uint32 GetServerType();
void AddReport(const std::string& who, const std::string& against, const std::string& lines);
struct TimeOfDay_Struct LoadTime(time_t& realtime);
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
void ClearMerchantTemp();
void ClearPTimers(uint32 character_id);
void SetFirstLogon(uint32 character_id, uint8 first_logon);
void SetLFG(uint32 character_id, bool is_lfg);
void SetLFP(uint32 character_id, bool is_lfp);
void SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon);
bool GetVariable(std::string varname, std::string &varvalue);
bool SetVariable(const std::string& varname, const std::string &varvalue);
bool LoadVariables();
int64 CountInvSnapshots();
void ClearInvSnapshots(bool from_now = false);
/* General Queries */
void SourceDatabaseTableFromUrl(const std::string& table_name, const std::string& url);
void SourceSqlFromUrl(const std::string& url);
void PurgeCharacterParcels();
void Encode(std::string &in);
void Decode(std::string &in);
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 LoadPTimers(uint32 charid, PTimerList &into);
uint64_t GetNextTableId(const std::string& table_name);
uint8 GetPEQZone(uint32 zone_id, uint32 version);
uint8 GetMinStatus(uint32 zone_id, uint32 instance_version);
uint8 GetRaceSkill(uint8 skillid, uint8 in_race);
uint8 GetServerType();
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
void AddReport(std::string who, std::string against, std::string lines);
struct TimeOfDay_Struct LoadTime(time_t &realtime);
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
void ClearMerchantTemp();
void ClearPTimers(uint32 charid);
void SetFirstLogon(uint32 CharID, uint8 firstlogon);
void SetLFG(uint32 CharID, bool LFG);
void SetLFP(uint32 CharID, bool LFP);
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
int CountInvSnapshots();
void ClearInvSnapshots(bool from_now = false);
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
void SourceSqlFromUrl(std::string url);
private:
Mutex Mvarcache;
Mutex Mvarcache;
VarCache_Struct varcache;
/* Groups, utility methods. */
void ClearAllGroupLeaders();
void ClearAllGroups();
void ClearAllGroupLeaders();
void ClearAllGroups();
/* Raid, utility methods. */
void ClearAllRaids();
+23 -12
View File
@@ -136,6 +136,11 @@ std::string DatabaseDumpService::GetLoginTableList()
return Strings::Join(DatabaseSchema::GetLoginTables(), " ");
}
std::string DatabaseDumpService::GetQueryServTables()
{
return Strings::Join(DatabaseSchema::GetQueryServerTables(), " ");
}
std::string DatabaseDumpService::GetSystemTablesList()
{
auto system_tables = DatabaseSchema::GetServerTables();
@@ -267,6 +272,11 @@ void DatabaseDumpService::DatabaseDump()
tables_to_dump += GetLoginTableList() + " ";
dump_descriptor += "-login";
}
if (IsDumpQueryServerTables()) {
tables_to_dump += GetQueryServTables();
dump_descriptor += "-queryserv";
}
}
if (IsDumpStaticInstanceData()) {
@@ -391,6 +401,7 @@ void DatabaseDumpService::DatabaseDump()
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
// LogDebug("[{}] dump-path", GetSetDumpPath());
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
// LogDebug("[{}] query-serv", (IsDumpQueryServerTables() ? "true" : "false"));
// LogDebug("[{}] has-compression-binary", (HasCompressionBinary() ? "true" : "false"));
// LogDebug("[{}] content", (IsDumpContentTables() ? "true" : "false"));
// LogDebug("[{}] no-data", (IsDumpWithNoData() ? "true" : "false"));
@@ -500,6 +511,16 @@ const std::string &DatabaseDumpService::GetDumpFileName() const
return dump_file_name;
}
bool DatabaseDumpService::IsDumpQueryServerTables() const
{
return dump_query_server_tables;
}
void DatabaseDumpService::SetDumpQueryServerTables(bool dump_query_server_tables)
{
DatabaseDumpService::dump_query_server_tables = dump_query_server_tables;
}
bool DatabaseDumpService::IsDumpOutputToConsole() const
{
return dump_output_to_console;
@@ -554,12 +575,7 @@ void DatabaseDumpService::RemoveSqlBackup()
{
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
if (File::Exists(file)) {
try {
std::filesystem::remove(file);
}
catch (std::exception &e) {
LogError("std::filesystem::remove err [{}]", e.what());
}
std::filesystem::remove(file);
}
RemoveCredentialsFile();
@@ -596,12 +612,7 @@ void DatabaseDumpService::BuildCredentialsFile()
void DatabaseDumpService::RemoveCredentialsFile()
{
if (File::Exists(CREDENTIALS_FILE)) {
try {
std::filesystem::remove(CREDENTIALS_FILE);
}
catch (std::exception &e) {
LogError("std::filesystem::remove err [{}]", e.what());
}
std::filesystem::remove(CREDENTIALS_FILE);
}
}
+3
View File
@@ -45,6 +45,8 @@ public:
void SetDumpPath(const std::string &dump_path);
const std::string &GetDumpFileName() const;
void SetDumpFileName(const std::string &dump_file_name);
bool IsDumpQueryServerTables() const;
void SetDumpQueryServerTables(bool dump_query_server_tables);
bool IsDumpOutputToConsole() const;
void SetDumpOutputToConsole(bool dump_output_to_console);
bool IsDumpDropTableSyntaxOnly() const;
@@ -94,6 +96,7 @@ private:
bool HasCompressionBinary();
std::string GetDumpFileNameWithPath();
std::string GetSetDumpPath();
std::string GetQueryServTables();
void RemoveSqlBackup();
void BuildCredentialsFile();
void RemoveCredentialsFile();
+1 -52
View File
@@ -142,7 +142,6 @@ bool DatabaseUpdate::UpdateManifest(
if (version_low != version_high) {
LogSys.DisableMySQLErrorLogs();
bool force_interactive = false;
for (int version = version_low + 1; version <= version_high; ++version) {
for (auto &e: entries) {
if (e.version == version) {
@@ -164,20 +163,13 @@ bool DatabaseUpdate::UpdateManifest(
prefix,
e.description
);
if (!has_migration && e.force_interactive) {
force_interactive = true;
}
}
}
}
LogSys.EnableMySQLErrorLogs();
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
if (!missing_migrations.empty() && m_skip_backup) {
LogInfo("Skipping database backup");
}
else if (!missing_migrations.empty()) {
if (!missing_migrations.empty()) {
LogInfo("Automatically backing up database before applying updates");
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
auto s = DatabaseDumpService();
@@ -192,42 +184,6 @@ bool DatabaseUpdate::UpdateManifest(
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
}
if (force_interactive && !std::getenv("FORCE_INTERACTIVE")) {
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
LogInfo("Some migrations require user input. Running interactively");
LogInfo("This is usually due to a major change that could cause data loss");
LogInfo("Your server is automatically backed up before these updates are applied");
LogInfo("but you should also make sure you take a backup prior to running this update");
LogInfo("Would you like to run this update? [y/n] (Timeout 60s)");
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
// user input
std::string input;
bool gave_input = false;
time_t start_time = time(nullptr);
time_t wait_time_seconds = 60;
// spawn a concurrent thread that waits for input from std::cin
std::thread t1(
[&]() {
std::cin >> input;
gave_input = true;
}
);
t1.detach();
// check the inputReceived flag once every 50ms for 10 seconds
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
// prompt for user skip
if (Strings::Trim(input) != "y") {
LogInfo("Exiting due to user input");
std::exit(1);
}
}
for (auto &m: missing_migrations) {
for (auto &e: entries) {
if (e.version == m) {
@@ -315,13 +271,6 @@ DatabaseUpdate *DatabaseUpdate::SetContentDatabase(Database *db)
return this;
}
DatabaseUpdate *DatabaseUpdate::SetSkipBackup(bool skip)
{
m_skip_backup = skip;
return this;
}
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
{
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
-4
View File
@@ -11,7 +11,6 @@ struct ManifestEntry {
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
std::string sql{}; // the SQL DDL that gets ran when the condition is true
bool content_schema_update{}; // if true, this migration is a content schema update and should be ran against the content database
bool force_interactive; // if true, this migration will always be run interactively
};
struct DatabaseVersion {
@@ -30,15 +29,12 @@ public:
DatabaseUpdate *SetDatabase(Database *db);
DatabaseUpdate *SetContentDatabase(Database *db);
DatabaseUpdate *SetSkipBackup(bool skip);
bool HasPendingUpdates();
private:
bool m_skip_backup = false;
Database *m_database;
Database *m_content_database;
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
void InjectBotsVersionColumn();
};
#endif //EQEMU_DATABASE_UPDATE_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+28 -68
View File
@@ -30,8 +30,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/repositories/respawn_times_repository.h"
#include "../common/repositories/spawn_condition_values_repository.h"
#include "repositories/spawn2_disabled_repository.h"
#include "repositories/data_buckets_repository.h"
#include "repositories/zone_state_spawns_repository.h"
#include "database.h"
#include <iomanip>
@@ -114,9 +114,7 @@ bool Database::CheckInstanceExpired(uint16 instance_id)
timeval tv{};
gettimeofday(&tv, nullptr);
// Use uint64_t for the addition to prevent overflow
uint64_t expiration_time = static_cast<uint64_t>(i.start_time) + static_cast<uint64_t>(i.duration);
return expiration_time <= tv.tv_sec;
return (i.start_time + i.duration) <= tv.tv_sec;
}
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
@@ -128,35 +126,11 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
e.version = version;
e.start_time = std::time(nullptr);
e.duration = duration;
e.expire_at = e.start_time + duration;
RespawnTimesRepository::ClearInstanceTimers(*this, e.id);
InstanceListRepository::ReplaceOne(*this, e);
return instance_id > 0 && e.id;
return InstanceListRepository::InsertOne(*this, e).id;
}
bool Database::GetUnusedInstanceID(uint16 &instance_id)
{
// attempt to get an unused instance id
for (int a = 0; a < 10; a++) {
uint16 attempted_id = 0;
if (TryGetUnusedInstanceID(attempted_id)) {
auto i = InstanceListRepository::NewEntity();
i.id = attempted_id;
i.notes = "Prefetching";
auto n = InstanceListRepository::InsertOne(*this, i);
if (n.id > 0) {
instance_id = n.id;
return true;
}
}
}
instance_id = 0;
return false;
}
bool Database::TryGetUnusedInstanceID(uint16 &instance_id)
{
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max_instance_id = 32000;
@@ -447,25 +421,20 @@ void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
const auto& l = GroupIdRepository::GetWhere(
auto l = GroupIdRepository::GetWhere(
*this,
fmt::format(
"`group_id` = {}",
"groupid = {}",
group_id
)
);
if (l.empty()) {
return;
}
for (const auto& e : l) {
if (!e.character_id) {
continue;
}
if (!GetInstanceID(zone_id, e.character_id, version)) {
AddClientToInstance(instance_id, e.character_id);
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
}
}
}
@@ -495,18 +464,16 @@ void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id)
void Database::DeleteInstance(uint16 instance_id)
{
// I'm not sure why this isn't in here but we should add it in a later change and make sure it's tested
// InstanceListRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id));
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id = {}", instance_id));
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
CharacterCorpsesRepository::BuryInstance(*this, instance_id);
DataBucketsRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
if (RuleB(Zone, StateSavingOnShutdown)) {
ZoneStateSpawnsRepository::DeleteWhere(*this, fmt::format("`instance_id` = {}", instance_id));
}
}
void Database::FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id)
@@ -537,7 +504,7 @@ void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 ch
return;
}
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id).c_str());
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id));
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
if (!raid_leader_instance_id) {
@@ -561,12 +528,14 @@ void Database::GetCharactersInInstance(uint16 instance_id, std::list<uint32> &ch
void Database::PurgeExpiredInstances()
{
/**
* Delay purging by a day so that we can continue using adjacent free instance id's
* from the table without risking the chance we immediately re-allocate a zone that freshly expired but
* has not been fully de-allocated
*/
auto l = InstanceListRepository::GetWhere(
*this,
fmt::format(
"expire_at <= (UNIX_TIMESTAMP() - {}) and expire_at != 0 AND never_expires = 0",
RuleI(Instances, ExpireOffsetTimeSeconds)
)
"(start_time + duration) <= (UNIX_TIMESTAMP() - 86400) AND never_expires = 0"
);
if (l.empty()) {
return;
@@ -577,24 +546,16 @@ void Database::PurgeExpiredInstances()
instance_ids.emplace_back(std::to_string(e.id));
}
const auto ids = Strings::Implode(",", instance_ids);
const auto imploded_instance_ids = Strings::Implode(",", instance_ids);
TransactionBegin();
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", ids));
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", ids));
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
CharacterCorpsesRepository::BuryInstances(*this, ids);
DynamicZoneMembersRepository::DeleteByManyInstances(*this, ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", ids));
DataBucketsRepository::DeleteWhere(*this, fmt::format("instance_id != 0 and instance_id IN ({})", ids));
if (RuleB(Zone, StateSavingOnShutdown)) {
ZoneStateSpawnsRepository::DeleteWhere(*this, fmt::format("`instance_id` IN ({})", ids));
}
TransactionCommit();
LogInfo("Purged [{}] expired instances", l.size());
InstanceListRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
InstanceListPlayerRepository::DeleteWhere(*this, fmt::format("id IN ({})", imploded_instance_ids));
RespawnTimesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
SpawnConditionValuesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
}
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
@@ -606,7 +567,6 @@ void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
i.start_time = std::time(nullptr);
i.duration = new_duration;
i.expire_at = i.start_time + i.duration;
InstanceListRepository::UpdateOne(*this, i);
}
+29 -30
View File
@@ -36,6 +36,7 @@ namespace DatabaseSchema {
{
return {
{"adventure_stats", "player_id"},
{"buyer", "charid"},
{"char_recipe_list", "char_id"},
{"character_activities", "charid"},
{"character_alt_currency", "char_id"},
@@ -51,7 +52,6 @@ namespace DatabaseSchema {
{"character_enabledtasks", "charid"},
{"character_expedition_lockouts", "character_id"},
{"character_exp_modifiers", "character_id"},
{"character_evolving_items", "character_id"},
{"character_inspect_messages", "id"},
{"character_instance_safereturns", "character_id"},
{"character_item_recast", "id"},
@@ -59,12 +59,9 @@ namespace DatabaseSchema {
{"character_leadership_abilities", "id"},
{"character_material", "id"},
{"character_memmed_spells", "id"},
{"character_parcels", "char_id"},
{"character_parcels_containers", "id"},
{"character_pet_buffs", "char_id"},
{"character_pet_info", "char_id"},
{"character_pet_inventory", "char_id"},
{"character_pet_name", "character_id"},
{"character_peqzone_flags", "id"},
{"character_potionbelt", "id"},
{"character_skills", "id"},
@@ -108,8 +105,6 @@ namespace DatabaseSchema {
"adventure_details",
"adventure_stats",
"buyer",
"buyer_buy_lines",
"buyer_trade_items",
"char_recipe_list",
"character_activities",
"character_alt_currency",
@@ -126,7 +121,6 @@ namespace DatabaseSchema {
"character_enabledtasks",
"character_expedition_lockouts",
"character_exp_modifiers",
"character_evolving_items",
"character_inspect_messages",
"character_instance_safereturns",
"character_item_recast",
@@ -134,12 +128,9 @@ namespace DatabaseSchema {
"character_leadership_abilities",
"character_material",
"character_memmed_spells",
"character_parcels",
"character_parcels_containers",
"character_pet_buffs",
"character_pet_info",
"character_pet_inventory",
"character_pet_name",
"character_peqzone_flags",
"character_potionbelt",
"character_skills",
@@ -216,7 +207,6 @@ namespace DatabaseSchema {
"ground_spawns",
"horses",
"items",
"items_evolving_details",
"ldon_trap_entries",
"ldon_trap_templates",
"lootdrop",
@@ -292,6 +282,32 @@ namespace DatabaseSchema {
};
}
/**
* Gets QueryServer tables
*
* @return
*/
static std::vector<std::string> GetQueryServerTables()
{
return {
"qs_merchant_transaction_record",
"qs_merchant_transaction_record_entries",
"qs_player_aa_rate_hourly",
"qs_player_delete_record",
"qs_player_delete_record_entries",
"qs_player_events",
"qs_player_handin_record",
"qs_player_handin_record_entries",
"qs_player_move_record",
"qs_player_move_record_entries",
"qs_player_npc_kill_record",
"qs_player_npc_kill_record_entries",
"qs_player_speech",
"qs_player_trade_record",
"qs_player_trade_record_entries",
};
}
/**
* Gets state tables
* Tables that keep track of server state
@@ -305,16 +321,14 @@ namespace DatabaseSchema {
"banned_ips",
"bug_reports",
"bugs",
"buyer",
"buyer_buy_lines",
"buyer_trade_items",
"completed_shared_task_activity_state",
"completed_shared_task_members",
"completed_shared_tasks",
"discord_webhooks",
"dynamic_zone_lockouts",
"dynamic_zone_members",
"dynamic_zones",
"expedition_lockouts",
"expeditions",
"gm_ips",
"group_id",
"group_leaders",
@@ -333,25 +347,12 @@ namespace DatabaseSchema {
"saylink",
"server_scheduled_events",
"spawn2_disabled",
"player_event_aa_purchase",
"player_event_killed_npc",
"player_event_killed_named_npc",
"player_event_killed_raid_npc",
"player_event_log_settings",
"player_event_logs",
"player_event_loot_items",
"player_event_merchant_purchase",
"player_event_merchant_sell",
"player_event_npc_handin",
"player_event_npc_handin_entries",
"player_event_speech",
"player_event_trade",
"player_event_trade_entries",
"shared_task_activity_state",
"shared_task_dynamic_zones",
"shared_task_members",
"shared_tasks",
"zone_state_spawns",
};
}
@@ -393,7 +394,6 @@ namespace DatabaseSchema {
static std::vector<std::string> GetBotTables()
{
return {
"bot_blocked_buffs",
"bot_buffs",
"bot_command_settings",
"bot_create_combinations",
@@ -407,7 +407,6 @@ namespace DatabaseSchema {
"bot_pet_buffs",
"bot_pet_inventories",
"bot_pets",
"bot_settings",
"bot_spell_casting_chances",
"bot_spell_settings",
"bot_spells_entries",
+1 -9
View File
@@ -7,7 +7,6 @@
#include "timer.h"
#include "dbcore.h"
#include "mysql_stmt.h"
#include <fstream>
#include <iostream>
@@ -302,9 +301,7 @@ std::string DBcore::Escape(const std::string& s)
void DBcore::SetMutex(Mutex *mutex)
{
if (m_mutex && m_mutex != mutex) {
safe_delete(m_mutex);
}
safe_delete(m_mutex);
DBcore::m_mutex = mutex;
}
@@ -439,8 +436,3 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
return r;
}
mysql::PreparedStmt DBcore::Prepare(std::string query)
{
return mysql::PreparedStmt(*mysql, std::move(query), m_mutex);
}
-7
View File
@@ -17,8 +17,6 @@
#define CR_SERVER_GONE_ERROR 2006
#define CR_SERVER_LOST 2013
namespace mysql { class PreparedStmt; }
class DBcore {
public:
enum eStatus {
@@ -50,11 +48,6 @@ public:
}
void SetMutex(Mutex *mutex);
// only safe on connections shared with other threads if results buffered
// unsafe to use off main thread due to internal server logging
// throws std::runtime_error on failure
mysql::PreparedStmt Prepare(std::string query);
protected:
bool Open(
const char *iHost,
+70 -6
View File
@@ -19,17 +19,81 @@
#include "deity.h"
uint32 Deity::GetBitmask(uint32 deity_id)
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
{
return IsValid(deity_id) ? deity_bitmasks[deity_id] : Deity::Bitmask::All;
switch (deity_type) {
case DeityBertoxxulous:
return bit_DeityBertoxxulous;
case DeityBrellSirilis:
return bit_DeityBrellSirilis;
case DeityCazicThule:
return bit_DeityCazicThule;
case DeityErollisiMarr:
return bit_DeityErollisiMarr;
case DeityBristlebane:
return bit_DeityBristlebane;
case DeityInnoruuk:
return bit_DeityInnoruuk;
case DeityKarana:
return bit_DeityKarana;
case DeityMithanielMarr:
return bit_DeityMithanielMarr;
case DeityPrexus:
return bit_DeityPrexus;
case DeityQuellious:
return bit_DeityQuellious;
case DeityRallosZek:
return bit_DeityRallosZek;
case DeityRodcetNife:
return bit_DeityRodcetNife;
case DeitySolusekRo:
return bit_DeitySolusekRo;
case DeityTheTribunal:
return bit_DeityTheTribunal;
case DeityTunare:
return bit_DeityTunare;
case DeityVeeshan:
return bit_DeityVeeshan;
case DeityAgnostic_LB:
case DeityAgnostic:
return bit_DeityAgnostic;
default:
return bit_DeityAll;
}
}
std::string Deity::GetName(uint32 deity_id)
const std::map<EQ::deity::DeityType, std::string>& EQ::deity::GetDeityMap()
{
return IsValid(deity_id) ? deity_names[deity_id] : "UNKNOWN DEITY";
static const std::map<EQ::deity::DeityType, std::string> deity_map = {
{ DeityAgnostic, "Agnostic" },
{ DeityAgnostic_LB, "Agnostic" },
{ DeityBertoxxulous, "Bertoxxulous" },
{ DeityBrellSirilis, "Brell Serilis" },
{ DeityBristlebane, "Bristlebane" },
{ DeityCazicThule, "Cazic-Thule" },
{ DeityErollisiMarr, "Erollisi Marr" },
{ DeityInnoruuk, "Innoruuk" },
{ DeityKarana, "Karana" },
{ DeityMithanielMarr, "Mithaniel Marr" },
{ DeityPrexus, "Prexus" },
{ DeityQuellious, "Quellious" },
{ DeityRallosZek, "Rallos Zek" },
{ DeityRodcetNife, "Rodcet Nife" },
{ DeitySolusekRo, "Solusek Ro" },
{ DeityTheTribunal, "The Tribunal" },
{ DeityTunare, "Tunare" },
{ DeityVeeshan, "Veeshan" }
};
return deity_map;
}
bool Deity::IsValid(uint32 deity_id)
std::string EQ::deity::GetDeityName(DeityType deity_type)
{
return deity_names.find(deity_id) != deity_names.end();
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) {
return EQ::deity::GetDeityMap().find(deity_type)->second;
}
return std::string();
}
+52 -85
View File
@@ -23,95 +23,62 @@
#include "types.h"
#include <map>
#include <string>
#include <limits>
namespace Deity {
constexpr uint32 Unknown = 0;
constexpr uint32 Agnostic1 = 140;
constexpr uint32 Bertoxxulous = 201;
constexpr uint32 BrellSirilis = 202;
constexpr uint32 CazicThule = 203;
constexpr uint32 ErollisiMarr = 204;
constexpr uint32 Bristlebane = 205;
constexpr uint32 Innoruuk = 206;
constexpr uint32 Karana = 207;
constexpr uint32 MithanielMarr = 208;
constexpr uint32 Prexus = 209;
constexpr uint32 Quellious = 210;
constexpr uint32 RallosZek = 211;
constexpr uint32 RodcetNife = 212;
constexpr uint32 SolusekRo = 213;
constexpr uint32 TheTribunal = 214;
constexpr uint32 Tunare = 215;
constexpr uint32 Veeshan = 216;
constexpr uint32 Agnostic2 = 396;
namespace Bitmask {
constexpr uint32 Agnostic = 1;
constexpr uint32 Bertoxxulous = 2;
constexpr uint32 BrellSirilis = 4;
constexpr uint32 CazicThule = 8;
constexpr uint32 ErollisiMarr = 16;
constexpr uint32 Bristlebane = 32;
constexpr uint32 Innoruuk = 64;
constexpr uint32 Karana = 128;
constexpr uint32 MithanielMarr = 256;
constexpr uint32 Prexus = 512;
constexpr uint32 Quellious = 1024;
constexpr uint32 RallosZek = 2048;
constexpr uint32 RodcetNife = 4096;
constexpr uint32 SolusekRo = 8192;
constexpr uint32 TheTribunal = 16384;
constexpr uint32 Tunare = 32768;
constexpr uint32 Veeshan = 65536;
constexpr uint32 All = std::numeric_limits<uint32>::max();
}
namespace EQ
{
namespace deity {
enum DeityType {
DeityUnknown = 0,
DeityAgnostic_LB = 140,
DeityBertoxxulous = 201,
DeityBrellSirilis,
DeityCazicThule,
DeityErollisiMarr,
DeityBristlebane,
DeityInnoruuk,
DeityKarana,
DeityMithanielMarr,
DeityPrexus,
DeityQuellious,
DeityRallosZek,
DeityRodcetNife,
DeitySolusekRo,
DeityTheTribunal,
DeityTunare,
DeityVeeshan,
DeityAgnostic = 396
};
uint32 GetBitmask(uint32 deity_id);
std::string GetName(uint32 deity_id);
bool IsValid(uint32 deity_id);
}
enum DeityTypeBit : uint32 {
bit_DeityAgnostic = 0x00000001,
bit_DeityBertoxxulous = 0x00000002,
bit_DeityBrellSirilis = 0x00000004,
bit_DeityCazicThule = 0x00000008,
bit_DeityErollisiMarr = 0x00000010,
bit_DeityBristlebane = 0x00000020,
bit_DeityInnoruuk = 0x00000040,
bit_DeityKarana = 0x00000080,
bit_DeityMithanielMarr = 0x00000100,
bit_DeityPrexus = 0x00000200,
bit_DeityQuellious = 0x00000400,
bit_DeityRallosZek = 0x00000800,
bit_DeityRodcetNife = 0x00001000,
bit_DeitySolusekRo = 0x00002000,
bit_DeityTheTribunal = 0x00004000,
bit_DeityTunare = 0x00008000,
bit_DeityVeeshan = 0x00010000,
bit_DeityAll = UINT32_MAX
};
static std::map<uint32, std::string> deity_names = {
{ Deity::Agnostic1, "Agnostic" },
{ Deity::Agnostic2, "Agnostic" },
{ Deity::Bertoxxulous, "Bertoxxulous" },
{ Deity::BrellSirilis, "Brell Serilis" },
{ Deity::Bristlebane, "Bristlebane" },
{ Deity::CazicThule, "Cazic-Thule" },
{ Deity::ErollisiMarr, "Erollisi Marr" },
{ Deity::Innoruuk, "Innoruuk" },
{ Deity::Karana, "Karana" },
{ Deity::MithanielMarr, "Mithaniel Marr" },
{ Deity::Prexus, "Prexus" },
{ Deity::Quellious, "Quellious" },
{ Deity::RallosZek, "Rallos Zek" },
{ Deity::RodcetNife, "Rodcet Nife" },
{ Deity::SolusekRo, "Solusek Ro" },
{ Deity::TheTribunal, "The Tribunal" },
{ Deity::Tunare, "Tunare" },
{ Deity::Veeshan, "Veeshan" }
};
constexpr int format_as(DeityType type) { return static_cast<int>(type); }
static std::map<uint32, uint32> deity_bitmasks = {
{ Deity::Agnostic1, Deity::Bitmask::Agnostic },
{ Deity::Agnostic2, Deity::Bitmask::Agnostic },
{ Deity::Bertoxxulous, Deity::Bitmask::Bertoxxulous },
{ Deity::BrellSirilis, Deity::Bitmask::BrellSirilis },
{ Deity::CazicThule, Deity::Bitmask::CazicThule },
{ Deity::ErollisiMarr, Deity::Bitmask::ErollisiMarr },
{ Deity::Bristlebane, Deity::Bitmask::Bristlebane },
{ Deity::Innoruuk, Deity::Bitmask::Innoruuk },
{ Deity::Karana, Deity::Bitmask::Karana },
{ Deity::MithanielMarr, Deity::Bitmask::MithanielMarr },
{ Deity::Prexus, Deity::Bitmask::Prexus },
{ Deity::Quellious, Deity::Bitmask::Quellious },
{ Deity::RallosZek, Deity::Bitmask::RallosZek },
{ Deity::RodcetNife, Deity::Bitmask::RodcetNife },
{ Deity::SolusekRo, Deity::Bitmask::SolusekRo },
{ Deity::TheTribunal, Deity::Bitmask::TheTribunal },
{ Deity::Tunare, Deity::Bitmask::Tunare },
{ Deity::Veeshan, Deity::Bitmask::Veeshan }
};
extern DeityTypeBit GetDeityBitmask(DeityType deity_type);
extern std::string GetDeityName(DeityType deity_type);
extern const std::map<DeityType, std::string>& GetDeityMap();
} /*deity*/
} /*EQEmu*/
#endif /* COMMON_DEITY_H */
+67 -297
View File
@@ -1,13 +1,11 @@
#include "dynamic_zone_base.h"
#include "database.h"
#include "eqemu_logsys.h"
#include "repositories/instance_list_repository.h"
#include "repositories/instance_list_player_repository.h"
#include "rulesys.h"
#include "servertalk.h"
#include "util/uuid.h"
#include "repositories/character_expedition_lockouts_repository.h"
#include "repositories/dynamic_zone_lockouts_repository.h"
#include "repositories/instance_list_repository.h"
#include "repositories/instance_list_player_repository.h"
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
{
@@ -58,16 +56,15 @@ uint32_t DynamicZoneBase::CreateInstance()
insert_instance.start_time = static_cast<int>(std::chrono::system_clock::to_time_t(m_start_time));
insert_instance.duration = static_cast<int>(m_duration.count());
insert_instance.never_expires = m_never_expires;
insert_instance.expire_at = insert_instance.start_time + insert_instance.duration;
auto instance = InstanceListRepository::ReplaceOne(GetDatabase(), insert_instance);
if (!instance)
auto instance = InstanceListRepository::InsertOne(GetDatabase(), insert_instance);
if (instance.id == 0)
{
LogDynamicZones("Failed to create instance [{}] for zone [{}]", unused_instance_id, m_zone_id);
return 0;
}
m_instance_id = unused_instance_id;
m_instance_id = instance.id;
return m_instance_id;
}
@@ -96,15 +93,13 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
m_zonein.y = dz_entry.zone_in_y;
m_zonein.z = dz_entry.zone_in_z;
m_zonein.heading = dz_entry.zone_in_heading;
m_has_zonein = dz_entry.has_zone_in != 0;
m_is_locked = dz_entry.is_locked;
m_add_replay = dz_entry.add_replay;
m_has_zonein = (dz_entry.has_zone_in != 0);
// instance_list portion
m_zone_id = dz_entry.zone;
m_zone_version = dz_entry.version;
m_start_time = std::chrono::system_clock::from_time_t(dz_entry.start_time);
m_duration = std::chrono::seconds(dz_entry.duration);
m_never_expires = dz_entry.never_expires != 0;
m_never_expires = (dz_entry.never_expires != 0);
m_expire_time = m_start_time + m_duration;
}
@@ -124,40 +119,37 @@ void DynamicZoneBase::AddMemberFromRepositoryResult(
uint32_t DynamicZoneBase::SaveToDatabase()
{
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
if (m_instance_id == 0)
if (m_instance_id != 0)
{
return 0;
auto insert_dz = DynamicZonesRepository::NewEntity();
insert_dz.uuid = m_uuid;
insert_dz.name = m_name;
insert_dz.leader_id = m_leader.id;
insert_dz.min_players = m_min_players;
insert_dz.max_players = m_max_players;
insert_dz.instance_id = m_instance_id,
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_x = m_compass.x;
insert_dz.compass_y = m_compass.y;
insert_dz.compass_z = m_compass.z;
insert_dz.safe_return_zone_id = m_safereturn.zone_id;
insert_dz.safe_return_x = m_safereturn.x;
insert_dz.safe_return_y = m_safereturn.y;
insert_dz.safe_return_z = m_safereturn.z;
insert_dz.safe_return_heading = m_safereturn.heading;
insert_dz.zone_in_x = m_zonein.x;
insert_dz.zone_in_y = m_zonein.y;
insert_dz.zone_in_z = m_zonein.z;
insert_dz.zone_in_heading = m_zonein.heading;
insert_dz.has_zone_in = m_has_zonein;
auto inserted_dz = DynamicZonesRepository::InsertOne(GetDatabase(), insert_dz);
return inserted_dz.id;
}
auto dz = DynamicZonesRepository::NewEntity();
dz.uuid = m_uuid;
dz.name = m_name;
dz.leader_id = m_leader.id;
dz.min_players = m_min_players;
dz.max_players = m_max_players;
dz.instance_id = static_cast<int32_t>(m_instance_id),
dz.type = static_cast<uint8_t>(m_type);
dz.dz_switch_id = m_dz_switch_id;
dz.compass_zone_id = m_compass.zone_id;
dz.compass_x = m_compass.x;
dz.compass_y = m_compass.y;
dz.compass_z = m_compass.z;
dz.safe_return_zone_id = m_safereturn.zone_id;
dz.safe_return_x = m_safereturn.x;
dz.safe_return_y = m_safereturn.y;
dz.safe_return_z = m_safereturn.z;
dz.safe_return_heading = m_safereturn.heading;
dz.zone_in_x = m_zonein.x;
dz.zone_in_y = m_zonein.y;
dz.zone_in_z = m_zonein.z;
dz.zone_in_heading = m_zonein.heading;
dz.has_zone_in = static_cast<uint8_t>(m_has_zonein);
dz.is_locked = static_cast<int8_t>(m_is_locked);
dz.add_replay = static_cast<int8_t>(m_add_replay);
dz = DynamicZonesRepository::InsertOne(GetDatabase(), std::move(dz));
return dz.id;
return 0;
}
bool DynamicZoneBase::AddMember(const DynamicZoneMember& add_member)
@@ -204,9 +196,10 @@ bool DynamicZoneBase::RemoveMember(const DynamicZoneMember& remove_member)
return true;
}
bool DynamicZoneBase::SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name)
bool DynamicZoneBase::SwapMember(
const DynamicZoneMember& add_member, const std::string& remove_char_name)
{
auto remove_member = GetMemberData(remove_name);
auto remove_member = GetMemberData(remove_char_name);
if (!add_member.IsValid() || !remove_member.IsValid())
{
return false;
@@ -237,18 +230,9 @@ void DynamicZoneBase::RemoveAllMembers()
void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
{
if (members.empty())
{
return;
}
LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id);
m_members = members;
if (m_members.size() > m_max_players)
{
m_members.resize(m_max_players);
}
// the lower level instance_list_players needs to be kept updated as well
std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members;
@@ -258,12 +242,12 @@ void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
member_entry.dynamic_zone_id = m_id;
member_entry.character_id = member.id;
insert_members.push_back(member_entry);
insert_members.emplace_back(member_entry);
InstanceListPlayerRepository::InstanceListPlayer player_entry{};
player_entry.id = m_instance_id;
player_entry.charid = member.id;
insert_players.push_back(player_entry);
InstanceListPlayerRepository::InstanceListPlayer player_entry;
player_entry.id = static_cast<int>(m_instance_id);
player_entry.charid = static_cast<int>(member.id);
insert_players.emplace_back(player_entry);
}
DynamicZoneMembersRepository::InsertOrUpdateMany(GetDatabase(), insert_members);
@@ -355,44 +339,6 @@ void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update
}
}
void DynamicZoneBase::SetLocked(bool lock, bool update_db, DzLockMsg lock_msg, uint32_t color)
{
m_is_locked = lock;
if (update_db)
{
DynamicZonesRepository::UpdateLocked(GetDatabase(), m_id, lock);
ServerPacket pack(ServerOP_DzLock, sizeof(ServerDzLock_Struct));
auto buf = reinterpret_cast<ServerDzLock_Struct*>(pack.pBuffer);
buf->dz_id = GetID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->lock = m_is_locked;
buf->lock_msg = static_cast<uint8_t>(lock_msg);
buf->color = color;
SendServerPacket(&pack);
}
}
void DynamicZoneBase::SetReplayOnJoin(bool enabled, bool update_db)
{
m_add_replay = enabled;
if (update_db)
{
DynamicZonesRepository::UpdateReplayOnJoin(GetDatabase(), m_id, enabled);
ServerPacket pack(ServerOP_DzReplayOnJoin, sizeof(ServerDzBool_Struct));
auto buf = reinterpret_cast<ServerDzBool_Struct*>(pack.pBuffer);
buf->dz_id = GetID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->enabled = enabled;
SendServerPacket(&pack);
}
}
uint32_t DynamicZoneBase::GetSecondsRemaining() const
{
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(GetDurationRemaining()).count();
@@ -532,13 +478,13 @@ void DynamicZoneBase::RemoveInternalMember(uint32_t character_id)
), m_members.end());
}
bool DynamicZoneBase::HasMember(uint32_t character_id) const
bool DynamicZoneBase::HasMember(uint32_t character_id)
{
return std::any_of(m_members.begin(), m_members.end(),
[&](const DynamicZoneMember& member) { return member.id == character_id; });
}
bool DynamicZoneBase::HasMember(const std::string& character_name) const
bool DynamicZoneBase::HasMember(const std::string& character_name)
{
return std::any_of(m_members.begin(), m_members.end(),
[&](const DynamicZoneMember& member) {
@@ -644,34 +590,35 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
}
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerPacket(uint16_t zone_id, uint16_t instance_id)
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
{
std::ostringstream ss = GetSerialized();
std::string_view sv = ss.view();
EQ::Net::DynamicPacket dyn_pack;
dyn_pack.PutSerialize(0, *this);
auto pack_size = sizeof(ServerDzCreate_Struct) + sv.size();
LogDynamicZonesDetail("Serialized server dz size [{}]", dyn_pack.Length());
return dyn_pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzCreatePacket(
uint16_t origin_zone_id, uint16_t origin_instance_id)
{
EQ::Net::DynamicPacket dyn_pack = GetSerializedDzPacket();
auto pack_size = sizeof(ServerDzCreateSerialized_Struct) + dyn_pack.Length();
auto pack = std::make_unique<ServerPacket>(ServerOP_DzCreated, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerDzCreate_Struct*>(pack->pBuffer);
buf->origin_zone_id = zone_id;
buf->origin_instance_id = instance_id;
buf->dz_id = GetID();
buf->cereal_size = static_cast<uint32_t>(sv.size());
memcpy(buf->cereal_data, sv.data(), sv.size());
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer);
buf->origin_zone_id = origin_zone_id;
buf->origin_instance_id = origin_instance_id;
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
return pack;
}
std::ostringstream DynamicZoneBase::GetSerialized()
void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size)
{
std::ostringstream ss;
cereal::BinaryOutputArchive archive(ss);
archive(*this);
return ss;
}
void DynamicZoneBase::Unserialize(std::span<char> buf)
{
EQ::Util::MemoryStreamReader ss(buf.data(), buf.size());
LogDynamicZonesDetail("Deserializing server dz size [{}]", cereal_size);
EQ::Util::MemoryStreamReader ss(cereal_data, cereal_size);
cereal::BinaryInputArchive archive(ss);
archive(*this);
}
@@ -700,180 +647,3 @@ void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::Dynamic
m_zonein.z = dz_template.zone_in_z;
m_zonein.heading = dz_template.zone_in_h;
}
std::vector<uint32_t> DynamicZoneBase::GetMemberIds()
{
std::vector<uint32_t> ids;
ids.reserve(m_members.size());
for (const auto& member : m_members)
{
ids.push_back(member.id);
}
return ids;
}
bool DynamicZoneBase::HasLockout(const std::string& event)
{
return std::ranges::any_of(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
}
bool DynamicZoneBase::HasReplayLockout()
{
return HasLockout(DzLockout::ReplayTimer);
}
void DynamicZoneBase::AddLockout(const std::string& event, uint32_t seconds)
{
auto lockout = DzLockout::Create(m_name, event, seconds, m_uuid);
AddLockout(lockout);
}
void DynamicZoneBase::AddLockout(const DzLockout& lockout, bool members_only)
{
if (!members_only)
{
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { lockout });
}
CharacterExpeditionLockoutsRepository::InsertLockout(GetDatabase(), GetMemberIds(), lockout);
HandleLockoutUpdate(lockout, false, members_only);
SendServerPacket(CreateLockoutPacket(lockout, false, members_only).get());
}
void DynamicZoneBase::AddLockoutDuration(const std::string& event, int seconds, bool members_only)
{
auto lockout = DzLockout::Create(m_name, event, std::max(0, seconds), m_uuid);
// lockout has unsigned duration, pass original seconds to support reducing existing timers
int secs = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
CharacterExpeditionLockoutsRepository::AddLockoutDuration(GetDatabase(), GetMemberIds(), lockout, secs);
HandleLockoutDuration(lockout, seconds, members_only, true);
SendServerPacket(CreateLockoutDurationPacket(lockout, seconds, members_only).get());
}
void DynamicZoneBase::UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only)
{
// some live expeditions update existing lockout timers during progression
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
if (it != m_lockouts.end())
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
DzLockout lockout(m_uuid, m_name, event, it->GetStartTime() + seconds, seconds);
AddLockout(lockout, members_only);
}
}
void DynamicZoneBase::RemoveLockout(const std::string& event)
{
DynamicZoneLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
"dynamic_zone_id = {} AND event_name = '{}'", GetID(), Strings::Escape(event)));
CharacterExpeditionLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
"character_id IN ({}) AND expedition_name = '{}' AND event_name = '{}'",
fmt::join(GetMemberIds(), ","), Strings::Escape(m_name), Strings::Escape(event)));
DzLockout lockout{m_uuid, m_name, event, 0, 0};
HandleLockoutUpdate(lockout, true, false);
SendServerPacket(CreateLockoutPacket(lockout, true).get());
}
void DynamicZoneBase::HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only)
{
if (!members_only)
{
std::erase_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
if (!remove)
{
m_lockouts.push_back(lockout);
}
}
}
void DynamicZoneBase::HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db)
{
if (!members_only)
{
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
if (it != m_lockouts.end())
{
it->AddLockoutTime(seconds);
}
else
{
it = m_lockouts.insert(m_lockouts.end(), lockout);
}
if (insert_db)
{
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { *it });
}
}
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only) const
{
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockout, pack_size);
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->expire_time = lockout.GetExpireTime();
buf->duration = lockout.GetDuration();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->remove = remove;
buf->members_only = members_only;
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only) const
{
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockoutDuration, pack_size);
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->expire_time = lockout.GetExpireTime();
buf->duration = lockout.GetDuration();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->members_only = members_only;
buf->seconds = seconds;
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
return pack;
}
void DynamicZoneBase::SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts)
{
// adds missing event lockouts to client for this expedition and updates
// client timers that are both shorter and from another expedition
bool modified = false;
for (const auto& lockout : m_lockouts)
{
if (lockout.IsReplay() || lockout.IsExpired() || lockout.UUID() != m_uuid)
{
continue;
}
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& l) { return l.IsSame(lockout); });
if (it == lockouts.end())
{
modified = true;
lockouts.push_back(lockout); // insert missing
}
else if (it->GetSecondsRemaining() < lockout.GetSecondsRemaining() && it->UUID() != m_uuid)
{
// only update lockout timer not uuid so loot event apis still work
modified = true;
it->SetDuration(lockout.GetDuration());
it->SetExpireTime(lockout.GetExpireTime());
}
}
if (modified)
{
CharacterExpeditionLockoutsRepository::InsertLockouts(GetDatabase(), char_id, lockouts);
}
}
+14 -68
View File
@@ -1,8 +1,8 @@
#ifndef COMMON_DYNAMIC_ZONE_BASE_H
#define COMMON_DYNAMIC_ZONE_BASE_H
#include "dynamic_zone_lockout.h"
#include "eq_constants.h"
#include "net/packet.h"
#include "repositories/dynamic_zones_repository.h"
#include "repositories/dynamic_zone_members_repository.h"
#include "repositories/dynamic_zone_templates_repository.h"
@@ -10,40 +10,12 @@
#include <chrono>
#include <cstdint>
#include <memory>
#include <span>
#include <string>
#include <vector>
class Database;
class ServerPacket;
// message string 8312 added in September 08 2020 Test patch (used by both dz and shared tasks)
inline constexpr char DzNotAllAdded[] = "Not all players in your {0} were added to the {1}. The {1} can take a maximum of {2} players, and your {0} has {3}.";
enum class DzLockMsg : uint8_t
{
None = 0, Close, Begin
};
enum class DynamicZoneType
{
None = 0,
Expedition,
Tutorial,
Task,
Mission, // Shared Task
Quest
};
enum class DynamicZoneMemberStatus
{
Unknown = 0,
Online,
Offline,
InDynamicZone,
LinkDead
};
struct DynamicZoneMember
{
uint32_t id = 0;
@@ -121,7 +93,6 @@ public:
const std::string& GetName() const { return m_name; }
const std::string& GetUUID() const { return m_uuid; }
const DynamicZoneMember& GetLeader() const { return m_leader; }
const std::vector<DzLockout>& GetLockouts() const { return m_lockouts; }
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
const DynamicZoneLocation& GetCompassLocation() const { return m_compass; }
const DynamicZoneLocation& GetSafeReturnLocation() const { return m_safereturn; }
@@ -133,34 +104,31 @@ public:
uint32_t GetDatabaseMemberCount();
DynamicZoneMember GetMemberData(uint32_t character_id);
DynamicZoneMember GetMemberData(const std::string& character_name);
std::vector<uint32_t> GetMemberIds();
std::ostringstream GetSerialized();
EQ::Net::DynamicPacket GetSerializedDzPacket();
bool HasDatabaseMember(uint32_t character_id);
bool HasMember(uint32_t character_id) const;
bool HasMember(const std::string& character_name) const;
bool HasMember(uint32_t character_id);
bool HasMember(const std::string& character_name);
bool HasMembers() const { return !m_members.empty(); }
bool HasZoneInLocation() const { return m_has_zonein; }
bool IsExpedition() const { return m_type == DynamicZoneType::Expedition; }
bool IsExpired() const { return m_expire_time < std::chrono::system_clock::now(); }
bool IsInstanceID(uint32_t instance_id) const { return (m_instance_id != 0 && m_instance_id == instance_id); }
bool IsLocked() const { return m_is_locked; }
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; }
void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
void RemoveAllMembers();
bool RemoveMember(uint32_t character_id);
bool RemoveMember(const std::string& character_name);
bool RemoveMember(const DynamicZoneMember& remove_member);
void SaveMembers(const std::vector<DynamicZoneMember>& members);
void SetCompass(const DynamicZoneLocation& location, bool update_db = false);
void SetCompass(uint32_t zone_id, float x, float y, float z, bool update_db = false);
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
void SetLeader(const DynamicZoneMember& leader, bool update_db = false);
void SetLocked(bool lock, bool update_db = false, DzLockMsg lock_msg = DzLockMsg::None, uint32_t color = Chat::Yellow);
void SetMaxPlayers(uint32_t max_players) { m_max_players = max_players; }
void SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; }
void SetName(const std::string& name) { m_name = name; }
void SetReplayOnJoin(bool enabled, 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 SetSwitchID(int dz_switch_id, bool update_db = false);
@@ -168,48 +136,34 @@ public:
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
void SetZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name);
void AddLockout(const std::string& event, uint32_t seconds);
void AddLockoutDuration(const std::string& event, int seconds, bool members_only = true);
bool HasLockout(const std::string& event);
bool HasReplayLockout();
void RemoveLockout(const std::string& event);
void SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts);
void UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only = true);
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_char_name);
protected:
virtual uint16_t GetCurrentInstanceID() const { return 0; }
virtual uint16_t GetCurrentZoneID() const { return 0; }
virtual uint16_t GetCurrentInstanceID() { return 0; }
virtual uint16_t GetCurrentZoneID() { return 0; }
virtual Database& GetDatabase() = 0;
virtual void HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db);
virtual void HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only);
virtual void ProcessCompassChange(const DynamicZoneLocation& location) { m_compass = location; }
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
virtual bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status);
virtual void ProcessRemoveAllMembers() { m_members.clear(); }
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status);
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;
void AddLockout(const DzLockout& lockout, bool members_only = false);
void AddInternalMember(const DynamicZoneMember& member);
uint32_t Create();
uint32_t CreateInstance();
void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry);
void RemoveInternalMember(uint32_t character_id);
void SaveMembers(const std::vector<DynamicZoneMember>& members);
uint32_t SaveToDatabase();
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
std::unique_ptr<ServerPacket> CreateServerPacket(uint16_t zone_id, uint16_t 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> CreateServerDzSwitchIDPacket();
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> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
std::unique_ptr<ServerPacket> CreateServerRemoveAllMembersPacket();
std::unique_ptr<ServerPacket> CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only = false) const;
std::unique_ptr<ServerPacket> CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only = false) const;
uint32_t m_id = 0;
uint32_t m_zone_id = 0;
@@ -221,8 +175,6 @@ protected:
bool m_never_expires = false;
bool m_has_zonein = false;
bool m_has_member_statuses = false;
bool m_is_locked = false;
bool m_add_replay = true;
std::string m_name;
std::string m_uuid;
DynamicZoneMember m_leader;
@@ -230,15 +182,12 @@ protected:
DynamicZoneLocation m_compass;
DynamicZoneLocation m_safereturn;
DynamicZoneLocation m_zonein;
std::chrono::seconds m_duration = {};
std::chrono::seconds m_duration;
std::chrono::time_point<std::chrono::system_clock> m_start_time;
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
std::vector<DynamicZoneMember> m_members;
std::vector<DzLockout> m_lockouts;
public:
void Unserialize(std::span<char> buf);
template<class Archive>
void serialize(Archive& archive)
{
@@ -253,8 +202,6 @@ public:
m_never_expires,
m_has_zonein,
m_has_member_statuses,
m_is_locked,
m_add_replay,
m_name,
m_uuid,
m_leader,
@@ -265,8 +212,7 @@ public:
m_duration,
m_start_time,
m_expire_time,
m_members,
m_lockouts
m_members
);
}
};
-92
View File
@@ -1,92 +0,0 @@
#include "dynamic_zone_lockout.h"
#include "strings.h"
#include "rulesys.h"
#include "util/uuid.h"
#include <fmt/format.h>
#include <cereal/types/chrono.hpp>
DzLockout::DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration)
: m_uuid(std::move(uuid))
, m_name(std::move(expedition))
, m_event(std::move(event))
, m_expire_time(std::chrono::system_clock::from_time_t(expire_time))
, m_duration(duration)
{
m_is_replay = m_event == ReplayTimer;
}
DzLockout::DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout)
: m_uuid(std::move(lockout.from_expedition_uuid))
, m_name(name)
, m_event(std::move(lockout.event_name))
, m_expire_time(std::chrono::system_clock::from_time_t(lockout.expire_time))
, m_duration(lockout.duration)
{
m_is_replay = m_event == ReplayTimer;
}
DzLockout DzLockout::Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid)
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
if (uuid.empty())
{
uuid = EQ::Util::UUID::Generate().ToString();
}
DzLockout lockout{uuid, expedition, event, 0, seconds};
lockout.Reset(); // sets expire time
return lockout;
}
uint32_t DzLockout::GetSecondsRemaining() const
{
auto now = std::chrono::system_clock::now();
if (m_expire_time > now)
{
auto remaining = m_expire_time - now;
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
}
return 0;
}
DzLockout::TimeStrings DzLockout::GetTimeRemainingStrs() const
{
auto seconds = GetSecondsRemaining();
return DzLockout::TimeStrings{
fmt::format_int(seconds / 86400).str(), // days
fmt::format_int(seconds / 3600 % 24).str(), // hours
fmt::format_int(seconds / 60 % 60).str(), // minutes
fmt::format_int(seconds % 60).str() // seconds
};
}
bool DzLockout::IsSame(const DzLockout& other) const
{
return other.IsSame(m_name, m_event);
}
bool DzLockout::IsSame(const std::string& expedition, const std::string& event) const
{
return m_name == expedition && m_event == event;
}
void DzLockout::AddLockoutTime(int seconds)
{
seconds = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
auto start_time = m_expire_time - m_duration;
m_duration = std::chrono::seconds(new_duration);
m_expire_time = start_time + m_duration;
}
template <typename T>
void DzLockout::serialize(T& archive)
{
archive(m_is_replay, m_uuid, m_name, m_event, m_duration, m_expire_time);
}
template void DzLockout::serialize(cereal::BinaryOutputArchive&);
template void DzLockout::serialize(cereal::BinaryInputArchive&);
-56
View File
@@ -1,56 +0,0 @@
#pragma once
#include <chrono>
#include <string>
#include "repositories/base/base_dynamic_zone_lockouts_repository.h"
class DzLockout
{
public:
DzLockout() = default;
DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration);
DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout);
static constexpr char ReplayTimer[] = "Replay Timer";
static DzLockout Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid = {});
struct TimeStrings
{
std::string days;
std::string hours;
std::string mins;
std::string secs;
};
void AddLockoutTime(int seconds);
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
uint32_t GetSecondsRemaining() const;
TimeStrings GetTimeRemainingStrs() const;
const std::string& DzName() const { return m_name; }
const std::string& Event() const { return m_event; }
const std::string& UUID() const { return m_uuid; }
bool IsEvent(std::string_view event) const { return m_event == event; }
bool IsExpired() const { return GetSecondsRemaining() == 0; }
bool IsReplay() const { return m_is_replay; }
bool IsSame(const DzLockout& other) const;
bool IsSame(const std::string& expedition, const std::string& event) const;
bool IsUUID(const std::string& uuid) const { return uuid == m_uuid; }
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
void SetUUID(const std::string& uuid) { m_uuid = uuid; }
template <typename T>
void serialize(T& archive);
private:
bool m_is_replay = false;
std::string m_uuid; // dz received in
std::string m_name;
std::string m_event;
std::chrono::seconds m_duration = {};
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
};
+355 -94
View File
@@ -59,40 +59,103 @@ int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
return local_array[inv_type];
}
uint32 Bug::GetID(const std::string& category_name)
{
for (const auto& e : bug_category_names) {
if (e.second == category_name) {
return e.first;
}
const char* EQ::bug::CategoryIDToCategoryName(CategoryID category_id) {
switch (category_id) {
case catVideo:
return "Video";
case catAudio:
return "Audio";
case catPathing:
return "Pathing";
case catQuest:
return "Quest";
case catTradeskills:
return "Tradeskills";
case catSpellStacking:
return "Spell stacking";
case catDoorsPortals:
return "Doors/Portals";
case catItems:
return "Items";
case catNPC:
return "NPC";
case catDialogs:
return "Dialogs";
case catLoNTCG:
return "LoN - TCG";
case catMercenaries:
return "Mercenaries";
case catOther:
default:
return "Other";
}
}
EQ::bug::CategoryID EQ::bug::CategoryNameToCategoryID(const char* category_name) {
if (!category_name)
return catOther;
if (!strcmp(category_name, "Video"))
return catVideo;
if (!strcmp(category_name, "Audio"))
return catAudio;
if (!strcmp(category_name, "Pathing"))
return catPathing;
if (!strcmp(category_name, "Quest"))
return catQuest;
if (!strcmp(category_name, "Tradeskills"))
return catTradeskills;
if (!strcmp(category_name, "Spell stacking"))
return catSpellStacking;
if (!strcmp(category_name, "Doors/Portals"))
return catDoorsPortals;
if (!strcmp(category_name, "Items"))
return catItems;
if (!strcmp(category_name, "NPC"))
return catNPC;
if (!strcmp(category_name, "Dialogs"))
return catDialogs;
if (!strcmp(category_name, "LoN - TCG"))
return catLoNTCG;
if (!strcmp(category_name, "Mercenaries"))
return catMercenaries;
return catOther;
}
const char *EQ::constants::GetStanceName(StanceType stance_type) {
switch (stance_type) {
case stanceUnknown:
return "Unknown";
case stancePassive:
return "Passive";
case stanceBalanced:
return "Balanced";
case stanceEfficient:
return "Efficient";
case stanceReactive:
return "Reactive";
case stanceAggressive:
return "Aggressive";
case stanceAssist:
return "Assist";
case stanceBurn:
return "Burn";
case stanceEfficient2:
return "Efficient2";
case stanceBurnAE:
return "BurnAE";
default:
return "Invalid";
}
}
int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
if (EQ::ValueWithin(stance_type, EQ::constants::stancePassive, EQ::constants::stanceBurnAE)) {
return (stance_type - EQ::constants::stancePassive);
}
return Bug::Category::Other;
}
std::string Bug::GetName(uint32 category_id)
{
return IsValid(category_id) ? bug_category_names[category_id] : "UNKNOWN BUG CATEGORY";
}
bool Bug::IsValid(uint32 category_id)
{
return bug_category_names.find(category_id) != bug_category_names.end();
}
std::string Stance::GetName(uint8 stance_id)
{
return IsValid(stance_id) ? stance_names[stance_id] : "UNKNOWN STANCE";
}
bool Stance::IsValid(uint8 stance_id)
{
return stance_names.find(stance_id) != stance_names.end();
}
uint8 Stance::GetIndex(uint8 stance_id)
{
return IsValid(stance_id) ? (stance_id - Stance::Passive) : 0;
return 0;
}
const std::map<uint8, std::string>& EQ::constants::GetLanguageMap()
@@ -140,6 +203,29 @@ std::string EQ::constants::GetLanguageName(uint8 language_id)
return EQ::constants::GetLanguageMap().find(language_id)->second;
}
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 std::string();
}
return EQ::constants::GetLDoNThemeMap().find(theme_id)->second;
}
const std::map<int8, std::string>& EQ::constants::GetFlyModeMap()
{
static const std::map<int8, std::string> flymode_map = {
@@ -163,6 +249,102 @@ std::string EQ::constants::GetFlyModeName(int8 flymode_id)
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
}
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 = {
@@ -253,6 +435,84 @@ std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
}
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
{
static const std::map<int, std::string> object_type_map = {
{ ObjectTypes::SmallBag, "Small Bag" },
{ ObjectTypes::LargeBag, "Large Bag" },
{ ObjectTypes::Quiver, "Quiver" },
{ ObjectTypes::BeltPouch, "Belt Pouch" },
{ ObjectTypes::WristPouch, "Wrist Pouch" },
{ ObjectTypes::Backpack, "Backpack" },
{ ObjectTypes::SmallChest, "Small Chest" },
{ ObjectTypes::LargeChest, "Large Chest" },
{ ObjectTypes::Bandolier, "Bandolier" },
{ ObjectTypes::Medicine, "Medicine" },
{ ObjectTypes::Tinkering, "Tinkering" },
{ ObjectTypes::Lexicon, "Lexicon" },
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
{ ObjectTypes::Quest, "Quest" },
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
{ ObjectTypes::Baking, "Baking" },
{ ObjectTypes::Tailoring, "Tailoring" },
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
{ ObjectTypes::Fletching, "Fletching" },
{ ObjectTypes::Brewing, "Brewing" },
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
{ ObjectTypes::Pottery, "Pottery" },
{ ObjectTypes::Kiln, "Kiln" },
{ ObjectTypes::KeyMaker, "Key Maker" },
{ ObjectTypes::ResearchWIZ, "Lexicon" },
{ ObjectTypes::ResearchMAG, "Lexicon" },
{ ObjectTypes::ResearchNEC, "Lexicon" },
{ ObjectTypes::ResearchENC, "Lexicon" },
{ ObjectTypes::Unknown, "Unknown" },
{ ObjectTypes::ResearchPractice, "Lexicon" },
{ ObjectTypes::Alchemy, "Alchemy" },
{ ObjectTypes::HighElfForge, "High Elf Forge" },
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
{ ObjectTypes::OgreForge, "Ogre Forge" },
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
{ ObjectTypes::GnomeForge, "Gnome Forge" },
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
{ ObjectTypes::IksarForge, "Iksar Forge" },
{ ObjectTypes::HumanForgeOne, "Human Forge" },
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
{ ObjectTypes::Fishing, "Fishing" },
{ ObjectTypes::TrollForge, "Troll Forge" },
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
{ ObjectTypes::HalflingForge, "Halfling Forge" },
{ ObjectTypes::EruditeForge, "Erudite Forge" },
{ ObjectTypes::Merchant, "Merchant" },
{ ObjectTypes::FroglokForge, "Froglok Forge" },
{ ObjectTypes::Augmenter, "Augmenter" },
{ ObjectTypes::Churn, "Churn" },
{ ObjectTypes::TransformationMold, "Transformation Mold" },
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
{ ObjectTypes::Unattuner, "Unattuner" },
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
{ ObjectTypes::NoDeposit, "No Deposit" }
};
return object_type_map;
}
std::string EQ::constants::GetObjectTypeName(int object_type)
{
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
return std::string();
}
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
}
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
{
static const std::map<uint8, std::string> weather_type_map = {
@@ -380,74 +640,75 @@ std::string EQ::constants::GetAppearanceTypeName(uint32 appearance_type)
return std::string();
}
std::string SpecialAbility::GetName(int ability_id)
const std::map<uint32, std::string>& EQ::constants::GetSpecialAbilityMap()
{
return IsValid(ability_id) ? special_ability_names[ability_id] : "UNKNOWN SPECIAL ABILITY";
}
bool SpecialAbility::IsValid(int ability_id)
{
return special_ability_names.find(ability_id) != special_ability_names.end();
}
const std::map<uint32, std::string>& EQ::constants::GetConsiderColorMap()
{
static const std::map<uint32, std::string> consider_color_map = {
{ ConsiderColor::Green, "Green" },
{ ConsiderColor::DarkBlue, "Dark Blue" },
{ ConsiderColor::Gray, "Gray" },
{ ConsiderColor::White, "White" },
{ ConsiderColor::Red, "Red" },
{ ConsiderColor::Yellow, "Yellow" },
{ ConsiderColor::LightBlue, "Light Blue" },
{ ConsiderColor::WhiteTitanium, "White" },
static const std::map<uint32, std::string> special_ability_map = {
{ SPECATK_SUMMON, "Summon" },
{ SPECATK_ENRAGE, "Enrage" },
{ SPECATK_RAMPAGE, "Rampage" },
{ SPECATK_AREA_RAMPAGE, "Area Rampage" },
{ SPECATK_FLURRY, "Flurry" },
{ SPECATK_TRIPLE, "Triple Attack" },
{ SPECATK_QUAD, "Quadruple Attack" },
{ SPECATK_INNATE_DW, "Dual Wield" },
{ SPECATK_BANE, "Bane Attack" },
{ SPECATK_MAGICAL, "Magical Attack" },
{ SPECATK_RANGED_ATK, "Ranged Attack" },
{ UNSLOWABLE, "Immune to Slow" },
{ UNMEZABLE, "Immune to Mesmerize" },
{ UNCHARMABLE, "Immune to Charm" },
{ UNSTUNABLE, "Immune to Stun" },
{ UNSNAREABLE, "Immune to Snare" },
{ UNFEARABLE, "Immune to Fear" },
{ UNDISPELLABLE, "Immune to Dispell" },
{ IMMUNE_MELEE, "Immune to Melee" },
{ IMMUNE_MAGIC, "Immune to Magic" },
{ IMMUNE_FLEEING, "Immune to Fleeing" },
{ IMMUNE_MELEE_EXCEPT_BANE, "Immune to Melee except Bane" },
{ IMMUNE_MELEE_NONMAGICAL, "Immune to Non-Magical Melee" },
{ IMMUNE_AGGRO, "Immune to Aggro" },
{ IMMUNE_AGGRO_ON, "Immune to Being Aggro" },
{ IMMUNE_CASTING_FROM_RANGE, "Immune to Ranged Spells" },
{ IMMUNE_FEIGN_DEATH, "Immune to Feign Death" },
{ IMMUNE_TAUNT, "Immune to Taunt" },
{ NPC_TUNNELVISION, "Tunnel Vision" },
{ NPC_NO_BUFFHEAL_FRIENDS, "Does Not Heal of Buff Allies" },
{ IMMUNE_PACIFY, "Immune to Pacify" },
{ LEASH, "Leashed" },
{ TETHER, "Tethered" },
{ DESTRUCTIBLE_OBJECT, "Destructible Object" },
{ NO_HARM_FROM_CLIENT, "Immune to Harm from Client" },
{ ALWAYS_FLEE, "Always Flees" },
{ FLEE_PERCENT, "Flee Percentage" },
{ ALLOW_BENEFICIAL, "Allows Beneficial Spells" },
{ DISABLE_MELEE, "Melee is Disabled" },
{ NPC_CHASE_DISTANCE, "Chase Distance" },
{ ALLOW_TO_TANK, "Allowed to Tank" },
{ IGNORE_ROOT_AGGRO_RULES, "Ignores Root Aggro" },
{ CASTING_RESIST_DIFF, "Casting Resist Difficulty" },
{ COUNTER_AVOID_DAMAGE, "Counter Damage Avoidance" },
{ PROX_AGGRO, "Proximity Aggro" },
{ IMMUNE_RANGED_ATTACKS, "Immune to Ranged Attacks" },
{ IMMUNE_DAMAGE_CLIENT, "Immune to Client Damage" },
{ IMMUNE_DAMAGE_NPC, "Immune to NPC Damage" },
{ IMMUNE_AGGRO_CLIENT, "Immune to Client Aggro" },
{ IMMUNE_AGGRO_NPC, "Immune to NPC Aggro" },
{ MODIFY_AVOID_DAMAGE, "Modify Damage Avoidance" },
{ IMMUNE_FADING_MEMORIES, "Immune to Memory Fades" },
{ IMMUNE_OPEN, "Immune to Open" },
{ IMMUNE_ASSASSINATE, "Immune to Assassinate" },
{ IMMUNE_HEADSHOT, "Immune to Headshot" },
};
return consider_color_map;
return special_ability_map;
}
std::string EQ::constants::GetConsiderColorName(uint32 consider_color)
std::string EQ::constants::GetSpecialAbilityName(uint32 ability_id)
{
const auto& c = EQ::constants::GetConsiderColorMap().find(consider_color);
return c != EQ::constants::GetConsiderColorMap().end() ? c->second : std::string();
}
std::string AccountStatus::GetName(uint8 account_status)
{
for (
auto e = account_status_names.rbegin();
e != account_status_names.rend();
++e
) {
if (account_status >= e->first) {
return e->second;
}
const auto& a = EQ::constants::GetSpecialAbilityMap().find(ability_id);
if (a != EQ::constants::GetSpecialAbilityMap().end()) {
return a->second;
}
return "UNKNOWN ACCOUNT STATUS";
}
std::string ComparisonType::GetName(uint8 type)
{
return IsValid(type) ? comparison_types[type] : "UNKNOWN COMPARISON TYPE";
}
bool ComparisonType::IsValid(uint8 type)
{
return comparison_types.find(type) != comparison_types.end();
}
uint32 LDoNTheme::GetBitmask(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].second : LDoNTheme::UnusedBit;
}
std::string LDoNTheme::GetName(uint32 theme_id)
{
return IsValid(theme_id) ? ldon_theme_names[theme_id].first : "UNKNOWN LDON THEME";
}
bool LDoNTheme::IsValid(uint32 theme_id)
{
return ldon_theme_names.find(theme_id) != ldon_theme_names.end();
return std::string();
}
+254 -362
View File
@@ -26,76 +26,6 @@
#include <string.h>
namespace AccountStatus {
constexpr uint8 Player = 0;
constexpr uint8 Steward = 10;
constexpr uint8 ApprenticeGuide = 20;
constexpr uint8 Guide = 50;
constexpr uint8 QuestTroupe = 80;
constexpr uint8 SeniorGuide = 81;
constexpr uint8 GMTester = 85;
constexpr uint8 EQSupport = 90;
constexpr uint8 GMStaff = 95;
constexpr uint8 GMAdmin = 100;
constexpr uint8 GMLeadAdmin = 150;
constexpr uint8 QuestMaster = 160;
constexpr uint8 GMAreas = 170;
constexpr uint8 GMCoder = 180;
constexpr uint8 GMMgmt = 200;
constexpr uint8 GMImpossible = 250;
constexpr uint8 Max = 255;
std::string GetName(uint8 account_status);
}
static std::map<uint8, std::string> account_status_names = {
{ 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" }
};
namespace ComparisonType {
constexpr uint8 Equal = 0;
constexpr uint8 NotEqual = 1;
constexpr uint8 GreaterOrEqual = 2;
constexpr uint8 LesserOrEqual = 3;
constexpr uint8 Greater = 4;
constexpr uint8 Lesser = 5;
constexpr uint8 Any = 6;
constexpr uint8 NotAny = 7;
constexpr uint8 Between = 8;
constexpr uint8 NotBetween = 9;
std::string GetName(uint8 type);
bool IsValid(uint8 type);
}
static std::map<uint8, std::string> comparison_types = {
{ ComparisonType::Equal, "Equal" },
{ ComparisonType::NotEqual, "Not Equal" },
{ ComparisonType::GreaterOrEqual, "Greater or Equal" },
{ ComparisonType::LesserOrEqual, "Lesser or Equal" },
{ ComparisonType::Greater, "Greater" },
{ ComparisonType::Lesser, "Lesser" },
{ ComparisonType::Any, "Any" },
{ ComparisonType::NotAny, "Not Any" },
{ ComparisonType::Between, "Between" },
{ ComparisonType::NotBetween, "Not Between" },
};
// local definitions are the result of using hybrid-client or server-only values and methods
namespace EQ
@@ -130,11 +60,9 @@ namespace EQ
using RoF2::invtype::MAIL_SIZE;
using RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE;
using RoF2::invtype::KRONO_SIZE;
using RoF2::invtype::GUILD_BANK_MAIN_SIZE;
using RoF2::invtype::GUILD_BANK_DEPOSIT_SIZE;
using RoF2::invtype::OTHER_SIZE;
using RoF2::invtype::TRADE_NPC_SIZE;
using Titanium::invtype::TRADE_NPC_SIZE;
using RoF2::invtype::TYPE_INVALID;
using RoF2::invtype::TYPE_BEGIN;
@@ -161,7 +89,7 @@ namespace EQ
using RoF2::invslot::SLOT_INVALID;
using RoF2::invslot::SLOT_BEGIN;
using RoF2::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
using Titanium::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
const int16 SLOT_AUGMENT_GENERIC_RETURN = 1001; // clients don't appear to use this method... (internal inventory return value)
@@ -181,28 +109,28 @@ namespace EQ
using RoF2::invslot::BONUS_STAT_END;
using RoF2::invslot::BONUS_SKILL_END;
using RoF2::invslot::BANK_BEGIN;
using RoF2::invslot::BANK_END;
using Titanium::invslot::BANK_BEGIN;
using SoF::invslot::BANK_END;
using RoF2::invslot::SHARED_BANK_BEGIN;
using RoF2::invslot::SHARED_BANK_END;
using Titanium::invslot::SHARED_BANK_BEGIN;
using Titanium::invslot::SHARED_BANK_END;
using RoF2::invslot::TRADE_BEGIN;
using RoF2::invslot::TRADE_END;
using Titanium::invslot::TRADE_BEGIN;
using Titanium::invslot::TRADE_END;
using RoF2::invslot::TRADE_NPC_END;
using Titanium::invslot::TRADE_NPC_END;
using RoF2::invslot::WORLD_BEGIN;
using RoF2::invslot::WORLD_END;
using Titanium::invslot::WORLD_BEGIN;
using Titanium::invslot::WORLD_END;
using RoF2::invslot::TRIBUTE_BEGIN;
using RoF2::invslot::TRIBUTE_END;
using Titanium::invslot::TRIBUTE_BEGIN;
using Titanium::invslot::TRIBUTE_END;
using RoF2::invslot::GUILD_TRIBUTE_BEGIN;
using RoF2::invslot::GUILD_TRIBUTE_END;
using Titanium::invslot::GUILD_TRIBUTE_BEGIN;
using Titanium::invslot::GUILD_TRIBUTE_END;
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor;
const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor;
using RoF2::invslot::EQUIPMENT_BITMASK;
using RoF2::invslot::GENERAL_BITMASK;
@@ -216,40 +144,38 @@ namespace EQ
} // namespace invslot
namespace invbag {
using RoF2::invbag::SLOT_INVALID;
using RoF2::invbag::SLOT_BEGIN;
using RoF2::invbag::SLOT_END;
using RoF2::invbag::SLOT_COUNT;
using Titanium::invbag::SLOT_INVALID;
using Titanium::invbag::SLOT_BEGIN;
using Titanium::invbag::SLOT_END;
using Titanium::invbag::SLOT_COUNT;
using RoF2::invslot::WORLD_END;
const int16 GENERAL_BAGS_BEGIN = WORLD_END + 1;
using Titanium::invbag::GENERAL_BAGS_BEGIN;
const int16 GENERAL_BAGS_COUNT = invslot::GENERAL_COUNT * SLOT_COUNT;
const int16 GENERAL_BAGS_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_COUNT) - 1;
const int16 GENERAL_BAGS_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_COUNT) - 1;
const int16 GENERAL_BAGS_8_COUNT = 8 * SLOT_COUNT;
const int16 GENERAL_BAGS_8_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_8_COUNT) - 1;
const int16 GENERAL_BAGS_8_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_8_COUNT) - 1;
const int16 CURSOR_BAG_BEGIN = GENERAL_BAGS_END + 1;
const int16 CURSOR_BAG_BEGIN = 351;
const int16 CURSOR_BAG_COUNT = SLOT_COUNT;
const int16 CURSOR_BAG_END = (CURSOR_BAG_BEGIN + CURSOR_BAG_COUNT) - 1;
const int16 CURSOR_BAG_END = (CURSOR_BAG_BEGIN + CURSOR_BAG_COUNT) - 1;
const int16 BANK_BAGS_BEGIN = CURSOR_BAG_END + 1;
using Titanium::invbag::BANK_BAGS_BEGIN;
const int16 BANK_BAGS_COUNT = (invtype::BANK_SIZE * SLOT_COUNT);
const int16 BANK_BAGS_END = (BANK_BAGS_BEGIN + BANK_BAGS_COUNT) - 1;
const int16 BANK_BAGS_END = (BANK_BAGS_BEGIN + BANK_BAGS_COUNT) - 1;
const int16 BANK_BAGS_16_COUNT = 16 * SLOT_COUNT;
const int16 BANK_BAGS_16_END = (BANK_BAGS_BEGIN + BANK_BAGS_16_COUNT) - 1;
const int16 BANK_BAGS_16_END = (BANK_BAGS_BEGIN + BANK_BAGS_16_COUNT) - 1;
const int16 SHARED_BANK_BAGS_BEGIN = BANK_BAGS_END + 1;
using Titanium::invbag::SHARED_BANK_BAGS_BEGIN;
const int16 SHARED_BANK_BAGS_COUNT = invtype::SHARED_BANK_SIZE * SLOT_COUNT;
const int16 SHARED_BANK_BAGS_END = (SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_COUNT) - 1;
const int16 SHARED_BANK_BAGS_END = (SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_COUNT) - 1;
const int16 TRADE_BAGS_BEGIN = SHARED_BANK_BAGS_END + 1;
using Titanium::invbag::TRADE_BAGS_BEGIN;
const int16 TRADE_BAGS_COUNT = invtype::TRADE_SIZE * SLOT_COUNT;
const int16 TRADE_BAGS_END = (TRADE_BAGS_BEGIN + TRADE_BAGS_COUNT) - 1;
const int16 TRADE_BAGS_END = (TRADE_BAGS_BEGIN + TRADE_BAGS_COUNT) - 1;
using RoF2::invbag::GetInvBagIndexName;
using Titanium::invbag::GetInvBagIndexName;
} // namespace invbag
@@ -278,6 +204,19 @@ namespace EQ
const size_t SAY_LINK_CLOSER_SIZE = 1;
const size_t SAY_LINK_MAXIMUM_SIZE = (SAY_LINK_OPENER_SIZE + SAY_LINK_BODY_SIZE + SAY_LINK_TEXT_SIZE + SAY_LINK_CLOSER_SIZE);
enum StanceType : int {
stanceUnknown = 0,
stancePassive,
stanceBalanced,
stanceEfficient,
stanceReactive,
stanceAggressive,
stanceAssist,
stanceBurn,
stanceEfficient2,
stanceBurnAE
};
enum BotSpellIDs : int {
Warrior = 3001,
Cleric,
@@ -328,6 +267,70 @@ namespace EQ
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,
@@ -353,12 +356,24 @@ namespace EQ
Proximity
};
const char *GetStanceName(StanceType stance_type);
int ConvertStanceTypeToIndex(StanceType stance_type);
extern const std::map<uint8, std::string>& GetLanguageMap();
std::string GetLanguageName(uint8 language_id);
extern const std::map<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);
@@ -371,6 +386,9 @@ namespace EQ
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);
@@ -383,8 +401,12 @@ namespace EQ
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
std::string GetAppearanceTypeName(uint32 animation_type);
extern const std::map<uint32, std::string>& GetConsiderColorMap();
std::string GetConsiderColorName(uint32 consider_color);
extern const std::map<uint32, std::string>& GetSpecialAbilityMap();
std::string GetSpecialAbilityName(uint32 ability_id);
const int STANCE_TYPE_FIRST = stancePassive;
const int STANCE_TYPE_LAST = stanceBurnAE;
const int STANCE_TYPE_COUNT = stanceBurnAE;
} /*constants*/
@@ -439,6 +461,37 @@ namespace EQ
} // namespace spells
namespace bug {
enum CategoryID : uint32 {
catOther = 0,
catVideo,
catAudio,
catPathing,
catQuest,
catTradeskills,
catSpellStacking,
catDoorsPortals,
catItems,
catNPC,
catDialogs,
catLoNTCG,
catMercenaries
};
enum OptionalInfoFlag : uint32 {
infoNoOptionalInfo = 0x0,
infoCanDuplicate = 0x1,
infoCrashBug = 0x2,
infoTargetInfo = 0x4,
infoCharacterFlags = 0x8,
infoUnknownValue = 0xFFFFFFF0
};
const char* CategoryIDToCategoryName(CategoryID category_id);
CategoryID CategoryNameToCategoryID(const char* category_name);
} // namespace bug
enum WaypointStatus : int {
RoamBoxPauseInProgress = -3,
QuestControlNoGrid = -2,
@@ -452,7 +505,7 @@ namespace EQ
Raid,
Guild
};
};
}; // namespace consent
} /*EQEmu*/
enum ServerLockType : int {
@@ -461,6 +514,26 @@ enum ServerLockType : int {
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,
@@ -486,17 +559,6 @@ enum ConsiderLevel : uint8 {
Scowls
};
namespace ConsiderColor {
constexpr uint32 Green = 2;
constexpr uint32 DarkBlue = 4;
constexpr uint32 Gray = 6;
constexpr uint32 White = 10;
constexpr uint32 Red = 13;
constexpr uint32 Yellow = 15;
constexpr uint32 LightBlue = 18;
constexpr uint32 WhiteTitanium = 20;
};
enum TargetDescriptionType : uint8 {
LCSelf,
UCSelf,
@@ -512,6 +574,19 @@ enum ReloadWorld : uint8 {
ForceRepop
};
enum BucketComparison : uint8 {
BucketEqualTo = 0,
BucketNotEqualTo,
BucketGreaterThanOrEqualTo,
BucketLesserThanOrEqualTo,
BucketGreaterThan,
BucketLesserThan,
BucketIsAny,
BucketIsNotAny,
BucketIsBetween,
BucketIsNotBetween
};
enum class EntityFilterType {
All,
Bots,
@@ -525,132 +600,66 @@ enum class ApplySpellType {
Raid
};
namespace SpecialAbility {
constexpr int Summon = 1;
constexpr int Enrage = 2;
constexpr int Rampage = 3;
constexpr int AreaRampage = 4;
constexpr int Flurry = 5;
constexpr int TripleAttack = 6;
constexpr int QuadrupleAttack = 7;
constexpr int DualWield = 8;
constexpr int BaneAttack = 9;
constexpr int MagicalAttack = 10;
constexpr int RangedAttack = 11;
constexpr int SlowImmunity = 12;
constexpr int MesmerizeImmunity = 13;
constexpr int CharmImmunity = 14;
constexpr int StunImmunity = 15;
constexpr int SnareImmunity = 16;
constexpr int FearImmunity = 17;
constexpr int DispellImmunity = 18;
constexpr int MeleeImmunity = 19;
constexpr int MagicImmunity = 20;
constexpr int FleeingImmunity = 21;
constexpr int MeleeImmunityExceptBane = 22;
constexpr int MeleeImmunityExceptMagical = 23;
constexpr int AggroImmunity = 24;
constexpr int BeingAggroImmunity = 25;
constexpr int CastingFromRangeImmunity = 26;
constexpr int FeignDeathImmunity = 27;
constexpr int TauntImmunity = 28;
constexpr int TunnelVision = 29;
constexpr int NoBuffHealFriends = 30;
constexpr int PacifyImmunity = 31;
constexpr int Leash = 32;
constexpr int Tether = 33;
constexpr int DestructibleObject = 34;
constexpr int HarmFromClientImmunity = 35;
constexpr int AlwaysFlee = 36;
constexpr int FleePercent = 37;
constexpr int AllowBeneficial = 38;
constexpr int DisableMelee = 39;
constexpr int NPCChaseDistance = 40;
constexpr int AllowedToTank = 41;
constexpr int IgnoreRootAggroRules = 42;
constexpr int CastingResistDifficulty = 43;
constexpr int CounterAvoidDamage = 44;
constexpr int ProximityAggro = 45;
constexpr int RangedAttackImmunity = 46;
constexpr int ClientDamageImmunity = 47;
constexpr int NPCDamageImmunity = 48;
constexpr int ClientAggroImmunity = 49;
constexpr int NPCAggroImmunity = 50;
constexpr int ModifyAvoidDamage = 51;
constexpr int MemoryFadeImmunity = 52;
constexpr int OpenImmunity = 53;
constexpr int AssassinateImmunity = 54;
constexpr int HeadshotImmunity = 55;
constexpr int BotAggroImmunity = 56;
constexpr int BotDamageImmunity = 57;
constexpr int Max = 58;
constexpr int MaxParameters = 9;
std::string GetName(int ability_id);
bool IsValid(int ability_id);
}
static std::map<int, std::string> special_ability_names = {
{ SpecialAbility::Summon, "Summon" },
{ SpecialAbility::Enrage, "Enrage" },
{ SpecialAbility::Rampage, "Rampage" },
{ SpecialAbility::AreaRampage, "Area Rampage" },
{ SpecialAbility::Flurry, "Flurry" },
{ SpecialAbility::TripleAttack, "Triple Attack" },
{ SpecialAbility::QuadrupleAttack, "Quadruple Attack" },
{ SpecialAbility::DualWield, "Dual Wield" },
{ SpecialAbility::BaneAttack, "Bane Attack" },
{ SpecialAbility::MagicalAttack, "Magical Attack" },
{ SpecialAbility::RangedAttack, "Ranged Attack" },
{ SpecialAbility::SlowImmunity, "Immune to Slow" },
{ SpecialAbility::MesmerizeImmunity, "Immune to Mesmerize" },
{ SpecialAbility::CharmImmunity, "Immune to Charm" },
{ SpecialAbility::StunImmunity, "Immune to Stun" },
{ SpecialAbility::SnareImmunity, "Immune to Snare" },
{ SpecialAbility::FearImmunity, "Immune to Fear" },
{ SpecialAbility::DispellImmunity, "Immune to Dispell" },
{ SpecialAbility::MeleeImmunity, "Immune to Melee" },
{ SpecialAbility::MagicImmunity, "Immune to Magic" },
{ SpecialAbility::FleeingImmunity, "Immune to Fleeing" },
{ SpecialAbility::MeleeImmunityExceptBane, "Immune to Melee except Bane" },
{ SpecialAbility::MeleeImmunityExceptMagical, "Immune to Non-Magical Melee" },
{ SpecialAbility::AggroImmunity, "Immune to Aggro" },
{ SpecialAbility::BeingAggroImmunity, "Immune to Being Aggro" },
{ SpecialAbility::CastingFromRangeImmunity, "Immune to Ranged Spells" },
{ SpecialAbility::FeignDeathImmunity, "Immune to Feign Death" },
{ SpecialAbility::TauntImmunity, "Immune to Taunt" },
{ SpecialAbility::TunnelVision, "Tunnel Vision" },
{ SpecialAbility::NoBuffHealFriends, "Does Not Heal or Buff Allies" },
{ SpecialAbility::PacifyImmunity, "Immune to Pacify" },
{ SpecialAbility::Leash, "Leashed" },
{ SpecialAbility::Tether, "Tethered" },
{ SpecialAbility::DestructibleObject, "Destructible Object" },
{ SpecialAbility::HarmFromClientImmunity, "Immune to Harm from Client" },
{ SpecialAbility::AlwaysFlee, "Always Flees" },
{ SpecialAbility::FleePercent, "Flee Percentage" },
{ SpecialAbility::AllowBeneficial, "Allows Beneficial Spells" },
{ SpecialAbility::DisableMelee, "Melee is Disabled" },
{ SpecialAbility::NPCChaseDistance, "Chase Distance" },
{ SpecialAbility::AllowedToTank, "Allowed to Tank" },
{ SpecialAbility::IgnoreRootAggroRules, "Ignores Root Aggro" },
{ SpecialAbility::CastingResistDifficulty, "Casting Resist Difficulty" },
{ SpecialAbility::CounterAvoidDamage, "Counter Damage Avoidance" },
{ SpecialAbility::ProximityAggro, "Proximity Aggro" },
{ SpecialAbility::RangedAttackImmunity, "Immune to Ranged Attacks" },
{ SpecialAbility::ClientDamageImmunity, "Immune to Client Damage" },
{ SpecialAbility::NPCDamageImmunity, "Immune to NPC Damage" },
{ SpecialAbility::ClientAggroImmunity, "Immune to Client Aggro" },
{ SpecialAbility::NPCAggroImmunity, "Immune to NPC Aggro" },
{ SpecialAbility::ModifyAvoidDamage, "Modify Damage Avoidance" },
{ SpecialAbility::MemoryFadeImmunity, "Immune to Memory Fades" },
{ SpecialAbility::OpenImmunity, "Immune to Open" },
{ SpecialAbility::AssassinateImmunity, "Immune to Assassinate" },
{ SpecialAbility::HeadshotImmunity, "Immune to Headshot" },
{ SpecialAbility::BotAggroImmunity, "Immune to Bot Aggro" },
{ SpecialAbility::BotDamageImmunity, "Immune to Bot Damage" },
enum {
SPECATK_SUMMON = 1,
SPECATK_ENRAGE = 2,
SPECATK_RAMPAGE = 3,
SPECATK_AREA_RAMPAGE = 4,
SPECATK_FLURRY = 5,
SPECATK_TRIPLE = 6,
SPECATK_QUAD = 7,
SPECATK_INNATE_DW = 8,
SPECATK_BANE = 9,
SPECATK_MAGICAL = 10,
SPECATK_RANGED_ATK = 11,
UNSLOWABLE = 12,
UNMEZABLE = 13,
UNCHARMABLE = 14,
UNSTUNABLE = 15,
UNSNAREABLE = 16,
UNFEARABLE = 17,
UNDISPELLABLE = 18,
IMMUNE_MELEE = 19,
IMMUNE_MAGIC = 20,
IMMUNE_FLEEING = 21,
IMMUNE_MELEE_EXCEPT_BANE = 22,
IMMUNE_MELEE_NONMAGICAL = 23,
IMMUNE_AGGRO = 24,
IMMUNE_AGGRO_ON = 25,
IMMUNE_CASTING_FROM_RANGE = 26,
IMMUNE_FEIGN_DEATH = 27,
IMMUNE_TAUNT = 28,
NPC_TUNNELVISION = 29,
NPC_NO_BUFFHEAL_FRIENDS = 30,
IMMUNE_PACIFY = 31,
LEASH = 32,
TETHER = 33,
DESTRUCTIBLE_OBJECT = 34,
NO_HARM_FROM_CLIENT = 35,
ALWAYS_FLEE = 36,
FLEE_PERCENT = 37,
ALLOW_BENEFICIAL = 38,
DISABLE_MELEE = 39,
NPC_CHASE_DISTANCE = 40,
ALLOW_TO_TANK = 41,
IGNORE_ROOT_AGGRO_RULES = 42,
CASTING_RESIST_DIFF = 43,
COUNTER_AVOID_DAMAGE = 44, // Modify by percent NPC's opponents chance to riposte, block, parry or dodge individually, or for all skills
PROX_AGGRO = 45,
IMMUNE_RANGED_ATTACKS = 46,
IMMUNE_DAMAGE_CLIENT = 47,
IMMUNE_DAMAGE_NPC = 48,
IMMUNE_AGGRO_CLIENT = 49,
IMMUNE_AGGRO_NPC = 50,
MODIFY_AVOID_DAMAGE = 51, // Modify by percent the NPCs chance to riposte, block, parry or dodge individually, or for all skills
IMMUNE_FADING_MEMORIES = 52,
IMMUNE_OPEN = 53,
IMMUNE_ASSASSINATE = 54,
IMMUNE_HEADSHOT = 55,
MAX_SPECIAL_ATTACK = 56
};
namespace HeroicBonusBucket
{
const std::string WisMaxMana = "HWIS-MaxMana";
@@ -675,121 +684,4 @@ namespace HeroicBonusBucket
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
}
namespace Bug {
namespace Category {
constexpr uint32 Other = 0;
constexpr uint32 Video = 1;
constexpr uint32 Audio = 2;
constexpr uint32 Pathing = 3;
constexpr uint32 Quest = 4;
constexpr uint32 Tradeskills = 5;
constexpr uint32 SpellStacking = 6;
constexpr uint32 DoorsPortals = 7;
constexpr uint32 Items = 8;
constexpr uint32 NPC = 9;
constexpr uint32 Dialogs = 10;
constexpr uint32 LoNTCG = 11;
constexpr uint32 Mercenaries = 12;
}
namespace InformationFlag {
constexpr uint32 None = 0;
constexpr uint32 Repeatable = 1;
constexpr uint32 Crash = 2;
constexpr uint32 TargetInfo = 4;
constexpr uint32 CharacterFlags = 8;
constexpr uint32 Unknown = 4294967280;
}
uint32 GetID(const std::string& category_name);
std::string GetName(uint32 category_id);
bool IsValid(uint32 category_id);
}
static std::map<uint32, std::string> bug_category_names = {
{ Bug::Category::Other, "Other" },
{ Bug::Category::Video, "Video" },
{ Bug::Category::Audio, "Audio" },
{ Bug::Category::Pathing, "Pathing" },
{ Bug::Category::Quest, "Quest" },
{ Bug::Category::Tradeskills, "Tradeskills" },
{ Bug::Category::SpellStacking, "Spell Stacking" },
{ Bug::Category::DoorsPortals, "Doors and Portals" },
{ Bug::Category::Items, "Items" },
{ Bug::Category::NPC, "NPC" },
{ Bug::Category::Dialogs, "Dialogs" },
{ Bug::Category::LoNTCG, "LoN - TCG" },
{ Bug::Category::Mercenaries, "Mercenaries" }
};
namespace Stance {
constexpr uint32 Unknown = 0;
constexpr uint32 Passive = 1;
constexpr uint32 Balanced = 2;
constexpr uint32 Efficient = 3;
constexpr uint32 Reactive = 4;
constexpr uint32 Aggressive = 5;
constexpr uint32 Assist = 6;
constexpr uint32 Burn = 7;
constexpr uint32 Efficient2 = 8;
constexpr uint32 AEBurn = 9;
std::string GetName(uint8 stance_id);
uint8 GetIndex(uint8 stance_id);
bool IsValid(uint8 stance_id);
}
static std::map<uint32, std::string> stance_names = {
{ Stance::Unknown, "Unknown" },
{ Stance::Passive, "Passive" },
{ Stance::Balanced, "Balanced" },
{ Stance::Efficient, "Efficient" },
{ Stance::Reactive, "Reactive" },
{ Stance::Aggressive, "Aggressive" },
{ Stance::Assist, "Assist" },
{ Stance::Burn, "Burn" },
{ Stance::Efficient2, "Efficient" },
{ Stance::AEBurn, "AE Burn" }
};
namespace LDoNTheme {
constexpr uint32 Unused = 0;
constexpr uint32 GUK = 1;
constexpr uint32 MIR = 2;
constexpr uint32 MMC = 3;
constexpr uint32 RUJ = 4;
constexpr uint32 TAK = 5;
constexpr uint32 UnusedBit = 0;
constexpr uint32 GUKBit = 1;
constexpr uint32 MIRBit = 2;
constexpr uint32 MMCBit = 4;
constexpr uint32 RUJBit = 8;
constexpr uint32 TAKBit = 16;
uint32 GetBitmask(uint32 theme_id);
std::string GetName(uint32 theme_id);
bool IsValid(uint32 theme_id);
}
static std::map<uint32, std::pair<std::string, uint32>> ldon_theme_names = {
{ LDoNTheme::Unused, { "Unused", LDoNTheme::UnusedBit }, },
{ LDoNTheme::GUK, { "Deepest Guk", LDoNTheme::GUKBit }, },
{ LDoNTheme::MIR, { "Miragul's Menagerie", LDoNTheme::MIRBit }, },
{ LDoNTheme::MMC, { "Mistmoore Catacombs", LDoNTheme::MMCBit }, },
{ LDoNTheme::RUJ, { "Rujarkian Hills", LDoNTheme::RUJBit }, },
{ LDoNTheme::TAK, { "Takish-Hiz", LDoNTheme::TAKBit }, },
};
namespace PCNPCOnlyFlagType {
constexpr int PC = 1;
constexpr int NPC = 2;
}
namespace BookType {
constexpr uint8 Scroll = 0;
constexpr uint8 Book = 1;
constexpr uint8 ItemInfo = 2;
}
#endif /*COMMON_EMU_CONSTANTS_H*/
+1 -19
View File
@@ -35,7 +35,7 @@ N(OP_AltCurrencyMerchantRequest),
N(OP_AltCurrencyPurchase),
N(OP_AltCurrencyReclaim),
N(OP_AltCurrencySell),
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069
N(OP_AltCurrencySellSelection), // Used by eqstr_us.txt 8066, 8068, 8069
N(OP_Animation),
N(OP_AnnoyingZoneUnknown),
N(OP_ApplyPoison),
@@ -67,7 +67,6 @@ N(OP_Buff),
N(OP_BuffCreate),
N(OP_BuffRemoveRequest),
N(OP_Bug),
N(OP_BuyerItems),
N(OP_CameraEffect),
N(OP_Camp),
N(OP_CancelSneakHide),
@@ -77,7 +76,6 @@ N(OP_CashReward),
N(OP_CastSpell),
N(OP_ChangeSize),
N(OP_ChannelMessage),
N(OP_ChangePetName),
N(OP_CharacterCreate),
N(OP_CharacterCreateRequest),
N(OP_CharInventory),
@@ -163,7 +161,6 @@ N(OP_EnduranceUpdate),
N(OP_EnterChat),
N(OP_EnterWorld),
N(OP_EnvDamage),
N(OP_EvolveItem),
N(OP_ExpansionInfo),
N(OP_ExpUpdate),
N(OP_FaceChange),
@@ -285,17 +282,12 @@ N(OP_InspectMessageUpdate),
N(OP_InspectRequest),
N(OP_InstillDoubt),
N(OP_InterruptCast),
N(OP_InvokeChangePetName),
N(OP_InvokeChangePetNameImmediate),
N(OP_InvokeNameChangeImmediate),
N(OP_InvokeNameChangeLazy),
N(OP_ItemLinkClick),
N(OP_ItemLinkResponse),
N(OP_ItemLinkText),
N(OP_ItemName),
N(OP_ItemPacket),
N(OP_ItemPreview),
N(OP_ItemPreviewRequest),
N(OP_ItemRecastDelay),
N(OP_ItemVerifyReply),
N(OP_ItemVerifyRequest),
@@ -407,8 +399,6 @@ N(OP_PetitionSearchText),
N(OP_PetitionUnCheckout),
N(OP_PetitionUpdate),
N(OP_PickPocket),
N(OP_PickZone),
N(OP_PickZoneWindow),
N(OP_PlayerProfile),
N(OP_PlayerStateAdd),
N(OP_PlayerStateRemove),
@@ -520,11 +510,6 @@ N(OP_ShopEndConfirm),
N(OP_ShopItem),
N(OP_ShopPlayerBuy),
N(OP_ShopPlayerSell),
N(OP_ShopSendParcel),
N(OP_ShopDeleteParcel),
N(OP_ShopRespondParcel),
N(OP_ShopRetrieveParcel),
N(OP_ShopParcelIcon),
N(OP_ShopRequest),
N(OP_SimpleMessage),
N(OP_SkillUpdate),
@@ -543,7 +528,6 @@ N(OP_Stamina),
N(OP_Stun),
N(OP_Surname),
N(OP_SwapSpell),
N(OP_SystemFingerprint),
N(OP_TargetBuffs),
N(OP_TargetCommand),
N(OP_TargetHoTT),
@@ -568,7 +552,6 @@ N(OP_TradeBusy),
N(OP_TradeCoins),
N(OP_TradeMoneyUpdate),
N(OP_Trader),
N(OP_TraderBulkSend),
N(OP_TraderBuy),
N(OP_TraderDelItem),
N(OP_TradeRequest),
@@ -576,7 +559,6 @@ N(OP_TradeRequestAck),
N(OP_TraderItemUpdate),
N(OP_TraderShop),
N(OP_TradeSkillCombine),
N(OP_TradeSkillRecipeInspect),
N(OP_Translocate),
N(OP_TributeInfo),
N(OP_TributeItem),
+102 -71
View File
@@ -758,10 +758,10 @@ typedef enum {
FilterFocusEffects = 22, //0=show, 1=hide
FilterPetSpells = 23, //0=show, 1=hide
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide
FilterItemSpeech = 25, //0=show, 1=hide // RoF2 Confirmed
FilterStrikethrough = 26, //0=show, 1=hide // RoF2 Confirmed
FilterStuns = 27, //0=show, 1=hide // RoF2 Confirmed
FilterBardSongsOnPets = 28, //0=show, 1=hide // RoF2 Confirmed
FilterUnknown25 = 25,
FilterUnknown26 = 26,
FilterUnknown27 = 27,
FilterUnknown28 = 28,
_FilterCount
} eqFilterType;
@@ -772,47 +772,67 @@ typedef enum {
FilterShowSelfOnly
} eqFilterMode;
#define STAT_STR 0
#define STAT_STA 1
#define STAT_AGI 2
#define STAT_DEX 3
#define STAT_INT 4
#define STAT_WIS 5
#define STAT_CHA 6
#define STAT_MAGIC 7
#define STAT_COLD 8
#define STAT_FIRE 9
#define STAT_POISON 10
#define STAT_DISEASE 11
#define STAT_MANA 12
#define STAT_HP 13
#define STAT_AC 14
#define STAT_ENDURANCE 15
#define STAT_ATTACK 16
#define STAT_HP_REGEN 17
#define STAT_MANA_REGEN 18
#define STAT_HASTE 19
#define STAT_DAMAGE_SHIELD 20
#define STAT_DS_MITIGATION 22
#define STAT_HEAL_AMOUNT 23
#define STAT_SPELL_DAMAGE 24
#define STAT_CLAIRVOYANCE 25
#define STAT_HEROIC_AGILITY 26
#define STAT_HEROIC_CHARISMA 27
#define STAT_HEROIC_DEXTERITY 28
#define STAT_HEROIC_INTELLIGENCE 29
#define STAT_HEROIC_STAMINA 30
#define STAT_HEROIC_STRENGTH 31
#define STAT_HEROIC_WISDOM 32
#define STAT_BASH 33
#define STAT_BACKSTAB 34
#define STAT_DRAGON_PUNCH 35
#define STAT_EAGLE_STRIKE 36
#define STAT_FLYING_KICK 37
#define STAT_KICK 38
#define STAT_ROUND_KICK 39
#define STAT_TIGER_CLAW 40
#define STAT_FRENZY 41
#define STAT_STR 0
#define STAT_STA 1
#define STAT_AGI 2
#define STAT_DEX 3
#define STAT_INT 4
#define STAT_WIS 5
#define STAT_CHA 6
#define STAT_MAGIC 7
#define STAT_COLD 8
#define STAT_FIRE 9
#define STAT_POISON 10
#define STAT_DISEASE 11
#define STAT_MANA 12
#define STAT_HP 13
#define STAT_AC 14
#define STAT_ENDURANCE 15
#define STAT_ATTACK 16
#define STAT_HP_REGEN 17
#define STAT_MANA_REGEN 18
#define STAT_HASTE 19
#define STAT_DAMAGE_SHIELD 20
/*
** Recast timer types. Used as an off set to charProfileStruct timers.
**
** (Another orphaned enumeration...)
*/
enum RecastTimerTypes
{
RecTimer_0 = 0,
RecTimer_1,
RecTimer_WeaponHealClick, // 2
RecTimer_MuramiteBaneNukeClick, // 3
RecTimer_4,
RecTimer_DispellClick, // 5 (also click heal orbs?)
RecTimer_Epic, // 6
RecTimer_OoWBPClick, // 7
RecTimer_VishQuestClassItem, // 8
RecTimer_HealPotion, // 9
RecTimer_10,
RecTimer_11,
RecTimer_12,
RecTimer_13,
RecTimer_14,
RecTimer_15,
RecTimer_16,
RecTimer_17,
RecTimer_18,
RecTimer_ModRod, // 19
_RecTimerCount
};
enum GroupUpdateAction
{
GUA_Joined = 0,
GUA_Left = 1,
GUA_LastLeft = 6,
GUA_FullGroupInfo = 7,
GUA_MakeLeader = 8,
GUA_Started = 9
};
static const uint8 DamageTypeSomething = 0x1C; //0x1c is something...
static const uint8 DamageTypeFalling = 0xFC;
@@ -974,6 +994,43 @@ namespace ZoneBlockedSpellTypes {
const uint8 Region = 2;
};
enum class DynamicZoneType
{
None = 0,
Expedition,
Tutorial,
Task,
Mission, // Shared Task
Quest
};
enum class DynamicZoneMemberStatus : uint8_t
{
Unknown = 0,
Online,
Offline,
InDynamicZone,
LinkDead
};
enum LDoNThemes {
Unused = 0,
GUK,
MIR,
MMC,
RUJ,
TAK
};
enum LDoNThemeBits {
UnusedBit = 0,
GUKBit = 1,
MIRBit = 2,
MMCBit = 4,
RUJBit = 8,
TAKBit = 16
};
enum StartZoneIndex {
Odus = 0,
Qeynos,
@@ -1070,30 +1127,4 @@ namespace RaidLootType {
constexpr uint32 EntireRaid = 4;
}
namespace LeadershipAbilitySlot {
constexpr uint16 HealthOfTargetsTarget = 14;
}
enum ExpSource
{
Quest,
GM,
Kill,
Death,
Resurrection,
LDoNChest,
Task,
Sacrifice
};
#define PARCEL_SEND_ITEMS 0
#define PARCEL_SEND_MONEY 1
#define PARCEL_MONEY_ITEM_ID 99990 // item id of money
#define PARCEL_LIMIT 5
#define PARCEL_BEGIN_SLOT 1
namespace DoorType {
constexpr uint32 BuyerStall = 155;
}
#endif /*COMMON_EQ_CONSTANTS_H*/
+28 -36
View File
@@ -47,7 +47,6 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
ClientUnknown::constants::EXPANSION_BIT,
ClientUnknown::constants::EXPANSIONS_MASK,
ClientUnknown::INULL,
ClientUnknown::INULL,
ClientUnknown::INULL
),
/*[ClientVersion::Client62] =*/
@@ -56,7 +55,6 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
Client62::constants::EXPANSION_BIT,
Client62::constants::EXPANSIONS_MASK,
Client62::INULL,
Client62::INULL,
Client62::INULL
),
/*[ClientVersion::Titanium] =*/
@@ -65,8 +63,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
Titanium::constants::EXPANSION_BIT,
Titanium::constants::EXPANSIONS_MASK,
Titanium::constants::CHARACTER_CREATION_LIMIT,
Titanium::constants::SAY_LINK_BODY_SIZE,
Titanium::INULL
Titanium::constants::SAY_LINK_BODY_SIZE
),
/*[ClientVersion::SoF] =*/
EQ::constants::LookupEntry(
@@ -74,8 +71,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
SoF::constants::EXPANSION_BIT,
SoF::constants::EXPANSIONS_MASK,
SoF::constants::CHARACTER_CREATION_LIMIT,
SoF::constants::SAY_LINK_BODY_SIZE,
SoF::INULL
SoF::constants::SAY_LINK_BODY_SIZE
),
/*[ClientVersion::SoD] =*/
EQ::constants::LookupEntry(
@@ -83,8 +79,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
SoD::constants::EXPANSION_BIT,
SoD::constants::EXPANSIONS_MASK,
SoD::constants::CHARACTER_CREATION_LIMIT,
SoD::constants::SAY_LINK_BODY_SIZE,
SoD::INULL
SoD::constants::SAY_LINK_BODY_SIZE
),
/*[ClientVersion::UF] =*/
EQ::constants::LookupEntry(
@@ -92,8 +87,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
UF::constants::EXPANSION_BIT,
UF::constants::EXPANSIONS_MASK,
UF::constants::CHARACTER_CREATION_LIMIT,
UF::constants::SAY_LINK_BODY_SIZE,
UF::INULL
UF::constants::SAY_LINK_BODY_SIZE
),
/*[ClientVersion::RoF] =*/
EQ::constants::LookupEntry(
@@ -101,8 +95,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
RoF::constants::EXPANSION_BIT,
RoF::constants::EXPANSIONS_MASK,
RoF::constants::CHARACTER_CREATION_LIMIT,
RoF::constants::SAY_LINK_BODY_SIZE,
RoF::INULL
RoF::constants::SAY_LINK_BODY_SIZE
),
/*[ClientVersion::RoF2] =*/
EQ::constants::LookupEntry(
@@ -110,8 +103,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
RoF2::constants::EXPANSION_BIT,
RoF2::constants::EXPANSIONS_MASK,
RoF2::constants::CHARACTER_CREATION_LIMIT,
RoF2::constants::SAY_LINK_BODY_SIZE,
RoF2::constants::MAX_BAZAAR_TRADERS
RoF2::constants::SAY_LINK_BODY_SIZE
)
};
@@ -173,7 +165,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL
ClientUnknown::INULL
),
ClientUnknown::INULL,
@@ -200,7 +192,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Client62::INULL, Client62::INULL, Client62::INULL,
Client62::INULL, Client62::INULL, Client62::INULL,
Client62::INULL, Client62::INULL, Client62::INULL,
Client62::INULL, Client62::INULL, Client62::INULL
Client62::INULL
),
Client62::INULL,
@@ -227,7 +219,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Titanium::invtype::VIEW_MOD_PC_SIZE, Titanium::invtype::VIEW_MOD_BANK_SIZE, Titanium::invtype::VIEW_MOD_SHARED_BANK_SIZE,
Titanium::invtype::VIEW_MOD_LIMBO_SIZE, Titanium::invtype::ALT_STORAGE_SIZE, Titanium::invtype::ARCHIVED_SIZE,
Titanium::INULL, Titanium::INULL, Titanium::INULL,
Titanium::INULL, Titanium::INULL, Titanium::invtype::OTHER_SIZE
Titanium::invtype::OTHER_SIZE
),
Titanium::invslot::EQUIPMENT_BITMASK,
@@ -254,7 +246,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoF::invtype::VIEW_MOD_PC_SIZE, SoF::invtype::VIEW_MOD_BANK_SIZE, SoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
SoF::invtype::VIEW_MOD_LIMBO_SIZE, SoF::invtype::ALT_STORAGE_SIZE, SoF::invtype::ARCHIVED_SIZE,
SoF::INULL, SoF::INULL, SoF::INULL,
SoF::INULL, SoF::INULL, SoF::invtype::OTHER_SIZE
SoF::invtype::OTHER_SIZE
),
SoF::invslot::EQUIPMENT_BITMASK,
@@ -281,7 +273,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoD::invtype::VIEW_MOD_PC_SIZE, SoD::invtype::VIEW_MOD_BANK_SIZE, SoD::invtype::VIEW_MOD_SHARED_BANK_SIZE,
SoD::invtype::VIEW_MOD_LIMBO_SIZE, SoD::invtype::ALT_STORAGE_SIZE, SoD::invtype::ARCHIVED_SIZE,
SoD::INULL, SoD::INULL, SoD::INULL,
SoD::INULL, SoD::INULL, SoD::invtype::OTHER_SIZE
SoD::invtype::OTHER_SIZE
),
SoD::invslot::EQUIPMENT_BITMASK,
@@ -308,7 +300,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
UF::invtype::VIEW_MOD_PC_SIZE, UF::invtype::VIEW_MOD_BANK_SIZE, UF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
UF::invtype::VIEW_MOD_LIMBO_SIZE, UF::invtype::ALT_STORAGE_SIZE, UF::invtype::ARCHIVED_SIZE,
UF::INULL, UF::INULL, UF::INULL,
UF::INULL, UF::INULL, UF::invtype::OTHER_SIZE
UF::invtype::OTHER_SIZE
),
UF::invslot::EQUIPMENT_BITMASK,
@@ -335,7 +327,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
RoF::invtype::VIEW_MOD_PC_SIZE, RoF::invtype::VIEW_MOD_BANK_SIZE, RoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
RoF::invtype::VIEW_MOD_LIMBO_SIZE, RoF::invtype::ALT_STORAGE_SIZE, RoF::invtype::ARCHIVED_SIZE,
RoF::invtype::MAIL_SIZE, RoF::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF::INULL,
RoF::INULL,RoF::INULL,RoF::invtype::OTHER_SIZE
RoF::invtype::OTHER_SIZE
),
RoF::invslot::EQUIPMENT_BITMASK,
@@ -362,7 +354,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::invtype::ALT_STORAGE_SIZE, RoF2::invtype::ARCHIVED_SIZE,
RoF2::invtype::MAIL_SIZE, RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF2::invtype::KRONO_SIZE,
RoF2::invtype::GUILD_BANK_MAIN_SIZE,RoF2::invtype::GUILD_BANK_DEPOSIT_SIZE, RoF2::invtype::OTHER_SIZE
RoF2::invtype::OTHER_SIZE
),
RoF2::invslot::EQUIPMENT_BITMASK,
@@ -389,7 +381,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,
EntityLimits::NPC::INULL, EntityLimits::NPC::INULL,EntityLimits::NPC::INULL
EntityLimits::NPC::INULL
),
EntityLimits::NPC::INULL,
@@ -416,7 +408,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL,
EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL
EntityLimits::NPCMerchant::INULL
),
EntityLimits::NPCMerchant::INULL,
@@ -443,7 +435,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL,
EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL
EntityLimits::Merc::INULL
),
EntityLimits::Merc::INULL,
@@ -470,7 +462,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL,
EntityLimits::Bot::INULL, EntityLimits::Bot::INULL, EntityLimits::Bot::INULL
EntityLimits::Bot::INULL
),
EntityLimits::Bot::invslot::EQUIPMENT_BITMASK,
@@ -497,7 +489,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL,
EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL
EntityLimits::ClientPet::INULL
),
EntityLimits::ClientPet::INULL,
@@ -524,7 +516,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL,
EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL
EntityLimits::NPCPet::INULL
),
EntityLimits::NPCPet::INULL,
@@ -551,7 +543,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL,
EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL
EntityLimits::MercPet::INULL
),
EntityLimits::MercPet::INULL,
@@ -578,7 +570,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL,
EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL
EntityLimits::BotPet::INULL
),
EntityLimits::BotPet::INULL,
@@ -605,7 +597,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
Titanium::invtype::VIEW_MOD_PC_SIZE, Titanium::invtype::VIEW_MOD_BANK_SIZE, Titanium::invtype::VIEW_MOD_SHARED_BANK_SIZE,
Titanium::invtype::VIEW_MOD_LIMBO_SIZE, Titanium::INULL, Titanium::INULL,
Titanium::INULL, Titanium::INULL, Titanium::INULL,
Titanium::INULL, Titanium::INULL, Titanium::INULL
Titanium::INULL
),
Titanium::INULL,
@@ -632,7 +624,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoF::invtype::VIEW_MOD_PC_SIZE, SoF::invtype::VIEW_MOD_BANK_SIZE, SoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
SoF::invtype::VIEW_MOD_LIMBO_SIZE, SoF::INULL, SoF::INULL,
SoF::INULL, SoF::INULL, SoF::INULL,
SoF::INULL, SoF::INULL, SoF::INULL
SoF::INULL
),
SoF::INULL,
@@ -659,7 +651,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
SoD::invtype::VIEW_MOD_PC_SIZE, SoD::invtype::VIEW_MOD_BANK_SIZE, SoD::invtype::VIEW_MOD_SHARED_BANK_SIZE,
SoD::invtype::VIEW_MOD_LIMBO_SIZE, SoD::INULL, SoD::INULL,
SoD::INULL, SoD::INULL, SoD::INULL,
SoD::INULL, SoD::INULL, SoD::INULL
SoD::INULL
),
SoD::INULL,
@@ -686,7 +678,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
UF::invtype::VIEW_MOD_PC_SIZE, UF::invtype::VIEW_MOD_BANK_SIZE, UF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
UF::invtype::VIEW_MOD_LIMBO_SIZE, UF::INULL, UF::INULL,
UF::INULL, UF::INULL, UF::INULL,
UF::INULL, UF::INULL, UF::INULL
UF::INULL
),
UF::INULL,
@@ -713,7 +705,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
RoF::invtype::VIEW_MOD_PC_SIZE, RoF::invtype::VIEW_MOD_BANK_SIZE, RoF::invtype::VIEW_MOD_SHARED_BANK_SIZE,
RoF::invtype::VIEW_MOD_LIMBO_SIZE, RoF::INULL, RoF::INULL,
RoF::INULL, RoF::INULL, RoF::INULL,
RoF::INULL, RoF::INULL, RoF::INULL
RoF::INULL
),
RoF::INULL,
@@ -740,7 +732,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::INULL, RoF2::INULL,
RoF2::INULL, RoF2::INULL, RoF2::INULL,
RoF2::INULL, RoF2::INULL, RoF2::INULL
RoF2::INULL
),
RoF2::INULL,
+5 -8
View File
@@ -42,7 +42,6 @@ namespace EQ
uint32 ExpansionsMask;
int16 CharacterCreationLimit;
size_t SayLinkBodySize;
uint32 BazaarTraderLimit;
LookupEntry(const LookupEntry *lookup_entry) { }
LookupEntry(
@@ -50,15 +49,13 @@ namespace EQ
uint32 ExpansionBit,
uint32 ExpansionsMask,
int16 CharacterCreationLimit,
size_t SayLinkBodySize,
uint32 BazaarTraderLimit
size_t SayLinkBodySize
) :
Expansion(Expansion),
ExpansionBit(ExpansionBit),
ExpansionsMask(ExpansionsMask),
CharacterCreationLimit(CharacterCreationLimit),
SayLinkBodySize(SayLinkBodySize),
BazaarTraderLimit(BazaarTraderLimit)
SayLinkBodySize(SayLinkBodySize)
{ }
};
@@ -87,7 +84,7 @@ namespace EQ
int16 ViewMODPC, ViewMODBank, ViewMODSharedBank;
int16 ViewMODLimbo, AltStorage, Archived;
int16 Mail, GuildTrophyTribute, Krono;
int16 GuildBankMain,GuildBankDeposit, Other;
int16 Other;
InventoryTypeSize_Struct(
int16 Possessions, int16 Bank, int16 SharedBank,
@@ -98,7 +95,7 @@ namespace EQ
int16 ViewMODPC, int16 ViewMODBank, int16 ViewMODSharedBank,
int16 ViewMODLimbo, int16 AltStorage, int16 Archived,
int16 Mail, int16 GuildTrophyTribute, int16 Krono,
int16 GuildBankMain,int16 GuildBankDeposit, int16 Other
int16 Other
) :
Possessions(Possessions), Bank(Bank), SharedBank(SharedBank),
Trade(Trade), World(World), Limbo(Limbo),
@@ -108,7 +105,7 @@ namespace EQ
ViewMODPC(ViewMODPC), ViewMODBank(ViewMODBank), ViewMODSharedBank(ViewMODSharedBank),
ViewMODLimbo(ViewMODLimbo), AltStorage(AltStorage), Archived(Archived),
Mail(Mail), GuildTrophyTribute(GuildTrophyTribute), Krono(Krono),
GuildBankMain(GuildBankMain), GuildBankDeposit(GuildBankDeposit), Other(Other)
Other(Other)
{ }
};
+198 -881
View File
File diff suppressed because it is too large Load Diff
+1 -4
View File
@@ -94,7 +94,7 @@ void EQEmuConfig::parse_config()
auto_database_updates = true;
}
WorldIP = _root["server"]["world"]["tcp"].get("ip", "127.0.0.1").asString();
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
WorldTCPPort = Strings::ToUnsignedInt(_root["server"]["world"]["tcp"].get("port", "9000").asString());
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
@@ -147,8 +147,6 @@ void EQEmuConfig::parse_config()
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
QSHost = _root["server"]["queryserver"].get("host", "localhost").asString();
QSPort = Strings::ToUnsignedInt(_root["server"]["queryserver"].get("port", "9500").asString());
/**
* Zones
@@ -173,7 +171,6 @@ void EQEmuConfig::parse_config()
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
LuaModuleDir = _root["server"]["directories"].get("lua_modules", "lua_modules/").asString();
PatchDir = _root["server"]["directories"].get("patches", "./").asString();
OpcodeDir = _root["server"]["directories"].get("opcodes", "./").asString();
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
+2 -5
View File
@@ -81,9 +81,7 @@ class EQEmuConfig
std::string QSDatabaseUsername;
std::string QSDatabasePassword;
std::string QSDatabaseDB;
uint16 QSDatabasePort;
std::string QSHost;
int QSPort;
uint16 QSDatabasePort;
// From <files/>
std::string SpellsFile;
@@ -97,7 +95,6 @@ class EQEmuConfig
std::string PluginDir;
std::string LuaModuleDir;
std::string PatchDir;
std::string OpcodeDir;
std::string SharedMemDir;
std::string LogDir;
@@ -139,9 +136,9 @@ class EQEmuConfig
{
}
virtual ~EQEmuConfig() {}
public:
virtual ~EQEmuConfig() {}
// Produce a const singleton
static const EQEmuConfig *get()
+1 -21
View File
@@ -25,8 +25,6 @@
#include "repositories/discord_webhooks_repository.h"
#include "repositories/logsys_categories_repository.h"
#include "termcolor/rang.hpp"
#include "path_manager.h"
#include "file.h"
#include <iostream>
#include <string>
@@ -87,7 +85,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
* Set Defaults
*/
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_file = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
@@ -105,8 +102,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::NpcHandin].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NpcHandin].log_to_gmsay = static_cast<uint8>(Logs::General);
/**
* RFC 5424
@@ -537,11 +532,6 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
{
EQEmuLogSys::CloseFileLogs();
if (!File::Exists(path.GetLogPath())) {
LogInfo("Logs directory not found, creating [{}]", path.GetLogPath());
File::Makedir(path.GetLogPath());
}
/**
* 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...
*/
@@ -601,8 +591,6 @@ void EQEmuLogSys::SilenceConsoleLogging()
log_settings[log_index].is_category_enabled = 0;
}
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::MySQLError);
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::Error);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
}
@@ -614,7 +602,7 @@ void EQEmuLogSys::EnableConsoleLogging()
std::copy(std::begin(pre_silence_settings), std::end(pre_silence_settings), std::begin(log_settings));
}
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
{
InjectTablesIfNotExist();
@@ -699,10 +687,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
return this;
}
if (silent_load) {
SilenceConsoleLogging();
}
LogInfo("Loaded [{}] log categories", categories.size());
auto webhooks = DiscordWebhooksRepository::GetWhere(*m_database, fmt::format("id < {}", MAX_DISCORD_WEBHOOK_ID));
@@ -720,10 +704,6 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings(bool silent_load)
log_settings[Logs::Info].log_to_file = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
if (silent_load) {
SilenceConsoleLogging();
}
return this;
}
+1 -19
View File
@@ -141,15 +141,6 @@ namespace Logs {
Zoning,
EqTime,
Corpses,
XTargets,
EvolveItem,
PositionUpdate,
KSM,
BotSettings,
BotSpellChecks,
BotSpellTypeChecks,
NpcHandin,
ZoneState,
MaxCategoryID /* Don't Remove this */
};
@@ -250,15 +241,6 @@ namespace Logs {
"Zoning",
"EqTime",
"Corpses",
"XTargets",
"EvolveItem",
"PositionUpdate",
"KSM", // Kernel Samepage Merging
"Bot Settings",
"Bot Spell Checks",
"Bot Spell Type Checks",
"NpcHandin",
"ZoneState"
};
}
@@ -279,7 +261,7 @@ public:
*/
void CloseFileLogs();
EQEmuLogSys *LoadLogSettingsDefaults();
EQEmuLogSys *LoadLogDatabaseSettings(bool silent_load = false);
EQEmuLogSys *LoadLogDatabaseSettings();
/**
* @param directory_name
-90
View File
@@ -131,16 +131,6 @@
OutF(LogSys, Logs::Detail, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogEvolveItem(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::EvolveItem))\
OutF(LogSys, Logs::General, Logs::EvolveItem, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogEvolveItemDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::EvolveItem))\
OutF(LogSys, Logs::Detail, Logs::EvolveItem, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogGuilds(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::Guilds))\
OutF(LogSys, Logs::General, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
@@ -844,86 +834,6 @@
OutF(LogSys, Logs::Detail, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogXTargets(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::XTargets))\
OutF(LogSys, Logs::General, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogXTargetsDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::XTargets))\
OutF(LogSys, Logs::Detail, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogPositionUpdate(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::PositionUpdate))\
OutF(LogSys, Logs::General, Logs::PositionUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogPositionUpdateDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::PositionUpdate))\
OutF(LogSys, Logs::Detail, Logs::PositionUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__); \
} while (0)
#define LogKSM(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::KSM))\
OutF(LogSys, Logs::General, Logs::KSM, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogKSMDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::KSM))\
OutF(LogSys, Logs::Detail, Logs::KSM, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogBotSettings(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::BotSettings))\
OutF(LogSys, Logs::General, Logs::BotSettings, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogBotSettingsDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotSettings))\
OutF(LogSys, Logs::Detail, Logs::BotSettings, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogBotSpellChecks(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::BotSpellChecks))\
OutF(LogSys, Logs::General, Logs::BotSpellChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogBotSpellChecksDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotSpellChecks))\
OutF(LogSys, Logs::Detail, Logs::BotSpellChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogBotSpellTypeChecks(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::BotSpellTypeChecks))\
OutF(LogSys, Logs::General, Logs::BotSpellTypeChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogBotSpellTypeChecksDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotSpellTypeChecks))\
OutF(LogSys, Logs::Detail, Logs::BotSpellTypeChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNpcHandin(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::NpcHandin))\
OutF(LogSys, Logs::General, Logs::NpcHandin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNpcHandinDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::NpcHandin))\
OutF(LogSys, Logs::Detail, Logs::NpcHandin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogZoneState(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::ZoneState))\
OutF(LogSys, Logs::General, Logs::ZoneState, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogZoneStateDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::ZoneState))\
OutF(LogSys, Logs::Detail, Logs::ZoneState, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.IsLogEnabled(debug_level, log_category))\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
@@ -714,18 +714,6 @@ std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent(
h.charges > 1 ? fmt::format(" Charges: {}", h.charges) : "",
h.attuned ? " (Attuned)" : ""
);
for (int i = 0; i < h.augment_ids.size(); i++) {
if (!Strings::EqualFold(h.augment_names[i], "None")) {
const uint8 slot_id = (i + 1);
handin_items_info += fmt::format(
"Augment {}: {} ({})\n",
slot_id,
h.augment_names[i],
h.augment_ids[i]
);
}
}
}
}
@@ -739,18 +727,6 @@ std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent(
r.charges > 1 ? fmt::format(" Charges: {}", r.charges) : "",
r.attuned ? " (Attuned)" : ""
);
for (int i = 0; i < r.augment_ids.size(); i++) {
if (!Strings::EqualFold(r.augment_names[i], "None")) {
const uint8 slot_id = (i + 1);
return_items_info += fmt::format(
"Augment {}: {} ({})\n",
slot_id,
r.augment_names[i],
r.augment_ids[i]
);
}
}
}
}
@@ -813,36 +789,50 @@ std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent(
);
}
std::string npc_info = fmt::format(
"{} ({})\n",
e.npc_name,
e.npc_id
);
npc_info += fmt::format(
"Is Quest Handin: {}",
e.is_quest_handin ? "Yes" : "No"
);
std::vector<DiscordField> f = {};
BuildDiscordField(&f, "NPC", npc_info);
if (!handin_items_info.empty()) {
BuildDiscordField(&f, "Handin Items", handin_items_info);
BuildDiscordField(
&f,
"Handin Items",
fmt::format(
"{}",
handin_items_info
)
);
}
if (!handin_money_info.empty()) {
BuildDiscordField(&f, "Handin Money", handin_money_info);
BuildDiscordField(
&f,
"Handin Money",
fmt::format(
"{}",
handin_money_info
)
);
}
if (!return_items_info.empty()) {
BuildDiscordField(&f, "Return Items", return_items_info);
BuildDiscordField(
&f,
"Return Items",
fmt::format(
"{}",
return_items_info
)
);
}
if (!return_money_info.empty()) {
BuildDiscordField(&f, "Return Money", return_money_info);
BuildDiscordField(
&f,
"Return Money",
fmt::format(
"{}",
return_money_info
)
);
}
std::vector<DiscordEmbed> embeds = {};
@@ -1081,51 +1071,51 @@ std::string PlayerEventDiscordFormatter::FormatTradeEvent(
if (!e.character_1_give_items.empty()) {
for (const auto &i: e.character_1_give_items) {
std::string augment_info;
if (i.augment_1_id > 0) {
if (i.aug_1_item_id > 0) {
augment_info += fmt::format(
"Augment 1: {} ({})",
i.augment_1_name,
i.augment_1_id
i.aug_1_item_name,
i.aug_1_item_id
);
}
if (i.augment_2_id > 0) {
if (i.aug_2_item_id > 0) {
augment_info += fmt::format(
"Augment 2: {} ({})",
i.augment_2_name,
i.augment_2_id
i.aug_2_item_name,
i.aug_2_item_id
);
}
if (i.augment_3_id > 0) {
if (i.aug_3_item_id > 0) {
augment_info += fmt::format(
"Augment 3: {} ({})",
i.augment_3_name,
i.augment_3_id
i.aug_3_item_name,
i.aug_3_item_id
);
}
if (i.augment_4_id > 0) {
if (i.aug_4_item_id > 0) {
augment_info += fmt::format(
"Augment 4: {} ({})\n",
i.augment_4_name,
i.augment_4_id
i.aug_4_item_name,
i.aug_4_item_id
);
}
if (i.augment_5_id > 0) {
if (i.aug_5_item_id > 0) {
augment_info += fmt::format(
"Augment 5: {} ({})\n",
i.augment_5_name,
i.augment_5_id
i.aug_5_item_name,
i.aug_5_item_id
);
}
if (i.augment_6_id > 0) {
if (i.aug_6_item_id > 0) {
augment_info += fmt::format(
"Augment 6: {} ({})",
i.augment_6_name,
i.augment_6_id
i.aug_6_item_name,
i.aug_6_item_id
);
}
@@ -1146,51 +1136,51 @@ std::string PlayerEventDiscordFormatter::FormatTradeEvent(
if (!e.character_2_give_items.empty()) {
for (const auto &i: e.character_2_give_items) {
std::string augment_info;
if (i.augment_1_id > 0) {
if (i.aug_1_item_id > 0) {
augment_info += fmt::format(
"Augment 1: {} ({})",
i.augment_1_name,
i.augment_1_id
i.aug_1_item_name,
i.aug_1_item_id
);
}
if (i.augment_2_id > 0) {
if (i.aug_2_item_id > 0) {
augment_info += fmt::format(
"Augment 2: {} ({})",
i.augment_2_name,
i.augment_2_id
i.aug_2_item_name,
i.aug_2_item_id
);
}
if (i.augment_3_id > 0) {
if (i.aug_3_item_id > 0) {
augment_info += fmt::format(
"Augment 3: {} ({})",
i.augment_3_name,
i.augment_3_id
i.aug_3_item_name,
i.aug_3_item_id
);
}
if (i.augment_4_id > 0) {
if (i.aug_4_item_id > 0) {
augment_info += fmt::format(
"Augment 4: {} ({})\n",
i.augment_4_name,
i.augment_4_id
i.aug_4_item_name,
i.aug_4_item_id
);
}
if (i.augment_5_id > 0) {
if (i.aug_5_item_id > 0) {
augment_info += fmt::format(
"Augment 5: {} ({})\n",
i.augment_5_name,
i.augment_5_id
i.aug_5_item_name,
i.aug_5_item_id
);
}
if (i.augment_6_id > 0) {
if (i.aug_6_item_id > 0) {
augment_info += fmt::format(
"Augment 6: {} ({})",
i.augment_6_name,
i.augment_6_id
i.aug_6_item_name,
i.aug_6_item_id
);
}
+74 -619
View File
@@ -1,21 +1,14 @@
#include "player_event_logs.h"
#include <cereal/archives/json.hpp>
#include "player_event_logs.h"
#include "player_event_discord_formatter.h"
#include "../platform.h"
#include "../rulesys.h"
#include "player_event_discord_formatter.h"
#include "../repositories/player_event_loot_items_repository.h"
#include "../repositories/player_event_merchant_sell_repository.h"
#include "../repositories/player_event_merchant_purchase_repository.h"
#include "../repositories/player_event_npc_handin_repository.h"
#include "../repositories/player_event_npc_handin_entries_repository.h"
const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour
// general initialization routine
void PlayerEventLogs::Init()
{
m_process_batch_events_timer.SetTimer(RuleI(Logging, BatchPlayerEventProcessIntervalSeconds) * 1000);
m_process_retention_truncation_timer.SetTimer(PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL);
@@ -28,7 +21,6 @@ void PlayerEventLogs::Init()
m_settings[i].event_enabled = 1;
m_settings[i].retention_days = 0;
m_settings[i].discord_webhook_id = 0;
m_settings[i].etl_enabled = false;
}
SetSettingsDefaults();
@@ -73,7 +65,6 @@ void PlayerEventLogs::Init()
c.event_name = PlayerEvent::EventName[i];
c.event_enabled = m_settings[i].event_enabled;
c.retention_days = m_settings[i].retention_days;
c.etl_enabled = false;
settings_to_insert.emplace_back(c);
}
}
@@ -87,7 +78,6 @@ void PlayerEventLogs::Init()
// on initial boot process truncation
if (processing_in_world || processing_in_qs) {
LoadEtlIds();
ProcessRetentionTruncation();
}
}
@@ -131,327 +121,23 @@ void PlayerEventLogs::ProcessBatchQueue()
return;
}
static std::map<uint32, uint32> counter{};
counter.clear();
for (auto const &e: m_record_batch_queue) {
counter[e.event_type_id]++;
}
BenchTimer benchmark;
EtlQueues etl_queues{};
for (const auto &[type, count]: counter) {
if (count > 0) {
switch (type) {
case PlayerEvent::TRADE:
etl_queues.trade.reserve(count);
break;
case PlayerEvent::SPEECH:
etl_queues.speech.reserve(count);
break;
case PlayerEvent::LOOT_ITEM:
etl_queues.loot_items.reserve(count);
break;
case PlayerEvent::KILLED_NPC:
etl_queues.killed_npc.reserve(count);
break;
case PlayerEvent::NPC_HANDIN:
etl_queues.npc_handin.reserve(count);
break;
case PlayerEvent::AA_PURCHASE:
etl_queues.aa_purchase.reserve(count);
break;
case PlayerEvent::MERCHANT_SELL:
etl_queues.merchant_sell.reserve(count);
break;
case PlayerEvent::KILLED_RAID_NPC:
etl_queues.killed_raid_npc.reserve(count);
break;
case PlayerEvent::KILLED_NAMED_NPC:
etl_queues.killed_named_npc.reserve(count);
break;
case PlayerEvent::MERCHANT_PURCHASE:
etl_queues.merchant_purchase.reserve(count);
break;
default:
break;
}
}
}
// Helper to deserialize event data
auto Deserialize = [](const std::string &data, auto &out) {
if (!Strings::IsValidJson(data)) {
return;
}
// cpp exceptions are terrible, don't ever use them
try {
std::stringstream ss(data);
cereal::JSONInputArchive ar(ss);
out.serialize(ar);
}
catch (const std::exception &e) {}
};
// Helper to assign ETL table ID
auto AssignEtlId = [&](
PlayerEventLogsRepository::PlayerEventLogs &r,
PlayerEvent::EventType type
) {
if (m_etl_settings.contains(type)) {
r.etl_table_id = m_etl_settings.at(type).next_id++;
}
};
// Define event processors
std::unordered_map<PlayerEvent::EventType, std::function<void(PlayerEventLogsRepository::PlayerEventLogs &)>> event_processors = {
{
PlayerEvent::EventType::LOOT_ITEM, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::LootItemEvent in{};
PlayerEventLootItemsRepository::PlayerEventLootItems out{};
Deserialize(r.event_data, in);
out.charges = in.charges;
out.corpse_name = in.corpse_name;
out.item_id = in.item_id;
out.item_name = in.item_name;
out.augment_1_id = in.augment_1_id;
out.augment_2_id = in.augment_2_id;
out.augment_3_id = in.augment_3_id;
out.augment_4_id = in.augment_4_id;
out.augment_5_id = in.augment_5_id;
out.augment_6_id = in.augment_6_id;
out.npc_id = in.npc_id;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::LOOT_ITEM);
etl_queues.loot_items.push_back(out);
}
},
{
PlayerEvent::EventType::MERCHANT_SELL, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::MerchantSellEvent in{};
PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{};
Deserialize(r.event_data, in);
out.npc_id = in.npc_id;
out.merchant_name = in.merchant_name;
out.merchant_type = in.merchant_type;
out.item_id = in.item_id;
out.item_name = in.item_name;
out.charges = in.charges;
out.cost = in.cost;
out.alternate_currency_id = in.alternate_currency_id;
out.player_money_balance = in.player_money_balance;
out.player_currency_balance = in.player_currency_balance;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::MERCHANT_SELL);
etl_queues.merchant_sell.push_back(out);
}},
{
PlayerEvent::EventType::MERCHANT_PURCHASE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::MerchantPurchaseEvent in{};
PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{};
Deserialize(r.event_data, in);
out.npc_id = in.npc_id;
out.merchant_name = in.merchant_name;
out.merchant_type = in.merchant_type;
out.item_id = in.item_id;
out.item_name = in.item_name;
out.charges = in.charges;
out.cost = in.cost;
out.alternate_currency_id = in.alternate_currency_id;
out.player_money_balance = in.player_money_balance;
out.player_currency_balance = in.player_currency_balance;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::MERCHANT_PURCHASE);
etl_queues.merchant_purchase.push_back(out);
}},
{
PlayerEvent::EventType::NPC_HANDIN, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::HandinEvent in{};
PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{};
Deserialize(r.event_data, in);
out.npc_id = in.npc_id;
out.npc_name = in.npc_name;
out.handin_copper = in.handin_money.copper;
out.handin_silver = in.handin_money.silver;
out.handin_gold = in.handin_money.gold;
out.handin_platinum = in.handin_money.platinum;
out.return_copper = in.return_money.copper;
out.return_silver = in.return_money.silver;
out.return_gold = in.return_money.gold;
out.return_platinum = in.return_money.platinum;
out.is_quest_handin = in.is_quest_handin;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::NPC_HANDIN);
etl_queues.npc_handin.push_back(out);
for (const auto &i: in.handin_items) {
PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries entry{};
entry.player_event_npc_handin_id = r.etl_table_id;
entry.item_id = i.item_id;
entry.charges = i.charges;
entry.type = 1;
etl_queues.npc_handin_entries.push_back(entry);
}
for (const auto &i: in.return_items) {
PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries entry{};
entry.player_event_npc_handin_id = r.etl_table_id;
entry.item_id = i.item_id;
entry.charges = i.charges;
entry.type = 2;
etl_queues.npc_handin_entries.push_back(entry);
}
}},
{
PlayerEvent::EventType::TRADE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::TradeEvent in{};
PlayerEventTradeRepository::PlayerEventTrade out{};
Deserialize(r.event_data, in);
out.char1_id = in.character_1_id;
out.char2_id = in.character_2_id;
out.char1_copper = in.character_1_give_money.copper;
out.char1_silver = in.character_1_give_money.silver;
out.char1_gold = in.character_1_give_money.gold;
out.char1_platinum = in.character_1_give_money.platinum;
out.char2_copper = in.character_2_give_money.copper;
out.char2_silver = in.character_2_give_money.silver;
out.char2_gold = in.character_2_give_money.gold;
out.char2_platinum = in.character_2_give_money.platinum;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::TRADE);
etl_queues.trade.push_back(out);
for (const auto &i: in.character_1_give_items) {
PlayerEventTradeEntriesRepository::PlayerEventTradeEntries entry{};
entry.player_event_trade_id = r.etl_table_id;
entry.char_id = in.character_1_id;
entry.item_id = i.item_id;
entry.charges = i.charges;
entry.slot = i.slot;
etl_queues.trade_entries.push_back(entry);
}
for (const auto &i: in.character_2_give_items) {
PlayerEventTradeEntriesRepository::PlayerEventTradeEntries entry{};
entry.player_event_trade_id = r.etl_table_id;
entry.char_id = in.character_2_id;
entry.item_id = i.item_id;
entry.charges = i.charges;
entry.slot = i.slot;
etl_queues.trade_entries.push_back(entry);
}
}},
{
PlayerEvent::EventType::SPEECH, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::PlayerSpeech in{};
PlayerEventSpeechRepository::PlayerEventSpeech out{};
Deserialize(r.event_data, in);
out.from_char_id = in.from;
out.to_char_id = in.to;
out.type = in.type;
out.min_status = in.min_status;
out.message = in.message;
out.guild_id = in.guild_id;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::SPEECH);
etl_queues.speech.push_back(out);
}},
{
PlayerEvent::EventType::KILLED_NPC, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::KilledNPCEvent in{};
PlayerEventKilledNpcRepository::PlayerEventKilledNpc out{};
Deserialize(r.event_data, in);
out.npc_id = in.npc_id;
out.npc_name = in.npc_name;
out.combat_time_seconds = in.combat_time_seconds;
out.total_damage_per_second_taken = in.total_damage_per_second_taken;
out.total_heal_per_second_taken = in.total_heal_per_second_taken;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::KILLED_NPC);
etl_queues.killed_npc.push_back(out);
}},
{
PlayerEvent::EventType::AA_PURCHASE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) {
PlayerEvent::AAPurchasedEvent in{};
PlayerEventAaPurchaseRepository::PlayerEventAaPurchase out{};
Deserialize(r.event_data, in);
out.aa_ability_id = in.aa_id;
out.cost = in.aa_cost;
out.previous_id = in.aa_previous_id;
out.next_id = in.aa_next_id;
out.created_at = r.created_at;
AssignEtlId(r, PlayerEvent::EventType::AA_PURCHASE);
etl_queues.aa_purchase.push_back(out);
}},
};
// Process the batch queue
for (auto &r: m_record_batch_queue) {
if (m_settings[r.event_type_id].etl_enabled) {
auto it = event_processors.find(static_cast<PlayerEvent::EventType>(r.event_type_id));
if (it != event_processors.end()) {
it->second(r); // Call the appropriate lambda
r.event_data = "{}"; // Clear event data
}
else {
LogPlayerEventsDetail("Non-Implemented ETL routing [{}]", r.event_type_id);
}
}
}
// Helper to flush and clear queues
auto flush_queue = [&](auto insert_many, auto &queue) {
if (!queue.empty()) {
insert_many(*m_database, queue);
queue.clear();
}
};
// flush many
PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue);
// flush etl queues
flush_queue(PlayerEventLootItemsRepository::InsertMany, etl_queues.loot_items);
flush_queue(PlayerEventMerchantSellRepository::InsertMany, etl_queues.merchant_sell);
flush_queue(PlayerEventMerchantPurchaseRepository::InsertMany, etl_queues.merchant_purchase);
flush_queue(PlayerEventNpcHandinRepository::InsertMany, etl_queues.npc_handin);
flush_queue(PlayerEventNpcHandinEntriesRepository::InsertMany, etl_queues.npc_handin_entries);
flush_queue(PlayerEventTradeRepository::InsertMany, etl_queues.trade);
flush_queue(PlayerEventTradeEntriesRepository::InsertMany, etl_queues.trade_entries);
flush_queue(PlayerEventSpeechRepository::InsertMany, etl_queues.speech);
flush_queue(PlayerEventKilledNpcRepository::InsertMany, etl_queues.killed_npc);
flush_queue(PlayerEventKilledNamedNpcRepository::InsertMany, etl_queues.killed_named_npc);
flush_queue(PlayerEventKilledRaidNpcRepository::InsertMany, etl_queues.killed_raid_npc);
flush_queue(PlayerEventAaPurchaseRepository::InsertMany, etl_queues.aa_purchase);
LogPlayerEvents(
LogPlayerEventsDetail(
"Processing batch player event log queue of [{}] took [{}]",
m_record_batch_queue.size(),
benchmark.elapsed()
);
// empty
m_record_batch_queue.clear();
m_record_batch_queue = {};
m_batch_queue_lock.unlock();
}
// adds a player event to the queue
void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log)
void PlayerEventLogs::AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &log)
{
m_batch_queue_lock.lock();
m_record_batch_queue.emplace_back(log);
@@ -902,7 +588,7 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
break;
}
default: {
LogPlayerEventsDetail(
LogInfo(
"Player event [{}] ({}) Discord formatter not implemented",
e.player_event_log.event_type_name,
e.player_event_log.event_type_id
@@ -916,8 +602,7 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
// general process function, used in world or QS depending on rule Logging:PlayerEventsQSProcess
void PlayerEventLogs::Process()
{
if (m_process_batch_events_timer.Check() ||
m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) {
if (m_process_batch_events_timer.Check() || m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) {
ProcessBatchQueue();
}
@@ -928,125 +613,35 @@ void PlayerEventLogs::Process()
void PlayerEventLogs::ProcessRetentionTruncation()
{
LogPlayerEventsDetail("Running truncation");
LogPlayerEvents("Running truncation");
// Map of repository-specific deletion functions
std::unordered_map<PlayerEvent::EventType, std::function<uint32(const std::string &)>> repository_deleters = {
{
PlayerEvent::LOOT_ITEM, [&](const std::string &condition) {
return PlayerEventLootItemsRepository::DeleteWhere(*m_database, condition);
}},
{
PlayerEvent::MERCHANT_SELL, [&](const std::string &condition) {
return PlayerEventMerchantSellRepository::DeleteWhere(*m_database, condition);
}},
{
PlayerEvent::MERCHANT_PURCHASE, [&](const std::string &condition) {
return PlayerEventMerchantPurchaseRepository::DeleteWhere(*m_database, condition);
}},
{
PlayerEvent::NPC_HANDIN, [&](const std::string &condition) {
uint32 deleted_count = PlayerEventNpcHandinRepository::DeleteWhere(*m_database, condition);
deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere(*m_database, condition);
return deleted_count;
}},
{
PlayerEvent::TRADE, [&](const std::string &condition) {
uint32 deleted_count = PlayerEventTradeRepository::DeleteWhere(*m_database, condition);
deleted_count += PlayerEventTradeEntriesRepository::DeleteWhere(*m_database, condition);
return deleted_count;
}},
{
PlayerEvent::SPEECH, [&](const std::string &condition) {
return PlayerEventSpeechRepository::DeleteWhere(*m_database, condition);
}},
{
PlayerEvent::KILLED_NPC, [&](const std::string &condition) {
return PlayerEventKilledNpcRepository::DeleteWhere(*m_database, condition);
}},
{
PlayerEvent::KILLED_NAMED_NPC, [&](const std::string &condition) {
return PlayerEventKilledNamedNpcRepository::DeleteWhere(*m_database, condition);
}},
{
PlayerEvent::KILLED_RAID_NPC, [&](const std::string &condition) {
return PlayerEventKilledRaidNpcRepository::DeleteWhere(*m_database, condition);
}},
{
PlayerEvent::AA_PURCHASE, [&](const std::string &condition) {
return PlayerEventAaPurchaseRepository::DeleteWhere(*m_database, condition);
}}
};
// Group event types by retention interval
std::unordered_map<int, std::vector<int>> retention_groups;
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
if (m_settings[i].retention_days > 0) {
retention_groups[m_settings[i].retention_days].push_back(i);
}
}
int deleted_count = PlayerEventLogsRepository::DeleteWhere(
*m_database,
fmt::format(
"event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)",
i,
m_settings[i].retention_days
)
);
for (const auto &[retention_days, event_types]: retention_groups) {
std::string condition = fmt::format(
"created_at < (NOW() - INTERVAL {} DAY)",
retention_days
);
// Handle ETL deletions for each event type in the group
uint32 total_deleted_count = 0;
for (int event_type_id: event_types) {
if (m_settings[event_type_id].etl_enabled) {
auto it = repository_deleters.find(static_cast<PlayerEvent::EventType>(m_settings[event_type_id].id));
if (it != repository_deleters.end()) {
total_deleted_count += it->second(condition);
}
else {
LogError("Non-Implemented ETL Event Type [{}]", static_cast<uint32>(m_settings[event_type_id].id));
}
if (deleted_count > 0) {
LogInfo(
"Truncated [{}] events of type [{}] ({}) older than [{}] days",
deleted_count,
PlayerEvent::EventName[i],
i,
m_settings[i].retention_days
);
}
}
if (total_deleted_count > 0) {
LogInfo(
"Truncated [{}] ETL events older than [{}] days",
total_deleted_count,
retention_days
);
}
// Batch deletion for player_event_logs
std::string event_type_ids = fmt::format(
"({})",
fmt::join(event_types, ", ")
);
uint32 deleted_count = PlayerEventLogsRepository::DeleteWhere(
*m_database,
fmt::format(
"event_type_id IN {} AND {}",
event_type_ids,
condition
)
);
if (deleted_count > 0) {
LogInfo(
"Truncated [{}] events of types [{}] older than [{}] days",
deleted_count,
event_type_ids,
retention_days
);
}
}
}
void PlayerEventLogs::ReloadSettings()
{
for (auto &e: PlayerEventLogSettingsRepository::All(*m_database)) {
if (e.id >= PlayerEvent::MAX || e.id < 0) {
continue;
}
m_settings[e.id] = e;
}
}
@@ -1055,197 +650,57 @@ const int32_t RETENTION_DAYS_DEFAULT = 7;
void PlayerEventLogs::SetSettingsDefaults()
{
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
m_settings[PlayerEvent::ZONING].event_enabled = 1;
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
m_settings[PlayerEvent::TRADE].event_enabled = 1;
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
m_settings[PlayerEvent::SAY].event_enabled = 0;
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
m_settings[PlayerEvent::DEATH].event_enabled = 1;
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM].event_enabled = 1;
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_PLAT].event_enabled = 1;
m_settings[PlayerEvent::PARCEL_SEND].event_enabled = 1;
m_settings[PlayerEvent::PARCEL_RETRIEVE].event_enabled = 1;
m_settings[PlayerEvent::PARCEL_DELETE].event_enabled = 1;
m_settings[PlayerEvent::BARTER_TRANSACTION].event_enabled = 1;
m_settings[PlayerEvent::EVOLVE_ITEM].event_enabled = 1;
m_settings[PlayerEvent::SPEECH].event_enabled = 0;
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
m_settings[PlayerEvent::ZONING].event_enabled = 1;
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
m_settings[PlayerEvent::TRADE].event_enabled = 1;
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
m_settings[PlayerEvent::SAY].event_enabled = 0;
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
m_settings[PlayerEvent::DEATH].event_enabled = 1;
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM].event_enabled = 1;
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_PLAT].event_enabled = 1;
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
}
}
void PlayerEventLogs::LoadEtlIds()
{
auto e = [&](auto p) -> bool {
for (PlayerEventLogSettingsRepository::PlayerEventLogSettings const &c: m_settings) {
if (c.id == p) {
return c.etl_enabled ? true : false;
}
}
return false;
};
m_etl_settings.clear();
m_etl_settings = {
{
PlayerEvent::LOOT_ITEM,
{
.enabled = e(PlayerEvent::LOOT_ITEM),
.table_name = "player_event_loot_items",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventLootItemsRepository::TableName()))
}
},
{
PlayerEvent::MERCHANT_SELL,
{
.enabled = e(PlayerEvent::MERCHANT_SELL),
.table_name = "player_event_merchant_sell",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventMerchantSellRepository::TableName()))
}
},
{
PlayerEvent::MERCHANT_PURCHASE,
{
.enabled = e(PlayerEvent::MERCHANT_PURCHASE),
.table_name = "player_event_merchant_purchase",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventMerchantPurchaseRepository::TableName()))
}
},
{
PlayerEvent::NPC_HANDIN,
{
.enabled = e(PlayerEvent::NPC_HANDIN),
.table_name = "player_event_npc_handin",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventNpcHandinRepository::TableName()))
}
},
{
PlayerEvent::TRADE,
{
.enabled = e(PlayerEvent::TRADE),
.table_name = "player_event_trade",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventTradeRepository::TableName()))
}
},
{
PlayerEvent::SPEECH,
{
.enabled = e(PlayerEvent::SPEECH),
.table_name = "player_event_speech",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventSpeechRepository::TableName()))
}
},
{
PlayerEvent::KILLED_NPC,
{
.enabled = e(PlayerEvent::KILLED_NPC),
.table_name = "player_event_killed_npc",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventKilledNpcRepository::TableName()))
}
},
{
PlayerEvent::KILLED_NAMED_NPC,
{
.enabled = e(PlayerEvent::KILLED_NAMED_NPC),
.table_name = "player_event_killed_named_npc",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventKilledNamedNpcRepository::TableName()))
}
},
{
PlayerEvent::KILLED_RAID_NPC,
{
.enabled = e(PlayerEvent::KILLED_RAID_NPC),
.table_name = "player_event_killed_raid_npc",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventKilledRaidNpcRepository::TableName()))
}
},
{
PlayerEvent::AA_PURCHASE,
{
.enabled = e(PlayerEvent::AA_PURCHASE),
.table_name = "player_event_aa_purchase",
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventAaPurchaseRepository::TableName()))
}
}
};
for (auto &e: m_etl_settings) {
LogPlayerEventsDetail(
"ETL Settings [{}] Enabled [{}] Table [{}] NextId [{}]",
PlayerEvent::EventName[e.first],
e.second.enabled,
e.second.table_name,
e.second.next_id
);
}
}
bool PlayerEventLogs::LoadDatabaseConnection()
{
const auto c = EQEmuConfig::get();
LogInfo(
"Connecting to MySQL for PlayerEvents [{}]@[{}]:[{}]",
c->DatabaseUsername.c_str(),
c->DatabaseHost.c_str(),
c->DatabasePort
);
if (!player_event_database.Connect(
c->DatabaseHost.c_str(),
c->DatabaseUsername.c_str(),
c->DatabasePassword.c_str(),
c->DatabaseDB.c_str(),
c->DatabasePort
)) {
LogError("Cannot continue without a database connection for player events.");
return false;
}
SetDatabase(&player_event_database);
return true;
}
+7 -53
View File
@@ -1,38 +1,19 @@
#ifndef EQEMU_PLAYER_EVENT_LOGS_H
#define EQEMU_PLAYER_EVENT_LOGS_H
#include "../repositories/player_event_log_settings_repository.h"
#include "player_events.h"
#include "../servertalk.h"
#include "../repositories/player_event_logs_repository.h"
#include "../timer.h"
#include "../json/json_archive_single_line.h"
#include <cereal/archives/json.hpp>
#include <mutex>
#include "../json/json_archive_single_line.h"
#include "../servertalk.h"
#include "../timer.h"
#include "../eqemu_config.h"
#include "../repositories/player_event_log_settings_repository.h"
#include "../repositories/player_event_logs_repository.h"
#include "../repositories/player_event_loot_items_repository.h"
#include "../repositories/player_event_merchant_purchase_repository.h"
#include "../repositories/player_event_merchant_sell_repository.h"
#include "../repositories/player_event_npc_handin_repository.h"
#include "../repositories/player_event_npc_handin_entries_repository.h"
#include "../repositories/player_event_trade_repository.h"
#include "../repositories/player_event_trade_entries_repository.h"
#include "../repositories/player_event_speech_repository.h"
#include "../repositories/player_event_killed_npc_repository.h"
#include "../repositories/player_event_killed_named_npc_repository.h"
#include "../repositories/player_event_killed_raid_npc_repository.h"
#include "../repositories/player_event_aa_purchase_repository.h"
class PlayerEventLogs {
public:
Database player_event_database{};
void Init();
bool LoadDatabaseConnection();
void ReloadSettings();
void LoadEtlIds();
PlayerEventLogs *SetDatabase(Database *db);
bool ValidateDatabaseConnection();
bool IsEventEnabled(PlayerEvent::EventType event);
@@ -40,7 +21,7 @@ public:
void Process();
// batch queue
void AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &logs);
void AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &logs);
// main event record generic function
// can ingest any struct event types
@@ -78,29 +59,7 @@ public:
std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id);
static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e);
struct EtlQueues {
std::vector<PlayerEventLootItemsRepository::PlayerEventLootItems> loot_items;
std::vector<PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase> merchant_purchase;
std::vector<PlayerEventMerchantSellRepository::PlayerEventMerchantSell> merchant_sell;
std::vector<PlayerEventNpcHandinRepository::PlayerEventNpcHandin> npc_handin;
std::vector<PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries> npc_handin_entries;
std::vector<PlayerEventTradeRepository::PlayerEventTrade> trade;
std::vector<PlayerEventTradeEntriesRepository::PlayerEventTradeEntries> trade_entries;
std::vector<PlayerEventSpeechRepository::PlayerEventSpeech> speech;
std::vector<PlayerEventKilledNpcRepository::PlayerEventKilledNpc> killed_npc;
std::vector<PlayerEventKilledNamedNpcRepository::PlayerEventKilledNamedNpc> killed_named_npc;
std::vector<PlayerEventKilledRaidNpcRepository::PlayerEventKilledRaidNpc> killed_raid_npc;
std::vector<PlayerEventAaPurchaseRepository::PlayerEventAaPurchase> aa_purchase;
};
private:
struct EtlSettings {
bool enabled;
std::string table_name;
int64 next_id;
};
Database *m_database; // reference to database
PlayerEventLogSettingsRepository::PlayerEventLogSettings m_settings[PlayerEvent::EventType::MAX]{};
@@ -110,8 +69,6 @@ private:
static std::unique_ptr<ServerPacket>
BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e);
std::map<PlayerEvent::EventType, EtlSettings> m_etl_settings{};
// timers
Timer m_process_batch_events_timer; // events processing timer
Timer m_process_retention_truncation_timer; // timer for truncating events based on retention settings
@@ -121,9 +78,6 @@ private:
void ProcessBatchQueue();
void ProcessRetentionTruncation();
void SetSettingsDefaults();
public:
std::map<PlayerEvent::EventType, EtlSettings> &GetEtlSettings() { return m_etl_settings;}
};
extern PlayerEventLogs player_event_logs;
+79 -443
View File
@@ -4,7 +4,6 @@
#include <string>
#include <cereal/cereal.hpp>
#include "../types.h"
#include "../rulesys.h"
#include "../repositories/player_event_logs_repository.h"
namespace PlayerEvent {
@@ -59,15 +58,6 @@ namespace PlayerEvent {
ITEM_CREATION,
GUILD_TRIBUTE_DONATE_ITEM,
GUILD_TRIBUTE_DONATE_PLAT,
PARCEL_SEND,
PARCEL_RETRIEVE,
PARCEL_DELETE,
BARTER_TRANSACTION,
SPEECH,
EVOLVE_ITEM,
GUILD_BANK_DEPOSIT,
GUILD_BANK_WITHDRAWAL,
GUILD_BANK_MOVE_TO_BANK_AREA,
MAX // dont remove
};
@@ -76,7 +66,7 @@ namespace PlayerEvent {
// If event is unimplemented just tag (Unimplemented) in the name
// Events don't get saved to the database if unimplemented or deprecated
// Events tagged as deprecated will get automatically removed
static const char *EventName[EventType::MAX] = {
static const char *EventName[PlayerEvent::MAX] = {
"None",
"GM Command",
"Zoning",
@@ -126,16 +116,7 @@ namespace PlayerEvent {
"Killed Raid NPC",
"Item Creation",
"Guild Tribute Donate Item",
"Guild Tribute Donate Platinum",
"Parcel Item Sent",
"Parcel Item Retrieved",
"Parcel Prune Routine",
"Barter Transaction",
"Player Speech",
"Evolve Item Update",
"Guild Bank Item Deposit",
"Guild Bank Item Withdrawal",
"Guild Bank Move From Deposit Area to Bank Area"
"Guild Tribute Donate Platinum"
};
// Generic struct used by all events
@@ -215,12 +196,12 @@ namespace PlayerEvent {
std::string item_name;
uint16 to_slot;
int16 charges;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
uint32 aug1;
uint32 aug2;
uint32 aug3;
uint32 aug4;
uint32 aug5;
uint32 aug6;
bool attuned;
// cereal
@@ -232,57 +213,56 @@ namespace PlayerEvent {
CEREAL_NVP(item_name),
CEREAL_NVP(to_slot),
CEREAL_NVP(charges),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(aug1),
CEREAL_NVP(aug2),
CEREAL_NVP(aug3),
CEREAL_NVP(aug4),
CEREAL_NVP(aug5),
CEREAL_NVP(aug6),
CEREAL_NVP(attuned)
);
}
};
// used in Trade event
// struct TradeItem {
// int64 item_id;
// std::string item_name;
// int32 slot;
//
// // cereal
// template<class Archive>
// void serialize(Archive &ar)
// {
// ar(
// CEREAL_NVP(item_id),
// CEREAL_NVP(item_name),
// CEREAL_NVP(slot)
// );
// }
// };
struct TradeItem {
int64 item_id;
std::string item_name;
int32 slot;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(slot)
);
}
};
// used in Trade event
class TradeItemEntry {
public:
uint16 slot;
uint32 item_id;
uint32 augment_1_id;
std::string augment_1_name;
uint32 augment_2_id;
std::string augment_2_name;
uint32 augment_3_id;
std::string augment_3_name;
uint32 augment_4_id;
std::string augment_4_name;
uint32 augment_5_id;
std::string augment_5_name;
uint32 augment_6_id;
std::string augment_6_name;
std::string item_name;
uint16 charges;
uint32 aug_1_item_id;
std::string aug_1_item_name;
uint32 aug_2_item_id;
std::string aug_2_item_name;
uint32 aug_3_item_id;
std::string aug_3_item_name;
uint32 aug_4_item_id;
std::string aug_4_item_name;
uint32 aug_5_item_id;
std::string aug_5_item_name;
uint32 aug_6_item_id;
std::string aug_6_item_name;
bool in_bag;
// cereal
template<class Archive>
void serialize(Archive &ar)
@@ -290,20 +270,12 @@ namespace PlayerEvent {
ar(
CEREAL_NVP(slot),
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_1_name),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_2_name),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_1_name),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_4_name),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_5_name),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(augment_6_name),
CEREAL_NVP(item_name),
CEREAL_NVP(charges),
CEREAL_NVP(aug_1_item_id),
CEREAL_NVP(aug_2_item_id),
CEREAL_NVP(aug_3_item_id),
CEREAL_NVP(aug_4_item_id),
CEREAL_NVP(aug_5_item_id),
CEREAL_NVP(in_bag)
);
}
@@ -417,9 +389,9 @@ namespace PlayerEvent {
struct AAPurchasedEvent {
uint32 aa_id;
int32 aa_cost;
int32 aa_previous_id;
int32 aa_next_id;
int32 aa_cost;
int32 aa_previous_id;
int32 aa_next_id;
// cereal
template<class Archive>
@@ -436,12 +408,6 @@ namespace PlayerEvent {
struct ForageSuccessEvent {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
std::string item_name;
// cereal
@@ -450,12 +416,6 @@ namespace PlayerEvent {
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(item_name)
);
}
@@ -463,12 +423,6 @@ namespace PlayerEvent {
struct FishSuccessEvent {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
std::string item_name;
// cereal
@@ -477,12 +431,6 @@ namespace PlayerEvent {
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(item_name)
);
}
@@ -492,13 +440,6 @@ namespace PlayerEvent {
uint32 item_id;
std::string item_name;
int16 charges;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
bool attuned;
std::string reason;
// cereal
@@ -508,15 +449,8 @@ namespace PlayerEvent {
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(charges),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(attuned),
CEREAL_NVP(reason)
CEREAL_NVP(reason),
CEREAL_NVP(charges)
);
}
};
@@ -559,12 +493,6 @@ namespace PlayerEvent {
uint32 item_id;
std::string item_name;
int16 charges;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
uint32 npc_id;
std::string corpse_name;
@@ -576,12 +504,6 @@ namespace PlayerEvent {
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(charges),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(npc_id),
CEREAL_NVP(corpse_name)
);
@@ -794,12 +716,6 @@ namespace PlayerEvent {
struct DroppedItemEvent {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
std::string item_name;
int16 slot_id;
uint32 charges;
@@ -810,12 +726,6 @@ namespace PlayerEvent {
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(item_name),
CEREAL_NVP(slot_id),
CEREAL_NVP(charges)
@@ -871,19 +781,12 @@ namespace PlayerEvent {
struct TraderPurchaseEvent {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
std::string item_name;
uint32 trader_id;
std::string trader_name;
uint32 price;
uint32 quantity;
int32 charges;
uint64 total_cost;
uint32 charges;
uint32 total_cost;
uint64 player_money_balance;
@@ -893,17 +796,10 @@ namespace PlayerEvent {
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(item_name),
CEREAL_NVP(trader_id),
CEREAL_NVP(trader_name),
CEREAL_NVP(price),
CEREAL_NVP(quantity),
CEREAL_NVP(charges),
CEREAL_NVP(total_cost),
CEREAL_NVP(player_money_balance)
@@ -913,19 +809,12 @@ namespace PlayerEvent {
struct TraderSellEvent {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
std::string item_name;
uint32 buyer_id;
std::string buyer_name;
uint32 price;
uint32 quantity;
int32 charges;
uint64 total_cost;
uint32 charges;
uint32 total_cost;
uint64 player_money_balance;
@@ -935,17 +824,10 @@ namespace PlayerEvent {
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(item_name),
CEREAL_NVP(buyer_id),
CEREAL_NVP(buyer_name),
CEREAL_NVP(price),
CEREAL_NVP(quantity),
CEREAL_NVP(charges),
CEREAL_NVP(total_cost),
CEREAL_NVP(player_money_balance)
@@ -970,12 +852,10 @@ namespace PlayerEvent {
class HandinEntry {
public:
uint32 item_id;
std::string item_name;
std::vector<uint32> augment_ids;
std::vector<std::string> augment_names;
uint16 charges;
bool attuned;
uint32 item_id;
std::string item_name;
uint16 charges;
bool attuned;
// cereal
template<class Archive>
@@ -984,8 +864,6 @@ namespace PlayerEvent {
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(item_name),
CEREAL_NVP(augment_ids),
CEREAL_NVP(augment_names),
CEREAL_NVP(charges),
CEREAL_NVP(attuned)
);
@@ -1019,7 +897,6 @@ namespace PlayerEvent {
HandinMoney handin_money;
std::vector<HandinEntry> return_items;
HandinMoney return_money;
bool is_quest_handin;
// cereal
template<class Archive>
@@ -1031,8 +908,7 @@ namespace PlayerEvent {
CEREAL_NVP(handin_items),
CEREAL_NVP(handin_money),
CEREAL_NVP(return_items),
CEREAL_NVP(return_money),
CEREAL_NVP(is_quest_handin)
CEREAL_NVP(return_money)
);
}
};
@@ -1072,16 +948,8 @@ namespace PlayerEvent {
};
struct GuildTributeDonateItem {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
int16 charges;
bool attuned;
uint32 guild_favor;
uint32 item_id;
uint32 guild_favor;
// cereal
template<class Archive>
@@ -1089,20 +957,14 @@ namespace PlayerEvent {
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(guild_favor)
);
}
};
struct GuildTributeDonatePlat {
uint32 plat;
uint32 guild_favor;
uint32 plat;
uint32 guild_favor;
// cereal
template<class Archive>
@@ -1114,256 +976,30 @@ namespace PlayerEvent {
);
}
};
struct ParcelRetrieve {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
uint32 quantity;
std::string from_player_name;
uint32 sent_date;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(quantity),
CEREAL_NVP(from_player_name),
CEREAL_NVP(sent_date)
);
}
};
struct ParcelSend {
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
uint32 quantity;
int32 charges;
std::string from_player_name;
std::string to_player_name;
uint32 sent_date;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(quantity),
CEREAL_NVP(charges),
CEREAL_NVP(from_player_name),
CEREAL_NVP(to_player_name),
CEREAL_NVP(sent_date)
);
}
};
struct ParcelDelete {
uint32 char_id;
uint32 item_id;
uint32 augment_1_id;
uint32 augment_2_id;
uint32 augment_3_id;
uint32 augment_4_id;
uint32 augment_5_id;
uint32 augment_6_id;
uint32 quantity;
uint32 sent_date;
std::string from_name;
std::string note;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(augment_1_id),
CEREAL_NVP(augment_2_id),
CEREAL_NVP(augment_3_id),
CEREAL_NVP(augment_4_id),
CEREAL_NVP(augment_5_id),
CEREAL_NVP(augment_6_id),
CEREAL_NVP(quantity),
CEREAL_NVP(char_id),
CEREAL_NVP(from_name),
CEREAL_NVP(note),
CEREAL_NVP(sent_date)
);
}
};
struct BarterTransaction {
std::string status;
uint32 item_id;
uint32 item_quantity;
std::string item_name;
std::vector<BuyerLineTradeItems_Struct> trade_items;
std::string buyer_name;
std::string seller_name;
uint64 total_cost;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(status),
CEREAL_NVP(item_id),
CEREAL_NVP(item_quantity),
CEREAL_NVP(item_name),
CEREAL_NVP(trade_items),
CEREAL_NVP(buyer_name),
CEREAL_NVP(seller_name),
CEREAL_NVP(total_cost)
);
}
};
struct EvolveItem {
std::string status;
uint32 item_id;
uint64 unique_id;
std::string item_name;
uint32 level;
double progression;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(status),
CEREAL_NVP(item_id),
CEREAL_NVP(unique_id),
CEREAL_NVP(item_name),
CEREAL_NVP(level),
CEREAL_NVP(progression)
);
}
};
struct PlayerSpeech {
std::string to;
std::string from;
uint32 guild_id;
int16 min_status;
uint32 type;
std::string message;
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(to),
CEREAL_NVP(from),
CEREAL_NVP(guild_id),
CEREAL_NVP(min_status),
CEREAL_NVP(type),
CEREAL_NVP(message)
);
}
};
struct GuildBankTransaction {
uint32 char_id;
uint32 guild_id;
uint32 item_id;
uint32 aug_slot_one;
uint32 aug_slot_two;
uint32 aug_slot_three;
uint32 aug_slot_four;
uint32 aug_slot_five;
uint32 aug_slot_six;
uint32 quantity;
uint32 permission;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(char_id),
CEREAL_NVP(guild_id),
CEREAL_NVP(item_id),
CEREAL_NVP(aug_slot_one),
CEREAL_NVP(aug_slot_two),
CEREAL_NVP(aug_slot_three),
CEREAL_NVP(aug_slot_four),
CEREAL_NVP(aug_slot_five),
CEREAL_NVP(aug_slot_six),
CEREAL_NVP(quantity)
);
}
};
}
#endif //EQEMU_PLAYER_EVENTS_H
#define RecordPlayerEventLog(event_type, event_data) do {\
if (player_event_logs.IsEventEnabled(event_type)) {\
if (RuleB(Logging, PlayerEventsQSProcess)) {\
QServ->SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
GetPlayerEvent(),\
event_data\
).get()\
);\
} \
else { \
worldserver.SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
GetPlayerEvent(),\
event_data\
).get()\
);\
}\
worldserver.SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
GetPlayerEvent(),\
event_data\
).get()\
);\
}\
} while (0)
#define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\
if (player_event_logs.IsEventEnabled(event_type)) {\
if (RuleB(Logging, PlayerEventsQSProcess)) {\
QServ->SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
(c)->GetPlayerEvent(),\
event_data\
).get()\
);\
}\
else {\
worldserver.SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
(c)->GetPlayerEvent(),\
event_data\
).get()\
);\
}\
worldserver.SendPacket(\
player_event_logs.RecordEvent(\
event_type,\
(c)->GetPlayerEvent(),\
event_data\
).get()\
);\
}\
} while (0)
-303
View File
@@ -1,303 +0,0 @@
#include "evolving_items.h"
#include "item_instance.h"
#include "events/player_event_logs.h"
#include "repositories/character_evolving_items_repository.h"
EvolvingItemsManager::EvolvingItemsManager()
{
m_db = nullptr;
m_content_db = nullptr;
}
void EvolvingItemsManager::LoadEvolvingItems() const
{
auto const &results = ItemsEvolvingDetailsRepository::All(*m_content_db);
if (results.empty()) {
return;
}
std::ranges::transform(
results.begin(),
results.end(),
std::inserter(
evolving_items_manager.GetEvolvingItemsCache(),
evolving_items_manager.GetEvolvingItemsCache().end()
),
[](const ItemsEvolvingDetailsRepository::ItemsEvolvingDetails &x) {
return std::make_pair(x.item_id, x);
}
);
}
void EvolvingItemsManager::SetDatabase(Database *db)
{
m_db = db;
}
void EvolvingItemsManager::SetContentDatabase(Database *db)
{
m_content_db = db;
}
double EvolvingItemsManager::CalculateProgression(const uint64 current_amount, const uint32 item_id)
{
if (!evolving_items_manager.GetEvolvingItemsCache().contains(item_id)) {
return 0;
}
return evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount > 0
? static_cast<double>(current_amount)
/ static_cast<double>(evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount) * 100
: 0;
}
void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_id, const EQ::ItemInstance &inst) const
{
inst.SetEvolveEquipped(false);
if (inst.IsEvolving() && slot_id <= EQ::invslot::EQUIPMENT_END && slot_id >= EQ::invslot::EQUIPMENT_BEGIN) {
inst.SetEvolveEquipped(true);
}
if (!inst.IsEvolving()) {
return;
}
if (!inst.GetEvolveUniqueID()) {
auto e = CharacterEvolvingItemsRepository::NewEntity();
e.character_id = char_id;
e.item_id = inst.GetID();
e.equipped = inst.GetEvolveEquipped();
e.final_item_id = evolving_items_manager.GetFinalItemID(inst);
auto r = CharacterEvolvingItemsRepository::InsertOne(*m_db, e);
e.id = r.id;
inst.SetEvolveUniqueID(e.id);
inst.SetEvolveCharID(e.character_id);
inst.SetEvolveItemID(e.item_id);
inst.SetEvolveFinalItemID(e.final_item_id);
return;
}
CharacterEvolvingItemsRepository::SetEquipped(*m_db, inst.GetEvolveUniqueID(), inst.GetEvolveEquipped());
}
uint32 EvolvingItemsManager::GetFinalItemID(const EQ::ItemInstance &inst) const
{
const auto start_iterator = std::ranges::find_if(
evolving_items_manager.GetEvolvingItemsCache().cbegin(),
evolving_items_manager.GetEvolvingItemsCache().cend(),
[&](const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a) {
return a.second.item_evo_id == inst.GetEvolveLoreID();
}
);
if (start_iterator == std::end(evolving_items_manager.GetEvolvingItemsCache())) {
return 0;
}
const auto final_id = std::ranges::max_element(
start_iterator,
evolving_items_manager.GetEvolvingItemsCache().cend(),
[&](
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a,
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &b
) {
return a.second.item_evo_id == b.second.item_evo_id &&
a.second.item_evolve_level < b.second.item_evolve_level;
}
);
return final_id->first;
}
uint32 EvolvingItemsManager::GetNextEvolveItemID(const EQ::ItemInstance &inst) const
{
int8 const current_level = inst.GetEvolveLvl();
const auto iterator = std::ranges::find_if(
evolving_items_manager.GetEvolvingItemsCache().cbegin(),
evolving_items_manager.GetEvolvingItemsCache().cend(),
[&](const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a) {
return a.second.item_evo_id == inst.GetEvolveLoreID() &&
a.second.item_evolve_level == current_level + 1;
}
);
if (iterator == std::end(evolving_items_manager.GetEvolvingItemsCache())) {
return 0;
}
return iterator->first;
}
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails EvolvingItemsManager::GetEvolveItemDetails(const uint64 unique_id)
{
if (GetEvolvingItemsCache().contains(unique_id)) {
return GetEvolvingItemsCache().at(unique_id);
}
return ItemsEvolvingDetailsRepository::NewEntity();
}
std::vector<ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> EvolvingItemsManager::GetEvolveIDItems(
const uint32 evolve_id
)
{
std::vector<ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> e{};
for (auto const &[key, value]: GetEvolvingItemsCache()) {
if (value.item_evo_id == evolve_id) {
e.push_back(value);
}
}
std::ranges::sort(
e.begin(),
e.end(),
[&](
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails const &a,
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails const &b
) {
return a.item_evolve_level < b.item_evolve_level;
}
);
return e;
}
uint64 EvolvingItemsManager::GetTotalEarnedXP(const EQ::ItemInstance &inst)
{
if (!inst) {
return 0;
}
uint64 xp = inst.GetEvolveCurrentAmount();
auto evolve_id_item_cache = GetEvolveIDItems(inst.GetEvolveLoreID());
auto current_level = inst.GetEvolveLvl();
for (auto const &i: evolve_id_item_cache) {
if (i.item_evolve_level < current_level) {
xp += i.required_amount;
}
}
return xp;
}
EvolveGetNextItem EvolvingItemsManager::GetNextItemByXP(const EQ::ItemInstance &inst_in, const int64 in_xp)
{
EvolveGetNextItem ets{};
const auto evolve_items = GetEvolveIDItems(inst_in.GetEvolveLoreID());
uint32 max_transfer_level = 0;
int64 xp = in_xp;
for (auto const &e: evolve_items) {
if (e.item_evolve_level < inst_in.GetEvolveLvl()) {
continue;
}
int64 have = 0;
if (e.item_evolve_level == inst_in.GetEvolveLvl()) {
have = inst_in.GetEvolveCurrentAmount();
}
const auto required = e.required_amount;
const int64 need = required - have;
const int64 balance = xp - need;
if (balance <= 0) {
ets.new_current_amount = have + xp;
ets.new_item_id = e.item_id;
ets.from_current_amount = 0;
ets.max_transfer_level = max_transfer_level;
return ets;
}
xp = balance;
max_transfer_level += 1;
ets.new_current_amount = required;
ets.new_item_id = e.item_id;
ets.from_current_amount = balance - required;
ets.max_transfer_level = max_transfer_level;
}
return ets;
}
EvolveTransfer EvolvingItemsManager::DetermineTransferResults(
const EQ::ItemInstance &inst_from,
const EQ::ItemInstance &inst_to
)
{
EvolveTransfer ets{};
auto evolving_details_inst_from = evolving_items_manager.GetEvolveItemDetails(inst_from.GetID());
auto evolving_details_inst_to = evolving_items_manager.GetEvolveItemDetails(inst_to.GetID());
if (!evolving_details_inst_from.id || !evolving_details_inst_to.id) {
return ets;
}
if (evolving_details_inst_from.type == evolving_details_inst_to.type) {
uint32 compatibility = 0;
uint64 xp = 0;
if (evolving_details_inst_from.sub_type == evolving_details_inst_to.sub_type) {
compatibility = 100;
}
else {
compatibility = 30;
}
xp = evolving_items_manager.GetTotalEarnedXP(inst_from) * compatibility / 100;
auto results = evolving_items_manager.GetNextItemByXP(inst_to, xp);
ets.item_from_id = evolving_items_manager.GetFirstItemInLoreGroup(inst_from.GetEvolveLoreID());
ets.item_from_current_amount = results.from_current_amount;
ets.item_to_id = results.new_item_id;
ets.item_to_current_amount = results.new_current_amount;
ets.compatibility = compatibility;
ets.max_transfer_level = results.max_transfer_level;
}
return ets;
}
uint32 EvolvingItemsManager::GetFirstItemInLoreGroup(const uint32 lore_id)
{
for (auto const &[key, value]: GetEvolvingItemsCache()) {
if (value.item_evo_id == lore_id && value.item_evolve_level == 1) {
return key;
}
}
return 0;
}
uint32 EvolvingItemsManager::GetFirstItemInLoreGroupByItemID(const uint32 item_id)
{
for (auto const &[key, value]: GetEvolvingItemsCache()) {
if (value.item_id == item_id) {
for (auto const &[key2, value2]: GetEvolvingItemsCache()) {
if (value2.item_evo_id == value.item_evo_id && value2.item_evolve_level == 1) {
return key;
}
}
}
}
return 0;
}
void EvolvingItemsManager::LoadPlayerEvent(const EQ::ItemInstance &inst, PlayerEvent::EvolveItem &e)
{
e.item_id = inst.GetID();
e.item_name = inst.GetItem() ? inst.GetItem()->Name : std::string();
e.level = inst.GetEvolveLvl();
e.progression = inst.GetEvolveProgression();
e.unique_id = inst.GetEvolveUniqueID();
}
-67
View File
@@ -1,67 +0,0 @@
#ifndef EVOLVING_H
#define EVOLVING_H
#include "shareddb.h"
#include "events/player_events.h"
#include "repositories/items_evolving_details_repository.h"
namespace EQ {
class ItemInstance;
}
namespace EvolvingItems {
namespace Actions {
constexpr int8 UPDATE_ITEMS = 0;
constexpr int8 TRANSFER_WINDOW_OPEN = 1;
constexpr int8 TRANSFER_WINDOW_DETAILS = 2;
constexpr int8 TRANSFER_XP = 3;
constexpr int8 FINAL_RESULT = 4;
}
namespace Types {
constexpr int8 AMOUNT_OF_EXP = 1;
constexpr int8 NUMBER_OF_KILLS = 2;
constexpr int8 SPECIFIC_MOB_RACE = 3;
constexpr int8 SPECIFIC_ZONE_ID = 4;
}
namespace SubTypes {
constexpr int8 ALL_EXP = 0;
constexpr int8 SOLO_EXP = 1;
constexpr int8 GROUP_EXP = 2;
constexpr int8 RAID_EXP = 3;
}
}
class EvolvingItemsManager
{
public:
EvolvingItemsManager();
void SetDatabase(Database *db);
void SetContentDatabase(Database *db);
void LoadEvolvingItems() const;
void DoLootChecks(uint32 char_id, uint16 slot_id, const EQ::ItemInstance &inst) const;
uint32 GetFinalItemID(const EQ::ItemInstance &inst) const;
uint32 GetNextEvolveItemID(const EQ::ItemInstance &inst) const;
uint32 GetFirstItemInLoreGroup(uint32 lore_id);
uint32 GetFirstItemInLoreGroupByItemID(uint32 item_id);
uint64 GetTotalEarnedXP(const EQ::ItemInstance &inst);
static double CalculateProgression(uint64 current_amount, uint32 item_id);
static void LoadPlayerEvent(const EQ::ItemInstance &inst, PlayerEvent::EvolveItem &e);
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails GetEvolveItemDetails(uint64 id);
EvolveTransfer DetermineTransferResults(const EQ::ItemInstance& inst_from, const EQ::ItemInstance& inst_to);
EvolveGetNextItem GetNextItemByXP(const EQ::ItemInstance &inst_in, int64 in_xp);
std::map<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails>& GetEvolvingItemsCache() { return evolving_items_cache; }
std::vector<ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> GetEvolveIDItems(uint32 evolve_id);
private:
std::map<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> evolving_items_cache;
Database * m_db;
Database * m_content_db;
};
extern EvolvingItemsManager evolving_items_manager;
#endif //EVOLVING_H
+101
View File
@@ -0,0 +1,101 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "expedition_lockout_timer.h"
#include "../common/strings.h"
#include "../common/rulesys.h"
#include "../common/util/uuid.h"
#include <fmt/format.h>
const char* const DZ_REPLAY_TIMER_NAME = "Replay Timer"; // see December 14, 2016 patch notes
ExpeditionLockoutTimer::ExpeditionLockoutTimer(
std::string expedition_uuid, std::string expedition_name,
std::string event_name, uint64_t expire_time, uint32_t duration
) :
m_expedition_uuid{std::move(expedition_uuid)},
m_expedition_name{std::move(expedition_name)},
m_event_name{std::move(event_name)},
m_expire_time(std::chrono::system_clock::from_time_t(expire_time)),
m_duration(duration)
{
if (m_event_name == DZ_REPLAY_TIMER_NAME)
{
m_is_replay_timer = true;
}
}
ExpeditionLockoutTimer ExpeditionLockoutTimer::CreateLockout(
const std::string& expedition_name, const std::string& event_name, uint32_t seconds, std::string uuid)
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
if (uuid.empty())
{
uuid = EQ::Util::UUID::Generate().ToString();
}
ExpeditionLockoutTimer lockout{uuid, expedition_name, event_name, 0, seconds};
lockout.Reset(); // sets expire time
return lockout;
}
uint32_t ExpeditionLockoutTimer::GetSecondsRemaining() const
{
auto now = std::chrono::system_clock::now();
if (m_expire_time > now)
{
auto remaining = m_expire_time - now;
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
}
return 0;
}
ExpeditionLockoutTimer::DaysHoursMinutes ExpeditionLockoutTimer::GetDaysHoursMinutesRemaining() const
{
auto seconds = GetSecondsRemaining();
return ExpeditionLockoutTimer::DaysHoursMinutes{
fmt::format_int(seconds / 86400).str(), // days
fmt::format_int((seconds / 3600) % 24).str(), // hours
fmt::format_int((seconds / 60) % 60).str() // minutes
};
}
bool ExpeditionLockoutTimer::IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const
{
return compare_lockout.IsSameLockout(GetExpeditionName(), GetEventName());
}
bool ExpeditionLockoutTimer::IsSameLockout(
const std::string& expedition_name, const std::string& event_name) const
{
return GetExpeditionName() == expedition_name && GetEventName() == event_name;
}
void ExpeditionLockoutTimer::AddLockoutTime(int seconds)
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
auto start_time = m_expire_time - m_duration;
m_duration = std::chrono::seconds(new_duration);
m_expire_time = start_time + m_duration;
}
+76
View File
@@ -0,0 +1,76 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EXPEDITION_LOCKOUT_TIMER_H
#define EXPEDITION_LOCKOUT_TIMER_H
#include <chrono>
#include <string>
extern const char* const DZ_REPLAY_TIMER_NAME;
class ExpeditionLockoutTimer
{
public:
ExpeditionLockoutTimer() = default;
ExpeditionLockoutTimer(
std::string expedition_uuid, std::string expedition_name,
std::string event_name, uint64_t expire_time, uint32_t duration);
static ExpeditionLockoutTimer CreateLockout(
const std::string& expedition_name, const std::string& event_name,
uint32_t seconds, std::string uuid = {});
struct DaysHoursMinutes
{
std::string days;
std::string hours;
std::string mins;
};
void AddLockoutTime(int seconds);
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
uint32_t GetSecondsRemaining() const;
DaysHoursMinutes GetDaysHoursMinutesRemaining() const;
const std::string& GetExpeditionName() const { return m_expedition_name; }
const std::string& GetExpeditionUUID() const { return m_expedition_uuid; }
const std::string& GetEventName() const { return m_event_name; }
bool IsExpired() const { return GetSecondsRemaining() == 0; }
bool IsFromExpedition(const std::string& uuid) const { return uuid == m_expedition_uuid; }
bool IsReplayTimer() const { return m_is_replay_timer; }
bool IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const;
bool IsSameLockout(const std::string& expedition_name, const std::string& event_name) const;
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
void SetUUID(const std::string& uuid) { m_expedition_uuid = uuid; }
private:
bool m_is_replay_timer = false;
std::string m_expedition_uuid; // expedition received in
std::string m_expedition_name;
std::string m_event_name;
std::chrono::seconds m_duration;
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
};
#endif
+13 -12
View File
@@ -39,7 +39,6 @@
#include <filesystem>
#include <iostream>
#include <sys/stat.h>
#include <vector>
namespace fs = std::filesystem;
@@ -91,21 +90,23 @@ std::string File::GetCwd()
FileContentsResult File::GetContents(const std::string &file_name)
{
std::ifstream f(file_name, std::ios::in | std::ios::binary);
if (!f) {
return { .error = fmt::format("Couldn't open file [{}]", file_name) };
}
constexpr size_t CHUNK_SIZE = 4096; // Read 4KB chunks
std::string error;
std::ifstream f;
f.open(file_name);
std::string line;
std::string lines;
std::vector<char> buffer(CHUNK_SIZE);
while (f.read(buffer.data(), CHUNK_SIZE) || f.gcount() > 0) {
lines.append(buffer.data(), f.gcount());
if (f.is_open()) {
while (f) {
std::getline(f, line);
lines += line + "\n";
}
}
else {
error = fmt::format("Couldn't open file [{}]", file_name);
}
return FileContentsResult{
.contents = lines,
.error = {}
.error = error,
};
}
+92 -73
View File
@@ -92,20 +92,10 @@ BaseGuildManager::~BaseGuildManager()
bool BaseGuildManager::LoadGuilds()
{
ClearGuilds();
auto guilds = GuildsRepository::GetWhere(
*m_db,
fmt::format("`id` < '{}'", RoF2::constants::MAX_GUILD_ID)
);
auto guilds_ranks = GuildRanksRepository::LoadAll(*m_db);
auto guilds_permissions = GuildPermissionsRepository::LoadAll(*m_db);
auto guilds_tributes = GuildTributesRepository::GetWhere(
*m_db,
fmt::format(
"`guild_id` < '{}'",
RoF2::constants::MAX_GUILD_ID
)
);
auto guilds = GuildsRepository::All(*m_db);
auto guilds_ranks = GuildRanksRepository::All(*m_db);
auto guilds_permissions = GuildPermissionsRepository::All(*m_db);
auto guilds_tributes = GuildTributesRepository::All(*m_db);
if (guilds.empty()) {
LogGuilds("No Guilds found in database.");
@@ -118,27 +108,22 @@ bool BaseGuildManager::LoadGuilds()
_CreateGuild(g.id, g.name, g.leader, g.minstatus, g.motd, g.motd_setter, g.channel, g.url, g.favor);
for (int i = 1; i <= GUILD_MAX_RANK; i++) {
auto key = fmt::format("{}-{}", g.id, i);
if (guilds_ranks.contains(key)) {
m_guilds[g.id]->rank_names[i] = guilds_ranks.find(key)->second;
for (auto const &r: guilds_ranks) {
if (r.guild_id == g.id) {
m_guilds[g.id]->rank_names[r.rank_] = r.title;
}
}
auto count = 0;
for (int i = 1; i <= GUILD_MAX_FUNCTIONS; i++) {
auto key = fmt::format("{}-{}", g.id, i);
if (guilds_permissions.contains(key)) {
auto p = guilds_permissions.find(key)->second;
for (auto const &p: guilds_permissions) {
if (p.guild_id == g.id) {
m_guilds[g.id]->functions[p.perm_id].id = p.id;
m_guilds[g.id]->functions[p.perm_id].guild_id = p.guild_id;
m_guilds[g.id]->functions[p.perm_id].perm_id = p.perm_id;
m_guilds[g.id]->functions[p.perm_id].perm_value = p.permission;
count++;
}
count++;
}
if (count < GUILD_MAX_FUNCTIONS) {
@@ -357,14 +342,41 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id)
return true;
}
uint32 BaseGuildManager::_GetFreeGuildID()
{
GuildsRepository::DeleteWhere(*m_db, "`name` = ''");
GuildsRepository::Guilds out;
out.id = 0;
out.leader = 0;
out.minstatus = 0;
out.tribute = 0;
out.name = "";
out.motd = "";
out.motd_setter = "";
out.url = "";
out.channel = "";
auto last_insert_id = GuildsRepository::InsertOne(*m_db, out);
if (last_insert_id.id > 0) {
LogGuilds("Located a free guild ID [{}] in the database", last_insert_id.id);
return last_insert_id.id;
}
LogGuilds("Unable to find a free guild ID in the database");
return GUILD_NONE;
}
uint32 BaseGuildManager::CreateGuild(std::string name, uint32 leader_char_id)
{
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
if (guild_id == GUILD_NONE) {
return (GUILD_NONE);
}
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
if (guild_id == GUILD_NONE) {
return (GUILD_NONE);
}
//RefreshGuild(guild_id);
//SendGuildRefresh(guild_id, true, false, false, false);
//SendCharRefresh(GUILD_NONE, guild_id, leader_char_id);
return guild_id;
return guild_id;
}
bool BaseGuildManager::DeleteGuild(uint32 guild_id)
@@ -527,8 +539,8 @@ bool BaseGuildManager::SetPublicNote(uint32 charid, std::string public_note)
uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
{
auto new_id = GuildsRepository::GetMaxId(*m_db) + 1;
if (!new_id) {
auto new_id = _GetFreeGuildID();
if (new_id == GUILD_NONE) {
return GUILD_NONE;
}
@@ -547,62 +559,60 @@ uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
bool BaseGuildManager::UpdateDbDeleteGuild(uint32 guild_id, bool local_delete, bool db_delete)
{
auto const where_filter = fmt::format("guild_id = {}", guild_id);
auto const bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
if (local_delete) {
auto where_filter = fmt::format("guildid = {}", guild_id);
auto bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
if (!bank_items.empty()) {
LogError(
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
"again.",
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
guild_id,
bank_items.size()
);
LogGuilds(
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
"again.",
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
guild_id,
bank_items.size()
);
return false;
}
auto res = m_guilds.find(guild_id);
if (res != m_guilds.end()) {
safe_delete(res->second);
m_guilds.erase(res);
LogGuilds("Deleted guild [{}] from memory", guild_id);
// Does this need to be sent to world?
else {
std::map<uint32, GuildInfo *>::iterator res;
res = m_guilds.find(guild_id);
if (res != m_guilds.end()) {
delete res->second;
m_guilds.erase(res);
LogGuilds("Deleted guild [{}] from memory", guild_id);
//Does this need to be sent to world?
}
}
}
if (db_delete) {
auto where_filter = fmt::format("guildid = {}", guild_id);
auto bank_items = GuildBankRepository::GetWhere(*m_db, where_filter);
if (!bank_items.empty()) {
LogError(
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
"again.",
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
guild_id,
bank_items.size()
);
LogGuilds(
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try "
"again.",
"Attempt to delete guild id [{}] that still has [{}] items in the bank. Please remove them and try again.",
guild_id,
bank_items.size()
);
return false;
}
GuildTributesRepository::DeleteOne(*m_db, guild_id);
GuildsRepository::DeleteOne(*m_db, guild_id);
GuildRanksRepository::DeleteWhere(*m_db, where_filter);
GuildPermissionsRepository::DeleteWhere(*m_db, where_filter);
GuildMembersRepository::DeleteWhere(*m_db, where_filter);
LogGuilds("Deleted guild [{}] from the database", guild_id);
else {
auto where_filter = fmt::format("guild_id = {}", guild_id);
GuildTributesRepository::DeleteOne(*m_db, guild_id);
GuildsRepository::DeleteOne(*m_db, guild_id);
GuildRanksRepository::DeleteWhere(*m_db, where_filter);
GuildPermissionsRepository::DeleteWhere(*m_db, where_filter);
GuildMembersRepository::DeleteWhere(*m_db, where_filter);
LogGuilds("Deleted guild [{}] from the database", guild_id);
}
}
return true;
}
@@ -946,24 +956,33 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into)
}
GuildsListMessaging_Struct BaseGuildManager::MakeGuildList()
//returns ownership of the buffer.
uint8 *BaseGuildManager::MakeGuildList(const char *head_name, uint32 &length) const
{
GuildsListMessaging_Struct guild_list_messaging{};
uint32 string_length = 0;
//dynamic structs will make this a lot less painful.
for (auto const &g: m_guilds) {
GuildsListMessagingEntry_Struct guild_entry{};
length = sizeof(GuildsList_Struct);
auto buffer = new uint8[length];
guild_entry.guild_id = g.first;
guild_entry.guild_name = g.second->name;
string_length += g.second->name.length() + 1;
guild_list_messaging.guild_detail.push_back(guild_entry);
//a bit little better than memsetting the whole thing...
uint32 r, pos;
for (r = 0, pos = 0; r <= MAX_NUMBER_GUILDS; r++, pos += 64) {
//strcpy((char *) buffer+pos, "BAD GUILD");
// These 'BAD GUILD' entries were showing in the drop-downs for selecting guilds in the LFP window,
// so just fill unused entries with an empty string instead.
buffer[pos] = '\0';
}
guild_list_messaging.no_of_guilds = m_guilds.size();
guild_list_messaging.string_length = string_length;
strn0cpy((char *) buffer, head_name, 64);
return guild_list_messaging;
std::map<uint32, GuildInfo *>::const_iterator cur, end;
cur = m_guilds.begin();
end = m_guilds.end();
for (; cur != end; ++cur) {
pos = 64 + (64 * cur->first);
strn0cpy((char *) buffer + pos, cur->second->name.c_str(), 64);
}
return (buffer);
}
const char *BaseGuildManager::GetRankName(uint32 guild_id, uint8 rank) const
@@ -1071,7 +1090,7 @@ bool BaseGuildManager::IsGuildLeader(uint32 guild_id, uint32 char_id) const
LogGuilds("Check leader for char [{}]: invalid guild", char_id);
return (false); //invalid guild
}
LogGuilds("Check leader for guild [{}], char [{}]: leader id=[{}]", guild_id, char_id, res->second->leader);
LogGuilds("Check leader for guild [{}]\, char [{}]\: leader id=[{}]", guild_id, char_id, res->second->leader);
return (char_id == res->second->leader);
}
+2 -1
View File
@@ -134,7 +134,7 @@ class BaseGuildManager
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
bool CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const;
bool UpdateDbBankerFlag(uint32 charid, bool is_banker);
GuildsListMessaging_Struct MakeGuildList();
uint8* MakeGuildList(const char* head_name, uint32& length) const; //make a guild list packet, returns ownership of the buffer.
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
uint32 GetGuildIDByName(const char *GuildName);
uint32 GetGuildIDByCharacterID(uint32 character_id);
@@ -208,6 +208,7 @@ class BaseGuildManager
bool _StoreGuildDB(uint32 guild_id);
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
uint32 _GetFreeGuildID();
GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in);
};
#endif /*GUILD_BASE_H_*/
File diff suppressed because it is too large Load Diff
+11 -16
View File
@@ -57,8 +57,6 @@ public:
inline std::list<EQ::ItemInstance*>::const_iterator cbegin() { return m_list.cbegin(); }
inline std::list<EQ::ItemInstance*>::const_iterator cend() { return m_list.cend(); }
inline std::list<EQ::ItemInstance*>::iterator begin() { return m_list.begin(); }
inline std::list<EQ::ItemInstance*>::iterator end() { return m_list.end(); }
inline int size() { return static_cast<int>(m_list.size()); } // TODO: change to size_t
inline bool empty() { return m_list.empty(); }
@@ -134,7 +132,7 @@ namespace EQ
// Swap items in inventory
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint32 deity_id = Deity::Unknown, uint8 level = 0);
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
// Remove item from inventory
bool DeleteItem(int16 slot_id, int16 quantity = 0);
@@ -149,13 +147,13 @@ namespace EQ
bool HasItemEquippedByID(uint32 item_id);
// Check how many of a specific item the player has equipped by Item ID
uint32 CountItemEquippedByID(uint32 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
uint32 CountAugmentEquippedByID(uint32 item_id);
int CountAugmentEquippedByID(uint32 item_id);
// Get a list of augments from a specific slot ID
std::vector<uint32> GetAugmentIDsBySlotID(int16 slot_id);
@@ -178,8 +176,6 @@ namespace EQ
// Locate an available inventory slot
int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false);
int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = invslot::GENERAL_BEGIN, uint8 bag_start = invbag::SLOT_BEGIN);
int16 FindFirstFreeSlotThatFitsItem(const EQ::ItemData *inst);
int16 FindFirstFreeSlotThatFitsItemWithStacking(ItemInstance *inst) const;
// Calculate slot_id for an item within a bag
static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id
@@ -201,25 +197,26 @@ namespace EQ
uint8 FindBrightestLightType();
void dumpEntireInventory();
void dumpWornItems();
void dumpInventory();
void dumpBankItems();
void dumpSharedBankItems();
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, const std::string& value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, int value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, float value);
void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, bool value);
std::string GetCustomItemData(int16 slot_id, const std::string& identifier);
static const int GetItemStatValue(uint32 item_id, const std::string& identifier);
std::map<int16, ItemInstance*>& GetWorn() { return m_worn; }
std::map<int16, ItemInstance*>& GetPersonal() { return m_inv; }
int16 HasEvolvingItem(uint64 evolve_unique_id, uint8 quantity, uint8 where);
inline int16 PushItem(int16 slot_id, ItemInstance* inst) { return _PutItem(slot_id, inst); }
protected:
///////////////////////////////
// Protected Methods
///////////////////////////////
int GetSlotByItemInstCollection(const std::map<int16, ItemInstance*> &collection, ItemInstance *inst);
void dumpItemCollection(const std::map<int16, ItemInstance*> &collection);
void dumpBagContents(ItemInstance *inst, std::map<int16, ItemInstance*>::const_iterator *it);
// Retrieves item within an inventory bucket
ItemInstance* _GetItem(const std::map<int16, ItemInstance*>& bucket, int16 slot_id) const;
@@ -234,8 +231,6 @@ namespace EQ
int16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity);
int16 _HasItemByLoreGroup(std::map<int16, ItemInstance*>& bucket, uint32 loregroup);
int16 _HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup);
int16 _HasEvolvingItem(std::map<int16, ItemInstance*>& bucket, uint64 evolve_unique_id, uint8 quantity);
int16 _HasEvolvingItem(ItemInstQueue& iqueue, uint64 evolve_unique_id, uint8 quantity);
// Player inventory
+21 -136
View File
@@ -81,79 +81,45 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
);
}
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include <iostream>
#include <string>
#include <cstring>
/**
* Gets local address - pings google to inspect what interface was used locally
* @return
*/
std::string IpUtil::GetLocalIPAddress()
{
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
return "";
}
#endif
char my_ip_address[INET_ADDRSTRLEN];
char my_ip_address[16];
unsigned int my_port;
struct sockaddr_in server_address{};
struct sockaddr_in my_address{};
int sockfd;
int sockfd;
// Create a UDP socket
#ifdef _WIN32
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == INVALID_SOCKET) {
WSACleanup();
return "";
}
#else
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
// Connect to server
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return "";
}
#endif
// Set server_addr (dummy address)
// Set server_addr
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("8.8.8.8"); // Google DNS
server_address.sin_port = htons(53); // DNS port
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("172.217.160.99");
server_address.sin_port = htons(80);
// Perform a dummy connection to the server (UDP)
connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
// Connect to server
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
close(sockfd);
return "";
}
// Get my IP address
// 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);
#ifdef _WIN32
closesocket(sockfd);
WSACleanup();
#else
close(sockfd);
#endif
LogInfo("Local IP Address [{}]", my_ip_address);
return std::string(my_ip_address);
return fmt::format("{}", my_ip_address);
}
/**
* Gets public address
* Uses various websites as options to return raw public IP back to the client
@@ -259,84 +225,3 @@ bool IpUtil::IsIPAddress(const std::string &ip_address)
}
#include <iostream>
#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // Link against Winsock library
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
#include <iostream>
#include <string>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h> // For inet_pton
#pragma comment(lib, "ws2_32.lib") // Link against Winsock library
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> // For inet_pton
#include <unistd.h>
#endif
bool IpUtil::IsPortInUse(const std::string& ip, int port) {
bool in_use = false;
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed\n";
return true; // Assume in use on failure
}
#endif
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
#ifdef _WIN32
WSACleanup();
#endif
return true; // Assume in use on failure
}
#ifdef _WIN32
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&opt, sizeof(opt)); // Windows-specific
#else
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // Linux/macOS
#endif
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
// Convert IP address from string to binary format
if (inet_pton(AF_INET, ip.c_str(), &addr.sin_addr) <= 0) {
std::cerr << "Invalid IP address format: " << ip << std::endl;
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
return true; // Assume in use on failure
}
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
in_use = true; // Bind failed, port is in use
}
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
return in_use;
}
-1
View File
@@ -37,7 +37,6 @@ public:
int port
);
static bool IsIPAddress(const std::string &ip_address);
static bool IsPortInUse(const std::string& ip, int port);
};
-28
View File
@@ -220,34 +220,6 @@ bool EQ::ItemData::IsType1HWeapon() const
return ((ItemType == item::ItemType1HBlunt) || (ItemType == item::ItemType1HSlash) || (ItemType == item::ItemType1HPiercing) || (ItemType == item::ItemTypeMartial));
}
bool EQ::ItemData::IsPetUsable() const
{
if (ItemClass == item::ItemClassBag) {
return true;
}
// if it's a misc item and has slots, it's wearable
// this item type is conflated with many other item types
if (ItemClass == item::ItemTypeMisc && Slots != 0) {
return true;
}
switch (ItemType) {
case item::ItemType1HBlunt:
case item::ItemType1HSlash:
case item::ItemType1HPiercing:
case item::ItemType2HBlunt:
case item::ItemType2HSlash:
case item::ItemTypeMartial:
case item::ItemTypeShield:
case item::ItemTypeArmor:
case item::ItemTypeJewelry:
return true;
default:
return false;
}
}
bool EQ::ItemData::IsType2HWeapon() const
{
return ((ItemType == item::ItemType2HBlunt) || (ItemType == item::ItemType2HSlash) || (ItemType == item::ItemType2HPiercing));
+66 -70
View File
@@ -58,75 +58,72 @@ namespace EQ
};
enum ItemType : uint8 {
/*9138*/ ItemType1HSlash = 0,
/*9141*/ ItemType2HSlash,
/*9140*/ ItemType1HPiercing,
/*9139*/ ItemType1HBlunt,
/*9142*/ ItemType2HBlunt,
/*5504*/ ItemTypeBow, // 5
/*----*/ ItemTypeUnknown1,
/*----*/ ItemTypeLargeThrowing,
/*5505*/ ItemTypeShield,
/*5506*/ ItemTypeScroll,
/*5507*/ ItemTypeArmor, // 10
/*5508*/ ItemTypeMisc, // a lot of random crap has this item use.
/*7564*/ ItemTypeLockPick,
/*----*/ ItemTypeUnknown2,
/*5509*/ ItemTypeFood,
/*5510*/ ItemTypeDrink, // 15
/*5511*/ ItemTypeLight,
/*5512*/ ItemTypeCombinable, // not all stackable items are this use...
/*5513*/ ItemTypeBandage,
/*----*/ ItemTypeSmallThrowing,
/*----*/ ItemTypeSpell, // 20 // spells and tomes
/*5514*/ ItemTypePotion,
/*----*/ ItemTypeUnknown3,
/*0406*/ ItemTypeWindInstrument,
/*0407*/ ItemTypeStringedInstrument,
/*0408*/ ItemTypeBrassInstrument, // 25
/*0405*/ ItemTypePercussionInstrument,
/*5515*/ ItemTypeArrow,
/*----*/ ItemTypeUnknown4,
/*5521*/ ItemTypeJewelry,
/*----*/ ItemTypeSkull, // 30
/*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...)
/*5517*/ ItemTypeNote,
/*5518*/ ItemTypeKey,
/*----*/ ItemTypeCoin,
/*5520*/ ItemType2HPiercing, // 35
/*----*/ ItemTypeFishingPole,
/*----*/ ItemTypeFishingBait,
/*5519*/ ItemTypeAlcohol,
/*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?)
/*----*/ ItemTypeCompass, // 40
/*----*/ ItemTypeUnknown5,
/*----*/ ItemTypePoison, // might be wrong, but includes poisons
/*----*/ ItemTypeUnknown6,
/*----*/ ItemTypeUnknown7,
/*5522*/ ItemTypeMartial, // 45
/*----*/ ItemTypeAllEffects,
/*----*/ ItemTypeUnknown9,
/*----*/ ItemTypeUnknown10,
/*----*/ ItemTypeFocusEffect,
/*----*/ ItemTypeSinging, // 50
/*5750*/ ItemTypeAllInstrumentTypes,
/*5776*/ ItemTypeCharm,
/*----*/ ItemTypeDye,
/*----*/ ItemTypeAugmentation,
/*----*/ ItemTypeAugmentationSolvent, // 55
/*----*/ ItemTypeAugmentationDistiller,
/*----*/ ItemTypeAlternateAbility,
/*----*/ ItemTypeFellowshipKit,
/*----*/ ItemTypeUnknown13,
/*----*/ ItemTypeRecipe, // 60
/*----*/ ItemTypeAdvancedRecipe,
/*----*/ ItemTypeJournal, // only one(1) database entry
/*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage)
/*5881*/ ItemTypePerfectedAugmentationDistiller,
/*----*/ ItemTypeCount,
/*----*/ ItemTypeCollectible,
/*----*/ ItemTypeContainer,
/*----*/ ItemTypeAll = 0xFF
/*9138*/ ItemType1HSlash = 0,
/*9141*/ ItemType2HSlash,
/*9140*/ ItemType1HPiercing,
/*9139*/ ItemType1HBlunt,
/*9142*/ ItemType2HBlunt,
/*5504*/ ItemTypeBow, // 5
/*----*/ ItemTypeUnknown1,
/*----*/ ItemTypeLargeThrowing,
/*5505*/ ItemTypeShield,
/*5506*/ ItemTypeScroll,
/*5507*/ ItemTypeArmor, // 10
/*5508*/ ItemTypeMisc, // a lot of random crap has this item use.
/*7564*/ ItemTypeLockPick,
/*----*/ ItemTypeUnknown2,
/*5509*/ ItemTypeFood,
/*5510*/ ItemTypeDrink, // 15
/*5511*/ ItemTypeLight,
/*5512*/ ItemTypeCombinable, // not all stackable items are this use...
/*5513*/ ItemTypeBandage,
/*----*/ ItemTypeSmallThrowing,
/*----*/ ItemTypeSpell, // 20 // spells and tomes
/*5514*/ ItemTypePotion,
/*----*/ ItemTypeUnknown3,
/*0406*/ ItemTypeWindInstrument,
/*0407*/ ItemTypeStringedInstrument,
/*0408*/ ItemTypeBrassInstrument, // 25
/*0405*/ ItemTypePercussionInstrument,
/*5515*/ ItemTypeArrow,
/*----*/ ItemTypeUnknown4,
/*5521*/ ItemTypeJewelry,
/*----*/ ItemTypeSkull, // 30
/*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...)
/*5517*/ ItemTypeNote,
/*5518*/ ItemTypeKey,
/*----*/ ItemTypeCoin,
/*5520*/ ItemType2HPiercing, // 35
/*----*/ ItemTypeFishingPole,
/*----*/ ItemTypeFishingBait,
/*5519*/ ItemTypeAlcohol,
/*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?)
/*----*/ ItemTypeCompass, // 40
/*----*/ ItemTypeUnknown5,
/*----*/ ItemTypePoison, // might be wrong, but includes poisons
/*----*/ ItemTypeUnknown6,
/*----*/ ItemTypeUnknown7,
/*5522*/ ItemTypeMartial, // 45
/*----*/ ItemTypeUnknown8,
/*----*/ ItemTypeUnknown9,
/*----*/ ItemTypeUnknown10,
/*----*/ ItemTypeUnknown11,
/*----*/ ItemTypeSinging, // 50
/*5750*/ ItemTypeAllInstrumentTypes,
/*5776*/ ItemTypeCharm,
/*----*/ ItemTypeDye,
/*----*/ ItemTypeAugmentation,
/*----*/ ItemTypeAugmentationSolvent, // 55
/*----*/ ItemTypeAugmentationDistiller,
/*----*/ ItemTypeUnknown12,
/*----*/ ItemTypeFellowshipKit,
/*----*/ ItemTypeUnknown13,
/*----*/ ItemTypeRecipe, // 60
/*----*/ ItemTypeAdvancedRecipe,
/*----*/ ItemTypeJournal, // only one(1) database entry
/*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage)
/*5881*/ ItemTypePerfectedAugmentationDistiller,
/*----*/ ItemTypeCount
/*
Unknowns:
@@ -550,7 +547,6 @@ namespace EQ
bool IsType1HWeapon() const;
bool IsType2HWeapon() const;
bool IsTypeShield() const;
bool IsPetUsable() const;
bool IsQuestItem() const;
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
+96 -271
View File
@@ -25,7 +25,6 @@
#include "rulesys.h"
#include "shareddb.h"
#include "strings.h"
#include "evolving_items.h"
//#include "../common/light_source.h"
@@ -33,11 +32,10 @@
//#include <iostream>
int32 next_item_serial_number = 1;
std::unordered_set<uint64> guids{};
int32 NextItemInstSerialNumber = 1;
static inline int32 GetNextItemInstSerialNumber() {
static inline int32 GetNextItemInstSerialNumber()
{
// The Bazaar relies on each item a client has up for Trade having a unique
// identifier. This 'SerialNumber' is sent in Serialized item packets and
// is used in Bazaar packets to identify the item a player is buying or inspecting.
@@ -48,18 +46,12 @@ static inline int32 GetNextItemInstSerialNumber()
// NextItemInstSerialNumber is the next one to hand out.
//
// It is very unlikely to reach 2,147,483,647. Maybe we should call abort(), rather than wrapping back to 1.
if (next_item_serial_number >= INT32_MAX) {
next_item_serial_number = 1;
}
else {
next_item_serial_number++;
}
if(NextItemInstSerialNumber >= INT_MAX)
NextItemInstSerialNumber = 1;
else
NextItemInstSerialNumber++;
while (guids.contains(next_item_serial_number)) {
next_item_serial_number++;
}
return next_item_serial_number;
return NextItemInstSerialNumber;
}
//
@@ -77,10 +69,6 @@ EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
m_color = m_item->Color;
}
if (IsEvolving()) {
SetTimer("evolve", RuleI(EvolvingItems, DelayUponEquipping));
}
m_SerialNumber = GetNextItemInstSerialNumber();
}
@@ -100,10 +88,6 @@ EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges
m_color = 0;
}
if (IsEvolving()) {
SetTimer("evolve", RuleI(EvolvingItems, DelayUponEquipping));
}
m_SerialNumber = GetNextItemInstSerialNumber();
}
@@ -155,6 +139,7 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
m_exp = copy.m_exp;
m_evolveLvl = copy.m_evolveLvl;
m_activated = copy.m_activated;
if (copy.m_scaledItem) {
m_scaledItem = new ItemData(*copy.m_scaledItem);
@@ -162,7 +147,12 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
m_scaledItem = nullptr;
}
m_evolving_details = copy.m_evolving_details;
if (copy.m_evolveInfo) {
m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo);
} else {
m_evolveInfo = nullptr;
}
m_scaling = copy.m_scaling;
m_ornamenticon = copy.m_ornamenticon;
m_ornamentidfile = copy.m_ornamentidfile;
@@ -177,6 +167,7 @@ EQ::ItemInstance::~ItemInstance()
Clear();
safe_delete(m_item);
safe_delete(m_scaledItem);
safe_delete(m_evolveInfo);
}
// Query item type
@@ -312,34 +303,47 @@ int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
return INVALID_INDEX;
}
for (int16 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) {
if (IsAugmentSlotAvailable(augment_type, slot_id)) {
return slot_id;
auto i = invaug::SOCKET_BEGIN;
for (; i <= invaug::SOCKET_END; ++i) {
if (GetItem(i)) {
continue;
}
if (
augment_type == -1 ||
(
m_item->AugSlotType[i] &&
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
)
) {
break;
}
}
return INVALID_INDEX;
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
}
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const
{
if (!m_item || !m_item->IsClassCommon() || GetItem(slot)) {
if (!m_item || !m_item->IsClassCommon()) {
return false;
}
return (
if (
(
augment_type == -1 ||
(
m_item->AugSlotType[slot] &&
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
)
) &&
(
RuleB(Items, AugmentItemAllowInvisibleAugments) ||
!GetItem(slot) &&
m_item->AugSlotVisible[slot]
) &&
augment_type == -1 ||
(
m_item->AugSlotType[slot] &&
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
)
);
) {
return true;
}
return false;
}
// Retrieve item inside container
@@ -906,32 +910,24 @@ bool EQ::ItemInstance::IsSlotAllowed(int16 slot_id) const {
bool EQ::ItemInstance::IsDroppable(bool recurse) const
{
if (!m_item) {
if (!m_item)
return false;
}
/*if (m_ornamentidfile) // not implemented
return false;*/
if (m_attuned) {
if (m_attuned)
return false;
}
if (RuleI(World, FVNoDropFlag) == FVNoDropFlagRule::Enabled && m_item->FVNoDrop == 0) {
return true;
}
if (m_item->NoDrop == 0) {
/*if (m_item->FVNoDrop != 0) // not implemented
return false;*/
if (m_item->NoDrop == 0)
return false;
}
if (recurse) {
for (auto iter: m_contents) {
if (!iter.second) {
for (auto iter : m_contents) {
if (!iter.second)
continue;
}
if (!iter.second->IsDroppable(recurse)) {
if (!iter.second->IsDroppable(recurse))
return false;
}
}
}
@@ -1040,6 +1036,29 @@ void EQ::ItemInstance::ScaleItem() {
m_scaledItem->CharmFileID = 0; // this stops the client from trying to scale the item itself.
}
bool EQ::ItemInstance::EvolveOnAllKills() const {
return (m_evolveInfo && m_evolveInfo->AllKills);
}
int8 EQ::ItemInstance::GetMaxEvolveLvl() const {
if (m_evolveInfo)
return m_evolveInfo->MaxLvl;
else
return 0;
}
uint32 EQ::ItemInstance::GetKillsNeeded(uint8 currentlevel) {
uint32 kills = -1; // default to -1 (max uint32 value) because this value is usually divided by, so we don't want to ever return zero.
if (m_evolveInfo)
if (currentlevel != m_evolveInfo->MaxLvl)
kills = m_evolveInfo->LvlKills[currentlevel - 1];
if (kills == 0)
kills = -1;
return kills;
}
void EQ::ItemInstance::SetTimer(std::string name, uint32 time) {
Timer t(time);
t.Start(time, false);
@@ -1273,7 +1292,7 @@ int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
return race;
}
int EQ::ItemInstance::GetItemBaneDamageBody(uint8 against, bool augments) const
int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const
{
int64 damage = 0;
const auto item = GetItem();
@@ -1782,222 +1801,28 @@ uint32 EQ::ItemInstance::GetItemGuildFavor() const
return 0;
}
std::vector<uint32> EQ::ItemInstance::GetAugmentIDs() const
{
std::vector<uint32> augments;
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; slot_id++) {
augments.push_back(GetAugment(slot_id) ? GetAugmentItemID(slot_id) : 0);
}
return augments;
//
// class EvolveInfo
//
EvolveInfo::EvolveInfo() {
// nothing here yet
}
std::vector<std::string> EQ::ItemInstance::GetAugmentNames() const
{
std::vector<std::string> augment_names;
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; slot_id++) {
const auto augment = GetAugment(slot_id);
augment_names.push_back(augment ? augment->GetItem()->Name : "None");
}
return augment_names;
EvolveInfo::EvolveInfo(uint32 first, uint8 max, bool allkills, uint32 L2, uint32 L3, uint32 L4, uint32 L5, uint32 L6, uint32 L7, uint32 L8, uint32 L9, uint32 L10) {
FirstItem = first;
MaxLvl = max;
AllKills = allkills;
LvlKills[0] = L2;
LvlKills[1] = L3;
LvlKills[2] = L4;
LvlKills[3] = L5;
LvlKills[4] = L6;
LvlKills[5] = L7;
LvlKills[6] = L8;
LvlKills[7] = L9;
LvlKills[8] = L10;
}
int EQ::ItemInstance::GetItemRegen(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->Regen;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemRegen();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemManaRegen(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->ManaRegen;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemManaRegen();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemDamageShield(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->DamageShield;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemDamageShield();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemDSMitigation(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->DSMitigation;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemDSMitigation();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemHealAmt(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->HealAmt;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemHealAmt();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemSpellDamage(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->SpellDmg;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemSpellDamage();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemClairvoyance(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->Clairvoyance;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemClairvoyance();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemSkillsStat(EQ::skills::SkillType skill, bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->ExtraDmgSkill == skill ? item->ExtraDmgAmt : 0;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemSkillsStat(skill);
}
}
}
}
return stat;
}
void EQ::ItemInstance::AddGUIDToMap(uint64 existing_serial_number)
{
guids.emplace(existing_serial_number);
}
void EQ::ItemInstance::ClearGUIDMap()
{
guids.clear();
}
bool EQ::ItemInstance::TransferOwnership(Database &db, const uint32 to_char_id) const
{
if (!to_char_id || !IsEvolving()) {
return false;
}
SetEvolveCharID(to_char_id);
CharacterEvolvingItemsRepository::UpdateCharID(db, GetEvolveUniqueID(), to_char_id);
return true;
}
uint32 EQ::ItemInstance::GetAugmentEvolveUniqueID(uint8 augment_index) const
{
if (!m_item || !m_item->IsClassCommon()) {
return 0;
}
const auto item = GetItem(augment_index);
if (item) {
return item->GetEvolveUniqueID();
}
return 0;
}
void EQ::ItemInstance::SetTimer(std::string name, uint32 time) const{
Timer t(time);
t.Start(time, false);
m_timers[name] = t;
}
void EQ::ItemInstance::SetEvolveEquipped(const bool in) const
{
if (!IsEvolving()) {
return;
}
m_evolving_details.equipped = in;
if (in && !GetTimers().contains("evolve")) {
SetTimer("evolve", RuleI(EvolvingItems, DelayUponEquipping));
return;
}
if (in) {
GetTimers().at("evolve").SetTimer(RuleI(EvolvingItems, DelayUponEquipping));
return;
}
GetTimers().at("evolve").Disable();
EvolveInfo::~EvolveInfo() {
}
+49 -69
View File
@@ -23,7 +23,6 @@
#ifndef COMMON_ITEM_INSTANCE_H
#define COMMON_ITEM_INSTANCE_H
#include "evolving_items.h"
class ItemParse; // Parses item packets
@@ -35,7 +34,6 @@ class EvolveInfo; // Stores information about an evolving item family
#include "../common/bodytypes.h"
#include "../common/deity.h"
#include "../common/memory_buffer.h"
#include "../common/repositories/character_evolving_items_repository.h"
#include <map>
@@ -207,9 +205,13 @@ namespace EQ
bool IsDroppable(bool recurse = true) const;
bool IsScaling() const { return m_scaling; }
bool IsEvolving() const { return (m_evolveLvl >= 1); }
uint32 GetExp() const { return m_exp; }
void SetExp(uint32 exp) { m_exp = exp; }
void AddExp(uint32 exp) { m_exp += exp; }
bool IsActivated() { return m_activated; }
void SetActivated(bool activated) { m_activated = activated; }
int8 GetEvolveLvl() const { return m_evolveLvl; }
void SetScaling(bool v) { m_scaling = v; }
uint32 GetOrnamentationIcon() const { return m_ornamenticon; }
void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; }
@@ -224,6 +226,9 @@ namespace EQ
void Initialize(SharedDatabase *db = nullptr);
void ScaleItem();
bool EvolveOnAllKills() const;
int8 GetMaxEvolveLvl() const;
uint32 GetKillsNeeded(uint8 currentlevel);
std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; }
void Serialize(OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); }
@@ -231,9 +236,8 @@ namespace EQ
inline int32 GetSerialNumber() const { return m_SerialNumber; }
inline void SetSerialNumber(int32 id) { m_SerialNumber = id; }
std::map<std::string, ::Timer>& GetTimers() const { return m_timers; }
std::map<std::string, ::Timer>& GetTimers() { return m_timers; }
void SetTimer(std::string name, uint32 time);
void SetTimer(std::string name, uint32 time) const;
void StopTimer(std::string name);
void ClearTimers();
@@ -261,12 +265,11 @@ namespace EQ
// these two are just quick checks
int GetItemBaneDamageBody(bool augments = false) const;
int GetItemBaneDamageRace(bool augments = false) const;
int GetItemBaneDamageBody(uint8 against, bool augments = false) const;
int GetItemBaneDamageBody(bodyType against, bool augments = false) const;
int GetItemBaneDamageRace(uint16 against, bool augments = false) const;
int GetItemMagical(bool augments = false) const;
int GetItemHP(bool augments = false) const;
int GetItemMana(bool augments = false) const;
int GetItemManaRegen(bool augments = false) const;
int GetItemEndur(bool augments = false) const;
int GetItemAttack(bool augments = false) const;
int GetItemStr(bool augments = false) const;
@@ -296,46 +299,7 @@ namespace EQ
int GetItemHeroicDR(bool augments = false) const;
int GetItemHeroicCorrup(bool augments = false) const;
int GetItemHaste(bool augments = false) const;
int GetItemRegen(bool augments = false) const;
int GetItemDamageShield(bool augments = false) const;
int GetItemDSMitigation(bool augments = false) const;
int GetItemHealAmt(bool augments = false) const;
int GetItemSpellDamage(bool augments = false) const;
int GetItemClairvoyance(bool augments = false) const;
int GetItemSkillsStat(EQ::skills::SkillType skill, bool augments = false) const;
uint32 GetItemGuildFavor() const;
std::vector<uint32> GetAugmentIDs() const;
std::vector<std::string> GetAugmentNames() const;
static void AddGUIDToMap(uint64 existing_serial_number);
static void ClearGUIDMap();
// evolving items stuff
CharacterEvolvingItemsRepository::CharacterEvolvingItems &GetEvolvingDetails() const { return m_evolving_details; }
int8 GetEvolveLvl() const { if (GetItem()) { return GetItem()->EvolvingLevel; } return false; }
bool IsEvolving() const { if (GetItem()) { return GetItem()->EvolvingItem; } return false; }
int8 GetMaxEvolveLvl() const { if (GetItem()) { return GetItem()->EvolvingMax; } return false; }
bool GetEvolveActivated() const { return m_evolving_details.activated ? true : false; }
bool GetEvolveEquipped() const { return m_evolving_details.equipped ? true : false; }
double GetEvolveProgression() const { return m_evolving_details.progression; }
uint64 GetEvolveUniqueID() const { return m_evolving_details.id; }
uint32 GetEvolveCharID() const { return m_evolving_details.character_id; }
uint32 GetEvolveItemID() const { return m_evolving_details.item_id; }
uint32 GetEvolveLoreID() const { if (GetItem()) { return GetItem()->EvolvingID; } return false; }
uint64 GetEvolveCurrentAmount() const { return m_evolving_details.current_amount; }
uint32 GetEvolveFinalItemID() const { return m_evolving_details.final_item_id; }
uint32 GetAugmentEvolveUniqueID(uint8 augment_index) const;
void SetEvolveEquipped(const bool in) const;
void SetEvolveActivated(const bool in) const { m_evolving_details.activated = in; }
void SetEvolveProgression(const double in) const { m_evolving_details.progression = in; }
void SetEvolveUniqueID(const uint64 in) const { m_evolving_details.id = in; }
void SetEvolveCharID(const uint32 in) const { m_evolving_details.character_id = in; }
void SetEvolveItemID(const uint32 in) const { m_evolving_details.item_id = in; }
void SetEvolveCurrentAmount(const uint64 in) const { m_evolving_details.current_amount = in; }
void SetEvolveAddToCurrentAmount(const uint64 in) const { m_evolving_details.current_amount += in; }
void SetEvolveFinalItemID(const uint32 in) const { m_evolving_details.final_item_id = in; }
bool TransferOwnership(Database& db, const uint32 to_char_id) const;
void CalculateEvolveProgression() const { m_evolving_details.progression = evolving_items_manager.CalculateProgression(GetEvolveCurrentAmount(), GetID()); }
protected:
//////////////////////////
@@ -348,32 +312,48 @@ namespace EQ
void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; }
ItemInstTypes m_use_type{ItemInstNormal};// Usage type for item
const ItemData * m_item{nullptr}; // Ptr to item data
int16 m_charges{0}; // # of charges for chargeable items
uint32 m_price{0}; // Bazaar /trader price
uint32 m_color{0};
uint32 m_merchantslot{0};
int16 m_currentslot{0};
bool m_attuned{false};
int32 m_merchantcount{1};//number avaliable on the merchant, -1=unlimited
int32 m_SerialNumber{0}; // Unique identifier for this instance of an item. Needed for Bazaar.
uint32 m_exp{0};
int8 m_evolveLvl{0};
ItemData * m_scaledItem{nullptr};
bool m_scaling{false};
uint32 m_ornamenticon{0};
uint32 m_ornamentidfile{0};
uint32 m_new_id_file{0};
uint32 m_ornament_hero_model{0};
uint32 m_recast_timestamp{0};
int m_task_delivered_count{0};
mutable CharacterEvolvingItemsRepository::CharacterEvolvingItems m_evolving_details{};
ItemInstTypes m_use_type {ItemInstNormal}; // Usage type for item
const ItemData* m_item {nullptr}; // Ptr to item data
int16 m_charges {0}; // # of charges for chargeable items
uint32 m_price {0}; // Bazaar /trader price
uint32 m_color {0};
uint32 m_merchantslot {0};
int16 m_currentslot {0};
bool m_attuned {false};
int32 m_merchantcount {1}; //number avaliable on the merchant, -1=unlimited
int32 m_SerialNumber {0}; // Unique identifier for this instance of an item. Needed for Bazaar.
uint32 m_exp {0};
int8 m_evolveLvl {0};
bool m_activated {false};
ItemData* m_scaledItem {nullptr};
::EvolveInfo* m_evolveInfo {nullptr};
bool m_scaling {false};
uint32 m_ornamenticon {0};
uint32 m_ornamentidfile {0};
uint32 m_new_id_file {0};
uint32 m_ornament_hero_model {0};
uint32 m_recast_timestamp {0};
int m_task_delivered_count {0};
// Items inside of this item (augs or contents) {};
std::map<uint8, ItemInstance*> m_contents {}; // Zero-based index: min=0, max=9
std::map<std::string, std::string> m_custom_data {};
mutable std::map<std::string, ::Timer> m_timers {};
std::map<uint8, ItemInstance*> m_contents {}; // Zero-based index: min=0, max=9
std::map<std::string, std::string> m_custom_data {};
std::map<std::string, ::Timer> m_timers {};
};
}
class EvolveInfo {
public:
friend class EQ::ItemInstance;
//temporary
uint16 LvlKills[9];
uint32 FirstItem;
uint8 MaxLvl;
bool AllKills;
EvolveInfo();
EvolveInfo(uint32 first, uint8 max, bool allkills, uint32 L2, uint32 L3, uint32 L4, uint32 L5, uint32 L6, uint32 L7, uint32 L8, uint32 L9, uint32 L10);
~EvolveInfo();
};
#endif /*COMMON_ITEM_INSTANCE_H*/
-1
View File
@@ -25,7 +25,6 @@ struct LootItem {
uint16 trivial_max_level;
uint16 npc_min_level;
uint16 npc_max_level;
uint32 lootdrop_id; // required for zone state referencing
};
typedef std::list<LootItem*> LootItems;
-220
View File
@@ -1,220 +0,0 @@
#ifndef EQEMU_KSM_HPP
#define EQEMU_KSM_HPP
#include "../eqemu_logsys.h"
#include <iostream>
#include <vector>
#include <cstring>
#ifdef _WIN32
#include <malloc.h> // For _aligned_malloc, _aligned_free
#include <windows.h>
#else
#include <sys/mman.h> // For madvise
#include <unistd.h> // For sysconf, sbrk
#endif
// Page-aligned allocator for std::vector
template <typename T>
class PageAlignedAllocator {
public:
using value_type = T;
PageAlignedAllocator() noexcept = default;
template <typename U>
PageAlignedAllocator(const PageAlignedAllocator<U>&) noexcept {}
T* allocate(std::size_t n) {
void* ptr = nullptr;
size_t size = n * sizeof(T);
#ifdef _WIN32
// Simply allocate memory without alignment
ptr = malloc(size);
if (!ptr) throw std::bad_alloc();
#else
size_t alignment = getPageSize(); // Get the system's page size
if (posix_memalign(&ptr, alignment, size) != 0) {
throw std::bad_alloc();
}
#endif
return static_cast<T*>(ptr);
}
void deallocate(T* p, std::size_t) noexcept {
free(p);
}
private:
size_t getPageSize() const
{
#ifdef _WIN32
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
return sysInfo.dwPageSize; // Page size in bytes
#else
return static_cast<size_t>(sysconf(_SC_PAGESIZE));
#endif
};
};
template <typename T, typename U>
bool operator==(const PageAlignedAllocator<T>&, const PageAlignedAllocator<U>&) noexcept {
return true;
}
template <typename T, typename U>
bool operator!=(const PageAlignedAllocator<T>&, const PageAlignedAllocator<U>&) noexcept {
return false;
}
// Kernel Samepage Merging (KSM) functionality
namespace KSM {
#ifdef _WIN32
// Windows-specific placeholder functions (no-op)
inline void CheckPageAlignment(void* ptr) {
}
inline void* AllocatePageAligned(size_t size) {
return memset(malloc(size), 0, size);
}
inline void MarkMemoryForKSM(void* start, size_t size) {
}
inline void AlignHeapToPageBoundary() {
}
inline void* MarkHeapStart() {
return nullptr;
}
inline size_t MeasureHeapUsage(void* start) {
return 0;
}
#else
// Linux-specific functionality
inline void CheckPageAlignment(void* ptr) {
size_t page_size = sysconf(_SC_PAGESIZE);
if (reinterpret_cast<uintptr_t>(ptr) % page_size == 0) {
LogKSMDetail("Memory is page-aligned [{}]", ptr);
} else {
LogKSMDetail("Memory is NOT page-aligned [{}]", ptr);
}
}
inline void* AllocatePageAligned(size_t size) {
size_t page_size = sysconf(_SC_PAGESIZE);
void* aligned_ptr = nullptr;
if (posix_memalign(&aligned_ptr, page_size, size) != 0) {
LogKSM("Failed to allocate page-aligned memory on Linux. page_size [{}] size [{}] bytes", page_size, size);
}
std::memset(aligned_ptr, 0, size);
return aligned_ptr;
}
inline void MarkMemoryForKSM(void* start, size_t size) {
if (madvise(start, size, MADV_MERGEABLE) == 0) {
LogKSM("Marked memory for KSM | start [{}] size [{}] bytes", start, size);
} else {
perror("madvise failed");
}
}
inline void AlignHeapToPageBoundary() {
size_t page_size = sysconf(_SC_PAGESIZE);
if (page_size == 0) {
LogKSM("Failed to retrieve page size SC_PAGESIZE [{}]", page_size);
return;
}
void* current_break = sbrk(0);
if (current_break == (void*)-1) {
LogKSM("Failed to retrieve the current program break");
return;
}
uintptr_t current_address = reinterpret_cast<uintptr_t>(current_break);
size_t misalignment = current_address % page_size;
if (misalignment != 0) {
size_t adjustment = page_size - misalignment;
if (sbrk(adjustment) == (void*)-1) {
LogKSM("Failed to align heap to page boundary. adjustment [{}] bytes", adjustment);
return;
}
}
LogKSMDetail("Heap aligned to next page boundary. Current break [{}]", sbrk(0));
}
inline void* MarkHeapStart() {
void* current_pos = sbrk(0);
AlignHeapToPageBoundary();
return current_pos;
}
inline size_t MeasureHeapUsage(void* start) {
void* current_break = sbrk(0);
return static_cast<char*>(current_break) - static_cast<char*>(start);
}
#endif
inline size_t getPageSize()
{
#ifdef _WIN32
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
return sysInfo.dwPageSize; // Page size in bytes
#else
return static_cast<size_t>(sysconf(_SC_PAGESIZE)); // POSIX page size
#endif
};
template <typename T>
inline void PageAlignVectorAligned(std::vector<T, PageAlignedAllocator<T>>& vec) {
if (vec.empty()) {
return;
}
size_t page_size = getPageSize();
void* start = vec.data();
size_t size = vec.size() * sizeof(T);
// Check if the memory is page-aligned
if (reinterpret_cast<std::uintptr_t>(start) % page_size != 0) {
// Allocate a new aligned vector
std::vector<T, PageAlignedAllocator<T>> aligned_vec(vec.get_allocator());
aligned_vec.reserve(vec.capacity()); // Match capacity to avoid reallocation during copy
// Copy elements from the original vector
aligned_vec.insert(aligned_vec.end(), vec.begin(), vec.end());
// Swap the aligned vector with the original vector
vec.swap(aligned_vec);
// Clear the temporary aligned vector to free its memory
aligned_vec.clear();
// Verify the new alignment
start = vec.data();
if (reinterpret_cast<std::uintptr_t>(start) % page_size != 0) {
throw std::runtime_error("Failed to align vector memory to page boundaries.");
}
LogKSMDetail("Vector reallocated to ensure page alignment. start [{}] size [{}] bytes", start, size);
} else {
LogKSMDetail("Vector is already page-aligned. start [{}] size [{}] bytes", start, size);
}
#ifndef _WIN32
// Mark memory for KSM (only on non-Windows systems)
MarkMemoryForKSM(start, size);
#endif
}
}
#endif // EQEMU_KSM_HPP
-600
View File
@@ -1,600 +0,0 @@
#include "mysql_stmt.h"
#include "eqemu_logsys.h"
#include "mutex.h"
#include "timer.h"
#include <charconv>
namespace mysql
{
void PreparedStmt::StmtDeleter::operator()(MYSQL_STMT* stmt) noexcept
{
// The connection must be locked when closing the stmt to avoid mysql errors
// in case another thread tries to use it during the close. If the mutex is
// changed to one that throws then exceptions need to be caught here.
LockMutex lock(mutex);
mysql_stmt_close(stmt);
}
PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts)
: m_stmt(mysql_stmt_init(&mysql), { mutex }), m_query(std::move(query)), m_mutex(mutex), m_options(opts)
{
LockMutex lock(m_mutex);
if (mysql_stmt_prepare(m_stmt.get(), m_query.c_str(), static_cast<unsigned long>(m_query.size())) != 0)
{
ThrowError(fmt::format("Prepare error: {}", GetStmtError()));
}
m_params.resize(mysql_stmt_param_count(m_stmt.get()));
m_inputs.resize(m_params.size());
}
void PreparedStmt::ThrowError(const std::string& error)
{
LogMySQLError("{}", error);
throw std::runtime_error(error);
}
std::string PreparedStmt::GetStmtError()
{
auto err = mysql_stmt_errno(m_stmt.get());
auto str = mysql_stmt_error(m_stmt.get());
return fmt::format("({}) [{}] for query [{}]", err, str, m_query);
}
template <typename T>
void PreparedStmt::BindInput(size_t index, T value)
{
if (index >= m_inputs.size())
{
ThrowError(fmt::format("Cannot bind input, index {} out of range", index));
}
impl::Bind& arg = m_inputs[index];
arg.is_null = std::is_same_v<T, std::nullptr_t>;
MYSQL_BIND& bind = m_params[index];
bind.is_unsigned = std::is_unsigned_v<T>;
bind.is_null = &arg.is_null;
bind.length = &arg.length;
auto old_type = bind.buffer_type;
if constexpr (std::is_arithmetic_v<T>)
{
if (arg.buffer.size() < sizeof(T))
{
arg.buffer.resize(std::max(sizeof(T), sizeof(int64_t)));
bind.buffer = arg.buffer.data();
m_need_bind = true;
}
memcpy(arg.buffer.data(), &value, sizeof(T));
}
if constexpr (std::is_same_v<T, int8_t> || std::is_same_v<T, uint8_t> || std::is_same_v<T, bool>)
{
bind.buffer_type = MYSQL_TYPE_TINY;
}
else if constexpr (std::is_same_v<T, int16_t> || std::is_same_v<T, uint16_t>)
{
bind.buffer_type = MYSQL_TYPE_SHORT;
}
else if constexpr (std::is_same_v<T, int32_t> || std::is_same_v<T, uint32_t>)
{
bind.buffer_type = MYSQL_TYPE_LONG;
}
else if constexpr (std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>)
{
bind.buffer_type = MYSQL_TYPE_LONGLONG;
}
else if constexpr (std::is_same_v<T, float>)
{
bind.buffer_type = MYSQL_TYPE_FLOAT;
}
else if constexpr (std::is_same_v<T, double>)
{
bind.buffer_type = MYSQL_TYPE_DOUBLE;
}
else if constexpr (std::is_same_v<T, std::string_view>)
{
bind.buffer_type = MYSQL_TYPE_STRING;
if (arg.buffer.empty() || arg.buffer.size() < value.size())
{
arg.buffer.resize(static_cast<size_t>((value.size() + 1) * 1.5));
bind.buffer = arg.buffer.data();
bind.buffer_length = static_cast<unsigned long>(arg.buffer.size());
m_need_bind = true;
}
std::copy(value.begin(), value.end(), arg.buffer.begin());
arg.length = static_cast<unsigned long>(value.size());
}
else if constexpr (!std::is_same_v<T, std::nullptr_t>)
{
static_assert(false_v<T>, "Cannot bind unsupported type");
}
if (old_type != bind.buffer_type)
{
m_need_bind = true;
}
}
void PreparedStmt::BindInput(size_t index, const char* str)
{
BindInput(index, std::string_view(str));
}
void PreparedStmt::BindInput(size_t index, const std::string& str)
{
BindInput(index, std::string_view(str));
}
StmtResult PreparedStmt::Execute()
{
CheckArgs(0);
return DoExecute();
}
StmtResult PreparedStmt::Execute(const std::vector<param_t>& args)
{
CheckArgs(args.size());
for (size_t i = 0; i < args.size(); ++i)
{
std::visit([&](const auto& arg) { BindInput(i, arg); }, args[i]);
}
return DoExecute();
}
template <typename T>
StmtResult PreparedStmt::Execute(const std::vector<T>& args)
{
CheckArgs(args.size());
for (size_t i = 0; i < args.size(); ++i)
{
BindInput(i, args[i]);
}
return DoExecute();
}
void PreparedStmt::CheckArgs(size_t argc)
{
if (argc != m_params.size())
{
ThrowError(fmt::format("Bad arg count (got {}, expected {}) for [{}]", argc, m_params.size(), m_query));
}
}
StmtResult PreparedStmt::DoExecute()
{
BenchTimer timer;
LockMutex lock(m_mutex);
if (m_need_bind && mysql_stmt_bind_param(m_stmt.get(), m_params.data()) != 0)
{
ThrowError(fmt::format("Bind param error: {}", GetStmtError()));
}
m_need_bind = false;
if (mysql_stmt_execute(m_stmt.get()) != 0)
{
ThrowError(fmt::format("Execute error: {}", GetStmtError()));
}
my_bool attr = m_options.use_max_length;
mysql_stmt_attr_set(m_stmt.get(), STMT_ATTR_UPDATE_MAX_LENGTH, &attr);
if (m_options.buffer_results && mysql_stmt_store_result(m_stmt.get()) != 0)
{
ThrowError(fmt::format("Store result error: {}", GetStmtError()));
}
// Result buffers are bound on first execute and re-used if needed
if (m_results.empty())
{
BindResults();
}
StmtResult res(m_stmt.get(), m_results.size());
if (m_results.empty())
{
LogMySQLQuery("{} -- ({} row(s) affected) ({:.6f}s)", m_query, res.RowsAffected(), timer.elapsed());
}
else
{
LogMySQLQuery("{} -- ({} row(s) returned) ({:.6f}s)", m_query, res.RowCount(), timer.elapsed());
}
return res;
}
void PreparedStmt::BindResults()
{
MYSQL_RES* res = mysql_stmt_result_metadata(m_stmt.get());
if (!res)
{
return; // did not produce a result set
}
MYSQL_FIELD* fields = mysql_fetch_fields(res);
m_columns.resize(mysql_num_fields(res));
m_results.resize(m_columns.size());
for (int i = 0; i < static_cast<int>(m_columns.size()); ++i)
{
impl::BindColumn& col = m_columns[i].m_col;
MYSQL_BIND& bind = m_results[i];
col.index = i;
col.name = fields[i].name;
col.buffer_type = fields[i].type;
col.is_unsigned = (fields[i].flags & UNSIGNED_FLAG) != 0;
col.buffer.resize(GetResultBufferSize(fields[i]));
bind.buffer_type = col.buffer_type;
bind.buffer = col.buffer.data();
bind.buffer_length = static_cast<unsigned long>(col.buffer.size());
bind.is_unsigned = col.is_unsigned;
bind.is_null = &col.is_null;
bind.length = &col.length;
bind.error = &col.error;
}
mysql_free_result(res);
if (!m_results.empty() && mysql_stmt_bind_result(m_stmt.get(), m_results.data()) != 0)
{
ThrowError(fmt::format("Bind result error: {}", GetStmtError()));
}
}
int PreparedStmt::GetResultBufferSize(const MYSQL_FIELD& field) const
{
switch (field.type)
{
case MYSQL_TYPE_TINY:
return sizeof(int8_t);
case MYSQL_TYPE_SHORT:
return sizeof(int16_t);
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
return sizeof(int32_t);
case MYSQL_TYPE_LONGLONG:
return sizeof(int64_t);
case MYSQL_TYPE_FLOAT:
return sizeof(float);
case MYSQL_TYPE_DOUBLE:
return sizeof(double);
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
return sizeof(MYSQL_TIME);
default: // if max_length is unavailable for strings buffers are resized on fetch
return field.max_length + 1; // ensure valid buffer created
}
}
StmtRow PreparedStmt::Fetch()
{
StmtRow row;
if (!m_columns.empty())
{
int rc = mysql_stmt_fetch(m_stmt.get());
if (rc == 1)
{
ThrowError(fmt::format("Fetch error: {}", GetStmtError()));
}
if (rc != MYSQL_NO_DATA)
{
if (rc == MYSQL_DATA_TRUNCATED)
{
FetchTruncated();
}
row = StmtRow(m_columns);
}
}
return row;
}
void PreparedStmt::FetchTruncated()
{
for (int i = 0; i < static_cast<int>(m_columns.size()); ++i)
{
impl::BindColumn& col = m_columns[i].m_col;
if (col.error)
{
MYSQL_BIND& bind = m_results[i];
col.buffer.resize(static_cast<size_t>(col.length * 1.5));
bind.buffer = col.buffer.data();
bind.buffer_length = static_cast<unsigned long>(col.buffer.size());
mysql_stmt_fetch_column(m_stmt.get(), &bind, i, 0);
}
}
if (mysql_stmt_bind_result(m_stmt.get(), m_results.data()) != 0)
{
ThrowError(fmt::format("Fetch rebind result error: {}", GetStmtError()));
}
}
// ---------------------------------------------------------------------------
StmtResult::StmtResult(MYSQL_STMT* stmt, size_t columns)
{
m_num_cols = static_cast<int>(columns);
m_num_rows = mysql_stmt_num_rows(stmt); // requires buffered results
m_affected = mysql_stmt_affected_rows(stmt);
m_insert_id = mysql_stmt_insert_id(stmt);
}
// ---------------------------------------------------------------------------
const StmtColumn* StmtRow::GetColumn(size_t index) const
{
return index < m_columns.size() ? &m_columns[index] : nullptr;
}
const StmtColumn* StmtRow::GetColumn(std::string_view name) const
{
auto it = std::ranges::find_if(m_columns,
[name](const StmtColumn& col) { return col.Name() == name; });
return it != m_columns.end() ? &(*it) : nullptr;
}
std::optional<std::string> StmtRow::operator[](size_t index) const
{
return GetStr(index);
}
std::optional<std::string> StmtRow::operator[](std::string_view name) const
{
return GetStr(name);
}
std::optional<std::string> StmtRow::GetStr(size_t index) const
{
const StmtColumn* col = GetColumn(index);
return col ? col->GetStr() : std::nullopt;
}
std::optional<std::string> StmtRow::GetStr(std::string_view name) const
{
const StmtColumn* col = GetColumn(name);
return col ? col->GetStr() : std::nullopt;
}
template <typename T> requires std::is_arithmetic_v<T>
std::optional<T> StmtRow::Get(size_t index) const
{
const StmtColumn* col = GetColumn(index);
return col ? col->Get<T>() : std::nullopt;
}
template <typename T> requires std::is_arithmetic_v<T>
std::optional<T> StmtRow::Get(std::string_view name) const
{
const StmtColumn* col = GetColumn(name);
return col ? col->Get<T>() : std::nullopt;
}
// ---------------------------------------------------------------------------
static time_t MakeTime(const MYSQL_TIME& mt)
{
// buffer mt given in mysql session time zone (assumes local)
std::tm tm{};
tm.tm_year = mt.year - 1900;
tm.tm_mon = mt.month - 1;
tm.tm_mday = mt.day;
tm.tm_hour = mt.hour;
tm.tm_min = mt.minute;
tm.tm_sec = mt.second;
tm.tm_isdst = -1;
return std::mktime(&tm);
}
static int MakeSeconds(const MYSQL_TIME& mt)
{
return (mt.neg ? -1 : 1) * static_cast<int>(mt.hour * 3600 + mt.minute * 60 + mt.second);
}
static uint64_t MakeBits(std::span<const uint8_t> data)
{
// byte stream for bits is in big endian
uint64_t bits = 0;
for (size_t i = 0; i < data.size() && i < sizeof(uint64_t); ++i)
{
bits |= static_cast<uint64_t>(data[data.size() - i - 1] & 0xff) << (i * 8);
}
return bits;
}
template <typename T>
concept has_from_chars = requires (const char* first, const char* last, T value)
{
std::from_chars(first, last, value);
};
template <typename T>
static T FromString(std::string_view sv)
{
if constexpr (std::is_same_v<T, bool>)
{
// return false for empty (zero-length) strings
return !sv.empty();
}
else if constexpr (std::is_same_v<T, float> && !has_from_chars<T>)
{
return std::strtof(std::string(sv).c_str(), nullptr);
}
else if constexpr (std::is_same_v<T, double> && !has_from_chars<T>)
{
return std::strtod(std::string(sv).c_str(), nullptr);
}
else
{
// non numbers return a zero initialized T (could return nullopt instead)
T value = {};
std::from_chars(sv.data(), sv.data() + sv.size(), value);
return value;
}
}
static std::string FormatTime(enum_field_types type, const MYSQL_TIME& mt)
{
switch (type)
{
case MYSQL_TYPE_TIME: // hhh:mm:ss '-838:59:59' to '838:59:59'
return fmt::format("{}{:02d}:{:02d}:{:02d}", mt.neg ? "-" : "", mt.hour, mt.minute, mt.second);
case MYSQL_TYPE_DATE: // YYYY-MM-DD '1000-01-01' to '9999-12-31'
return fmt::format("{}-{:02d}-{:02d}", mt.year, mt.month, mt.day);
case MYSQL_TYPE_DATETIME: // YYYY-MM-DD hh:mm:ss '1000-01-01 00:00:00' to '9999-12-31 23:59:59'
case MYSQL_TYPE_TIMESTAMP: // YYYY-MM-DD hh:mm:ss '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC
return fmt::format("{}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}", mt.year, mt.month, mt.day, mt.hour, mt.minute, mt.second);
default:
return std::string();
}
}
std::optional<std::string_view> StmtColumn::GetStrView() const
{
if (m_col.is_null)
{
return std::nullopt;
}
switch (m_col.buffer_type)
{
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
return std::make_optional<std::string_view>(reinterpret_cast<const char*>(m_col.buffer.data()), m_col.length);
default:
return std::nullopt;
}
}
std::optional<std::string> StmtColumn::GetStr() const
{
if (m_col.is_null)
{
return std::nullopt;
}
switch (m_col.buffer_type)
{
case MYSQL_TYPE_TINY:
return m_col.is_unsigned ? fmt::format_int(BitCast<uint8_t>()).c_str() : fmt::format_int(BitCast<int8_t>()).c_str();
case MYSQL_TYPE_SHORT:
return m_col.is_unsigned ? fmt::format_int(BitCast<uint16_t>()).c_str() : fmt::format_int(BitCast<int16_t>()).c_str();
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
return m_col.is_unsigned ? fmt::format_int(BitCast<uint32_t>()).c_str() : fmt::format_int(BitCast<int32_t>()).c_str();
case MYSQL_TYPE_LONGLONG:
return m_col.is_unsigned ? fmt::format_int(BitCast<uint64_t>()).c_str() : fmt::format_int(BitCast<int64_t>()).c_str();
case MYSQL_TYPE_FLOAT:
return fmt::format("{}", BitCast<float>());
case MYSQL_TYPE_DOUBLE:
return fmt::format("{}", BitCast<double>());
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
return FormatTime(m_col.buffer_type, BitCast<MYSQL_TIME>());
case MYSQL_TYPE_BIT:
return fmt::format_int(*Get<uint64_t>()).c_str();
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
return std::make_optional<std::string>(reinterpret_cast<const char*>(m_col.buffer.data()), m_col.length);
default:
return std::nullopt;
}
}
template <typename T> requires std::is_arithmetic_v<T>
std::optional<T> StmtColumn::Get() const
{
if (m_col.is_null)
{
return std::nullopt;
}
switch (m_col.buffer_type)
{
case MYSQL_TYPE_TINY:
return m_col.is_unsigned ? static_cast<T>(BitCast<uint8_t>()) : static_cast<T>(BitCast<int8_t>());
case MYSQL_TYPE_SHORT:
return m_col.is_unsigned ? static_cast<T>(BitCast<uint16_t>()) : static_cast<T>(BitCast<int16_t>());
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
return m_col.is_unsigned ? static_cast<T>(BitCast<uint32_t>()) : static_cast<T>(BitCast<int32_t>());
case MYSQL_TYPE_LONGLONG:
return m_col.is_unsigned ? static_cast<T>(BitCast<uint64_t>()) : static_cast<T>(BitCast<int64_t>());
case MYSQL_TYPE_FLOAT:
return static_cast<T>(BitCast<float>());
case MYSQL_TYPE_DOUBLE:
return static_cast<T>(BitCast<double>());
case MYSQL_TYPE_TIME: // return as total seconds
return static_cast<T>(MakeSeconds(BitCast<MYSQL_TIME>()));
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP: // return as epoch timestamp
return static_cast<T>(MakeTime(BitCast<MYSQL_TIME>()));
case MYSQL_TYPE_BIT:
return static_cast<T>(MakeBits({ m_col.buffer.data(), m_col.length }));
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
return FromString<T>({ reinterpret_cast<const char*>(m_col.buffer.data()), m_col.length });
default:
return std::nullopt;
}
}
// ---------------------------------------------------------------------------
// explicit template instantiations for supported types
template void PreparedStmt::BindInput(size_t, std::string_view);
template void PreparedStmt::BindInput(size_t, std::nullptr_t);
template StmtResult PreparedStmt::Execute(const std::vector<std::string_view>&);
template StmtResult PreparedStmt::Execute(const std::vector<std::string>&);
template StmtResult PreparedStmt::Execute(const std::vector<const char*>&);
#define INSTANTIATE(T) \
template void PreparedStmt::BindInput(size_t, T); \
template StmtResult PreparedStmt::Execute(const std::vector<T>&); \
template std::optional<T> StmtRow::Get(size_t) const; \
template std::optional<T> StmtRow::Get(std::string_view) const; \
template std::optional<T> StmtColumn::Get() const;
INSTANTIATE(bool);
INSTANTIATE(int8_t);
INSTANTIATE(uint8_t);
INSTANTIATE(int16_t);
INSTANTIATE(uint16_t);
INSTANTIATE(int32_t);
INSTANTIATE(uint32_t);
INSTANTIATE(int64_t);
INSTANTIATE(uint64_t);
INSTANTIATE(float);
INSTANTIATE(double);
} // namespace mysql
-221
View File
@@ -1,221 +0,0 @@
#pragma once
#include "mysql.h"
#include <cassert>
#include <cstring>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
class Mutex;
namespace mysql
{
// support MySQL 8.0.1+ API which removed the my_bool type
#if !defined(MARIADB_VERSION_ID) && MYSQL_VERSION_ID >= 80001
using my_bool = bool;
#endif
template <typename>
inline constexpr bool false_v = false;
namespace impl
{
struct Bind
{
std::vector<uint8_t> buffer;
unsigned long length = 0;
my_bool is_null = false;
my_bool error = false;
};
struct BindColumn : Bind
{
int index = 0;
std::string name;
bool is_unsigned = false;
enum_field_types buffer_type = {};
};
} // namespace impl
// ---------------------------------------------------------------------------
struct StmtOptions
{
// Enable buffering (storing) entire result set after executing a statement
bool buffer_results = true;
// Enable MySQL to update max_length of fields in execute result set (requires buffering)
bool use_max_length = true;
};
// ---------------------------------------------------------------------------
// Holds ownership of bound column value buffer
class StmtColumn
{
public:
int Index() const { return m_col.index; }
bool IsNull() const { return m_col.is_null; }
bool IsUnsigned() const { return m_col.is_unsigned; }
enum_field_types Type() const { return m_col.buffer_type; }
const std::string& Name() const { return m_col.name; }
// Get view of column value buffer
std::span<const uint8_t> GetBuf() const { return { m_col.buffer.data(), m_col.length }; }
// Get view of column string value. Returns nullopt if value is NULL or not a string
std::optional<std::string_view> GetStrView() const;
// Get column value as string. Returns nullopt if value is NULL or field type unsupported
std::optional<std::string> GetStr() const;
// Get column value as numeric T. Returns nullopt if value NULL or field type unsupported
template <typename T> requires std::is_arithmetic_v<T>
std::optional<T> Get() const;
private:
// uses memcpy for type punning buffer data to avoid UB with strict aliasing
template <typename T>
T BitCast() const
{
T val;
assert(sizeof(T) == m_col.length);
memcpy(&val, m_col.buffer.data(), sizeof(T));
return val;
}
friend class PreparedStmt; // access to allocate and bind buffers
friend class StmtResult; // access to resize truncated buffers
impl::BindColumn m_col;
};
// ---------------------------------------------------------------------------
// Provides a non-owning view of PreparedStmt column value buffers
// Evaluates false if it does not contain a valid row
class StmtRow
{
public:
StmtRow() = default;
StmtRow(std::span<const StmtColumn> columns) : m_columns(columns) {};
explicit operator bool() const noexcept { return !m_columns.empty(); }
int ColumnCount() const { return static_cast<int>(m_columns.size()); }
const StmtColumn* GetColumn(size_t index) const;
const StmtColumn* GetColumn(std::string_view name) const;
// Get specified column value as string
// Returns nullopt if column invalid, value is NULL, or field type unsupported
std::optional<std::string> operator[](size_t index) const;
std::optional<std::string> operator[](std::string_view name) const;
std::optional<std::string> GetStr(size_t index) const;
std::optional<std::string> GetStr(std::string_view name) const;
// Get specified column value as numeric T
// Returns nullopt if column invalid, value is NULL, or field type unsupported
template <typename T> requires std::is_arithmetic_v<T>
std::optional<T> Get(size_t index) const;
template <typename T> requires std::is_arithmetic_v<T>
std::optional<T> Get(std::string_view name) const;
auto begin() const { return m_columns.begin(); }
auto end() const { return m_columns.end(); }
private:
std::span<const StmtColumn> m_columns;
};
// ---------------------------------------------------------------------------
// Result meta data for an executed prepared statement
class StmtResult
{
public:
StmtResult() = default;
StmtResult(MYSQL_STMT* stmt, size_t columns);
int ColumnCount() const { return m_num_cols; }
uint64_t RowCount() const { return m_num_rows; }
uint64_t RowsAffected() const { return m_affected; }
uint64_t LastInsertID() const { return m_insert_id; }
private:
int m_num_cols = 0;
uint64_t m_num_rows = 0;
uint64_t m_affected = 0;
uint64_t m_insert_id = 0;
};
// ---------------------------------------------------------------------------
class PreparedStmt
{
public:
// Supported argument types for execute
using param_t = std::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
int64_t, uint64_t, float, double, bool, std::string_view, std::nullptr_t>;
PreparedStmt() = delete;
PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts = {});
const std::string& GetQuery() const { return m_query; }
StmtOptions GetOptions() const { return m_options; }
void SetOptions(StmtOptions options) { m_options = options; }
void FreeResult() { mysql_stmt_free_result(m_stmt.get()); }
// Execute the prepared statement with specified arguments
// Throws exception on error
template <typename T>
StmtResult Execute(const std::vector<T>& args);
StmtResult Execute(const std::vector<param_t>& args);
StmtResult Execute();
// Fetch the next row into column buffers (overwrites previous row values)
// Return value evaluates false if no more rows to fetch
// Throws exception on error
StmtRow Fetch();
private:
void CheckArgs(size_t argc);
StmtResult DoExecute();
void BindResults();
void FetchTruncated();
int GetResultBufferSize(const MYSQL_FIELD& field) const;
void ThrowError(const std::string& error);
std::string GetStmtError();
// bind an input value to a query parameter by index
template <typename T>
void BindInput(size_t index, T value);
void BindInput(size_t index, const char* str);
void BindInput(size_t index, const std::string& str);
struct StmtDeleter
{
Mutex* mutex = nullptr;
void operator()(MYSQL_STMT* stmt) noexcept;
};
private:
std::unique_ptr<MYSQL_STMT, StmtDeleter> m_stmt;
std::vector<MYSQL_BIND> m_params; // input binds
std::vector<MYSQL_BIND> m_results; // result binds
std::vector<impl::Bind> m_inputs; // execute buffers (addresses bound)
std::vector<StmtColumn> m_columns; // fetch buffers (addresses bound)
std::string m_query;
StmtOptions m_options = {};
bool m_need_bind = true;
Mutex* m_mutex = nullptr; // connection mutex
};
} // namespace mysql
+51 -91
View File
@@ -1091,109 +1091,70 @@ void EQ::Net::DaybreakConnection::ProcessResend()
}
}
// observed client receive window is 300 packets, 140KB
constexpr size_t MAX_CLIENT_RECV_PACKETS_PER_WINDOW = 300;
constexpr size_t MAX_CLIENT_RECV_BYTES_PER_WINDOW = 140 * 1024;
void EQ::Net::DaybreakConnection::ProcessResend(int stream)
{
if (m_status == DbProtocolStatus::StatusDisconnected) {
return;
}
if (m_streams[stream].sent_packets.empty()) {
return;
}
m_resend_packets_sent = 0;
m_resend_bytes_sent = 0;
auto now = Clock::now(); // Current time
auto resends = 0;
auto now = Clock::now();
auto s = &m_streams[stream];
for (auto &entry : s->sent_packets) {
auto time_since_last_send = std::chrono::duration_cast<std::chrono::milliseconds>(now - entry.second.last_sent);
if (entry.second.times_resent == 0) {
if ((size_t)time_since_last_send.count() > entry.second.resend_delay) {
auto &p = entry.second.packet;
if (p.Length() >= DaybreakHeader::size()) {
if (p.GetInt8(0) == 0 && p.GetInt8(1) >= OP_Fragment && p.GetInt8(1) <= OP_Fragment4) {
m_stats.resent_fragments++;
}
else {
m_stats.resent_full++;
}
}
else {
m_stats.resent_full++;
}
m_stats.resent_packets++;
// Get a reference resend delay (assume first packet represents the typical case)
if (!s->sent_packets.empty()) {
// Check if the first packet has timed out
auto &first_packet = s->sent_packets.begin()->second;
auto time_since_first_sent = std::chrono::duration_cast<std::chrono::milliseconds>(now - first_packet.first_sent).count();
// make sure that the first_packet in the list first_sent time is within the resend_delay and now
// if it is not, then we need to resend all packets in the list
if (time_since_first_sent <= first_packet.resend_delay && !m_acked_since_last_resend) {
LogNetcodeDetail(
"Not resending packets for stream [{}] time since first sent [{}] resend delay [{}] m_acked_since_last_resend [{}]",
stream,
time_since_first_sent,
first_packet.resend_delay,
m_acked_since_last_resend
);
return;
}
if (time_since_first_sent >= m_owner->m_options.resend_timeout) {
Close();
return;
}
}
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Netcode)) {
size_t total_size = 0;
for (auto &e: s->sent_packets) {
total_size += e.second.packet.Length();
}
LogNetcodeDetail(
"Resending packets for stream [{}] packet count [{}] total packet size [{}] m_acked_since_last_resend [{}]",
stream,
s->sent_packets.size(),
total_size,
m_acked_since_last_resend
);
}
for (auto &e: s->sent_packets) {
if (m_resend_packets_sent >= MAX_CLIENT_RECV_PACKETS_PER_WINDOW ||
m_resend_bytes_sent >= MAX_CLIENT_RECV_BYTES_PER_WINDOW) {
LogNetcodeDetail(
"Stopping resend because we hit thresholds m_resend_packets_sent [{}] max [{}] m_resend_bytes_sent [{}] max [{}]",
m_resend_packets_sent,
MAX_CLIENT_RECV_PACKETS_PER_WINDOW,
m_resend_bytes_sent,
MAX_CLIENT_RECV_BYTES_PER_WINDOW
);
break;
}
auto &sp = e.second;
auto &p = sp.packet;
if (p.Length() >= DaybreakHeader::size()) {
if (p.GetInt8(0) == 0 && p.GetInt8(1) >= OP_Fragment && p.GetInt8(1) <= OP_Fragment4) {
m_stats.resent_fragments++;
}
else {
m_stats.resent_full++;
InternalBufferedSend(p);
entry.second.last_sent = now;
entry.second.times_resent++;
entry.second.resend_delay = EQ::Clamp(entry.second.resend_delay * 2, m_owner->m_options.resend_delay_min, m_owner->m_options.resend_delay_max);
resends++;
}
}
else {
m_stats.resent_full++;
auto time_since_first_sent = std::chrono::duration_cast<std::chrono::milliseconds>(now - entry.second.first_sent);
if (time_since_first_sent.count() >= m_owner->m_options.resend_timeout) {
Close();
return;
}
if ((size_t)time_since_last_send.count() > entry.second.resend_delay) {
auto &p = entry.second.packet;
if (p.Length() >= DaybreakHeader::size()) {
if (p.GetInt8(0) == 0 && p.GetInt8(1) >= OP_Fragment && p.GetInt8(1) <= OP_Fragment4) {
m_stats.resent_fragments++;
}
else {
m_stats.resent_full++;
}
}
else {
m_stats.resent_full++;
}
m_stats.resent_packets++;
InternalBufferedSend(p);
entry.second.last_sent = now;
entry.second.times_resent++;
entry.second.resend_delay = EQ::Clamp(entry.second.resend_delay * 2, m_owner->m_options.resend_delay_min, m_owner->m_options.resend_delay_max);
resends++;
}
}
m_stats.resent_packets++;
// Resend the packet
InternalBufferedSend(p);
m_resend_packets_sent++;
m_resend_bytes_sent += p.Length();
sp.last_sent = now;
sp.times_resent++;
sp.resend_delay = EQ::Clamp(
sp.resend_delay * 2,
m_owner->m_options.resend_delay_min,
m_owner->m_options.resend_delay_max
);
}
m_acked_since_last_resend = false;
}
void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
@@ -1214,7 +1175,6 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3;
iter = s->sent_packets.erase(iter);
m_acked_since_last_resend = true;
}
else {
++iter;
-5
View File
@@ -181,11 +181,6 @@ namespace EQ
Timestamp m_close_time;
double m_outgoing_budget;
// resend tracking
size_t m_resend_packets_sent = 0;
size_t m_resend_bytes_sent = 0;
bool m_acked_since_last_resend = false;
struct DaybreakSentPacket
{
DynamicPacket packet;
@@ -23,9 +23,6 @@ namespace EQ
bool Connected() const { return m_connecting != true; }
std::shared_ptr<EQ::Net::TCPConnection> Handle() { return m_connection; }
const std::unique_ptr<EQ::Timer> &GetTimer() const { return m_timer; }
private:
void Connect();
void ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length);
+5 -5
View File
@@ -25,7 +25,7 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
return;
if (opcode == ServerOP_UsertoWorldReq) {
auto req_in = (UsertoWorldRequest*)p.Data();
auto req_in = (UsertoWorldRequest_Struct*)p.Data();
EQ::Net::DynamicPacket req;
size_t i = 0;
@@ -45,7 +45,7 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
}
if (opcode == ServerOP_LSClientAuth) {
auto req_in = (ClientAuth*)p.Data();
auto req_in = (ClientAuth_Struct*)p.Data();
EQ::Net::DynamicPacket req;
size_t i = 0;
@@ -54,7 +54,7 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
req.PutData(i, req_in->key, 30); i += 30;
req.PutUInt8(i, req_in->lsadmin); i += 1;
req.PutUInt16(i, req_in->is_world_admin); i += 2;
req.PutUInt32(i, req_in->ip_address); i += 4;
req.PutUInt32(i, req_in->ip); i += 4;
req.PutUInt8(i, req_in->is_client_from_local_network); i += 1;
EQ::Net::DynamicPacket out;
@@ -123,7 +123,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
{
size_t current = 0;
size_t total = m_buffer.size();
constexpr size_t ls_info_size = sizeof(LoginserverNewWorldRequest);
constexpr size_t ls_info_size = sizeof(ServerNewLSInfo_Struct);
while (current < total) {
auto left = total - current;
@@ -138,7 +138,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
//this creates a small edge case where the exact size of a
//packet from the modern protocol can't be "43061256"
//so in send we pad it one byte if that's the case
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(LoginserverNewWorldRequest)) {
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) {
m_legacy_mode = true;
m_identifier = "World";
m_parent->ConnectionIdentified(this);
-2
View File
@@ -80,8 +80,6 @@ void EQ::Net::TCPConnection::Start() {
}
}
else if (nread == UV_EOF) {
connection->Disconnect();
if (buf->base) {
delete[] buf->base;
}
-2
View File
@@ -197,7 +197,6 @@ IN(OP_RecipeDetails, uint32);
//there is also a complicated OP_RecipeDetails reply struct OUT
IN(OP_RecipeAutoCombine, RecipeAutoCombine_Struct);
IN(OP_TradeSkillCombine, NewCombine_Struct);
IN(OP_TradeSkillRecipeInspect, TradeSkillRecipeInspect_Struct);
IN(OP_ItemName, ItemNamePacket_Struct);
IN(OP_AugmentItem, AugmentItem_Struct);
IN(OP_ClickDoor, ClickDoor_Struct);
@@ -251,7 +250,6 @@ IN(OP_TraderBuy, TraderBuy_Struct);
IN(OP_Trader, Trader_ShowItems_Struct);
IN(OP_GMFind, GMSummon_Struct);
IN(OP_PickPocket, PickPocket_Struct);
IN(OP_PickZone, PickZone_Struct);
IN(OP_Bind_Wound, BindWound_Struct);
INr(OP_TrackTarget);
INr(OP_Track);
+71 -48
View File
@@ -1213,22 +1213,22 @@ namespace RoF
case 1: { // GuildBankItemUpdate
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
eq->action = 0;
OUT(unknown004);
eq->unknown008 = 0;
OUT(slot_id);
OUT(area);
OUT(display);
OUT(item_id);
OUT(icon_id);
OUT(quantity);
OUT(permissions);
OUT(allow_merge);
OUT(is_useable);
OUT_str(item_name);
OUT_str(donator);
OUT_str(who_for);
OUT(unknown226);
eq->Action = 0;
OUT(Unknown004);
eq->Unknown08 = 0;
OUT(SlotID);
OUT(Area);
OUT(Unknown012);
OUT(ItemID);
OUT(Icon);
OUT(Quantity);
OUT(Permissions);
OUT(AllowMerge);
OUT(Useable);
OUT_str(ItemName);
OUT_str(Donator);
OUT_str(WhoFor);
OUT(Unknown226);
break;
}
default:
@@ -3089,6 +3089,21 @@ namespace RoF
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(Merchant_Click_Struct);
SETUP_DIRECT_ENCODE(Merchant_Click_Struct, structs::Merchant_Click_Struct);
OUT(npcid);
OUT(playerid);
OUT(command);
OUT(rate);
eq->unknown01 = 3; // Not sure what these values do yet, but list won't display without them
eq->unknown02 = 2592000;
FINISH_ENCODE();
}
ENCODE(OP_SkillUpdate)
{
ENCODE_LENGTH_EXACT(SkillUpdate_Struct);
@@ -3494,13 +3509,14 @@ namespace RoF
ENCODE_LENGTH_EXACT(ClickTrader_Struct);
SETUP_DIRECT_ENCODE(ClickTrader_Struct, structs::ClickTrader_Struct);
eq->Code = emu->action;
for (uint32 i = 0; i < RoF::invtype::BAZAAR_SIZE; i++)
eq->Code = emu->Code;
// Live actually has 200 items now, but 80 is the most our internal struct supports
for (uint32 i = 0; i < 200; i++)
{
strncpy(eq->items[i].SerialNumber, "0000000000000000", sizeof(eq->items[i].SerialNumber));
eq->items[i].Unknown18 = 0;
if (i < 80) {
eq->ItemCost[i] = emu->item_cost[i];
eq->ItemCost[i] = emu->ItemCost[i];
}
else {
eq->ItemCost[i] = 0;
@@ -3514,9 +3530,9 @@ namespace RoF
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
eq->Code = emu->action;
eq->Code = emu->Code;
strncpy(eq->SerialNumber, "0000000000000000", sizeof(eq->SerialNumber));
eq->TraderID = emu->entity_id;
eq->TraderID = emu->TraderID;
eq->Stacksize = 0;
eq->Price = 0;
@@ -3542,13 +3558,13 @@ namespace RoF
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
OUT(action);
OUT(price);
OUT(trader_id);
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
OUT(item_id);
OUT(quantity);
OUT(already_sold);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
FINISH_ENCODE();
}
@@ -5031,6 +5047,19 @@ namespace RoF
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::Merchant_Click_Struct);
SETUP_DIRECT_DECODE(Merchant_Click_Struct, structs::Merchant_Click_Struct);
IN(npcid);
IN(playerid);
IN(command);
IN(rate);
FINISH_DIRECT_DECODE();
}
DECODE(OP_Trader)
{
uint32 psize = __packet->size;
@@ -5040,11 +5069,12 @@ namespace RoF
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::ClickTrader_Struct);
MEMSET_IN(ClickTrader_Struct);
emu->action = eq->Code;
for (uint32 i = 0; i < RoF::invtype::BAZAAR_SIZE; i++)
emu->Code = eq->Code;
// Live actually has 200 items now, but 80 is the most our internal struct supports
for (uint32 i = 0; i < 80; i++)
{
emu->serial_number[i] = 0; // eq->SerialNumber[i];
emu->item_cost[i] = eq->ItemCost[i];
emu->SerialNumber[i] = 0; // eq->SerialNumber[i];
emu->ItemCost[i] = eq->ItemCost[i];
}
FINISH_DIRECT_DECODE();
@@ -5055,8 +5085,8 @@ namespace RoF
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
MEMSET_IN(Trader_ShowItems_Struct);
emu->action = eq->Code;
emu->entity_id = eq->TraderID;
emu->Code = eq->Code;
emu->TraderID = eq->TraderID;
FINISH_DIRECT_DECODE();
}
@@ -5078,12 +5108,12 @@ namespace RoF
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
FINISH_DIRECT_DECODE();
}
@@ -5188,14 +5218,7 @@ namespace RoF
//sprintf(hdr.unknown000, "06e0002Y1W00");
strn0cpy(
hdr.unknown000,
fmt::format(
"{:016}\0",
packet_type == ItemPacketInvalid ? 0 : inst->GetSerialNumber()
).c_str(),
sizeof(hdr.unknown000)
);
snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID);
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 1000) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
hdr.unknown004 = 0;
+395 -1326
View File
File diff suppressed because it is too large Load Diff
+49 -85
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@ namespace RoF2
const bool AllowOverLevelEquipment = true;
const bool AllowEmptyBagInBag = true;
const bool AllowEmptyBagInBag = true;
const bool AllowClickCastFromBag = true;
} /*inventory*/
@@ -77,40 +77,38 @@ namespace RoF2
} // namespace enum_
using namespace enum_;
const int16 POSSESSIONS_SIZE = 34;
const int16 BANK_SIZE = 24;
const int16 SHARED_BANK_SIZE = 2;
const int16 TRADE_SIZE = 8;
const int16 WORLD_SIZE = 10;
const int16 LIMBO_SIZE = 36;
const int16 TRIBUTE_SIZE = 5;
const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 GUILD_TRIBUTE_SIZE = 2;//unverified
const int16 MERCHANT_SIZE = 500;
const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab"
const int16 CORPSE_SIZE = POSSESSIONS_SIZE;
const int16 BAZAAR_SIZE = 200;
const int16 INSPECT_SIZE = 23;
const int16 REAL_ESTATE_SIZE = 0;//unknown
const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE;
const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE;
const int16 POSSESSIONS_SIZE = 34;
const int16 BANK_SIZE = 24;
const int16 SHARED_BANK_SIZE = 2;
const int16 TRADE_SIZE = 8;
const int16 WORLD_SIZE = 10;
const int16 LIMBO_SIZE = 36;
const int16 TRIBUTE_SIZE = 5;
const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 GUILD_TRIBUTE_SIZE = 2;//unverified
const int16 MERCHANT_SIZE = 200;
const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab"
const int16 CORPSE_SIZE = POSSESSIONS_SIZE;
const int16 BAZAAR_SIZE = 200;
const int16 INSPECT_SIZE = 23;
const int16 REAL_ESTATE_SIZE = 0;//unknown
const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE;
const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE;
const int16 VIEW_MOD_SHARED_BANK_SIZE = SHARED_BANK_SIZE;
const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE;
const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank"
const int16 ARCHIVED_SIZE = 0;//unknown
const int16 MAIL_SIZE = 0;//unknown
const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE;
const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank"
const int16 ARCHIVED_SIZE = 0;//unknown
const int16 MAIL_SIZE = 0;//unknown
const int16 GUILD_TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 KRONO_SIZE = 0;//unknown
const int16 GUILD_BANK_MAIN_SIZE = 200;
const int16 GUILD_BANK_DEPOSIT_SIZE = 40;
const int16 OTHER_SIZE = 0;//unknown
const int16 KRONO_SIZE = 0;//unknown
const int16 OTHER_SIZE = 0;//unknown
const int16 TRADE_NPC_SIZE = 4; // defined by implication
const int16 TYPE_INVALID = IINVALID;
const int16 TYPE_BEGIN = typePossessions;
const int16 TYPE_END = typeOther;
const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1;
const int16 TYPE_BEGIN = typePossessions;
const int16 TYPE_END = typeOther;
const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1;
int16 GetInvTypeSize(int16 inv_type);
const char* GetInvTypeName(int16 inv_type);
@@ -164,54 +162,33 @@ namespace RoF2
} // namespace enum_
using namespace enum_;
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 BANK_BEGIN = 2000;
const int16 BANK_END = (BANK_BEGIN + invtype::BANK_SIZE) - 1;
const int16 SHARED_BANK_BEGIN = 2500;
const int16 SHARED_BANK_END = (SHARED_BANK_BEGIN + invtype::SHARED_BANK_SIZE) - 1;
const int16 TRADE_BEGIN = 3000;
const int16 TRADE_END = (TRADE_BEGIN + invtype::TRADE_SIZE) - 1;
const int16 TRADE_NPC_END = (TRADE_BEGIN + invtype::TRADE_NPC_SIZE) - 1; // defined by implication
const int16 WORLD_BEGIN = 4000;
const int16 WORLD_END = (WORLD_BEGIN + invtype::WORLD_SIZE) - 1;
const int16 TRIBUTE_BEGIN = 400;
const int16 TRIBUTE_END = (TRIBUTE_BEGIN + invtype::TRIBUTE_SIZE) - 1;
const int16 GUILD_TRIBUTE_BEGIN = 450;
const int16 GUILD_TRIBUTE_END = (GUILD_TRIBUTE_BEGIN + invtype::GUILD_TRIBUTE_SIZE) - 1;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 POSSESSIONS_BEGIN = slotCharm;
const int16 POSSESSIONS_END = slotCursor;
const int16 POSSESSIONS_END = slotCursor;
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
const int16 EQUIPMENT_BEGIN = slotCharm;
const int16 EQUIPMENT_END = slotAmmo;
const int16 EQUIPMENT_END = slotAmmo;
const int16 EQUIPMENT_COUNT = (EQUIPMENT_END - EQUIPMENT_BEGIN) + 1;
const int16 GENERAL_BEGIN = slotGeneral1;
const int16 GENERAL_END = slotGeneral10;
const int16 GENERAL_END = slotGeneral10;
const int16 GENERAL_COUNT = (GENERAL_END - GENERAL_BEGIN) + 1;
const int16 BONUS_BEGIN = invslot::slotCharm;
const int16 BONUS_STAT_END = invslot::slotPowerSource;
const int16 BONUS_BEGIN = invslot::slotCharm;
const int16 BONUS_STAT_END = invslot::slotPowerSource;
const int16 BONUS_SKILL_END = invslot::slotAmmo;
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
const uint64 GENERAL_BITMASK = 0x00000001FF800000;
const uint64 CURSOR_BITMASK = 0x0000000200000000;
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
const uint64 GENERAL_BITMASK = 0x00000001FF800000;
const uint64 CURSOR_BITMASK = 0x0000000200000000;
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+)
const char* GetInvPossessionsSlotName(int16 inv_slot);
@@ -222,21 +199,10 @@ namespace RoF2
namespace invbag {
inline EQ::versions::ClientVersion GetInvBagRef() { return EQ::versions::ClientVersion::RoF2; }
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 SLOT_COUNT = 200;
const int16 SLOT_END = SLOT_COUNT - 1;
const int16 GENERAL_BAGS_BEGIN = 251;
const int16 CURSOR_BAG_BEGIN = 351;
const int16 BANK_BAGS_BEGIN = 2031;
const int16 SHARED_BANK_BAGS_BEGIN = 2531;
const int16 TRADE_BAGS_BEGIN = 3031;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 SLOT_END = 9; //254;
const int16 SLOT_COUNT = 10; //255; // server Size will be 255..unsure what actual client is (test)
const char* GetInvBagIndexName(int16 bag_index);
@@ -246,9 +212,9 @@ namespace RoF2
inline EQ::versions::ClientVersion GetInvAugRef() { return EQ::versions::ClientVersion::RoF2; }
const int16 SOCKET_INVALID = IINVALID;
const int16 SOCKET_BEGIN = INULL;
const int16 SOCKET_END = 5;
const int16 SOCKET_COUNT = 6;
const int16 SOCKET_BEGIN = INULL;
const int16 SOCKET_END = 5;
const int16 SOCKET_COUNT = 6;
const char* GetInvAugIndexName(int16 aug_index);
@@ -305,8 +271,6 @@ namespace RoF2
const size_t CHARACTER_CREATION_LIMIT = 12;
const size_t SAY_LINK_BODY_SIZE = 56;
const uint32 MAX_GUILD_ID = 50000;
const uint32 MAX_BAZAAR_TRADERS = 600;
} /*constants*/
@@ -326,7 +290,7 @@ namespace RoF2
namespace spells {
inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::RoF2; }
enum class CastingSlot : uint32 {
Gem1 = 0,
Gem2 = 1,
@@ -349,7 +313,7 @@ namespace RoF2
const int SPELL_ID_MAX = 45000;
const int SPELLBOOK_SIZE = 720;
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
const int LONG_BUFFS = 42;
const int SHORT_BUFFS = 20;
const int DISC_BUFFS = 1;
+3 -8
View File
@@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@@ -43,12 +43,10 @@ E(OP_ApplyPoison)
E(OP_AugmentInfo)
E(OP_Barter)
E(OP_BazaarSearch)
E(OP_BecomeTrader)
E(OP_BeginCast)
E(OP_BlockedBuffs)
E(OP_Buff)
E(OP_BuffCreate)
E(OP_BuyerItems)
E(OP_CancelTrade)
E(OP_CastSpell)
E(OP_ChannelMessage)
@@ -70,7 +68,6 @@ E(OP_DzMemberListName)
E(OP_DzMemberListStatus)
E(OP_DzSetLeaderName)
E(OP_Emote)
E(OP_EvolveItem)
E(OP_ExpansionInfo)
E(OP_FormattedMessage)
E(OP_GMLastName)
@@ -92,7 +89,6 @@ E(OP_InspectBuffs)
E(OP_InspectRequest)
E(OP_ItemLinkResponse)
E(OP_ItemPacket)
E(OP_ItemPreviewRequest)
E(OP_ItemVerifyReply)
E(OP_LeadershipExpUpdate)
E(OP_LogServer)
@@ -120,6 +116,7 @@ E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SkillUpdate)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnAppearance)
@@ -152,13 +149,11 @@ D(OP_Animation)
D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_Barter)
D(OP_BazaarSearch)
D(OP_BlockedBuffs)
D(OP_BookButton)
D(OP_Buff)
D(OP_BuffRemoveRequest)
D(OP_BuyerItems)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)
@@ -205,7 +200,7 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopSendParcel)
D(OP_ShopRequest)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
+188 -379
View File
@@ -354,15 +354,15 @@ struct Spawn_Struct_Bitfields
/*29*/ unsigned showname:1;
/*30*/ unsigned idleanimationsoff:1; // what we called statue?
/*31*/ unsigned untargetable:1; // bClickThrough
// byte 5
/*32 unsigned buyer:1;
/*33 unsigned offline:1;
/*34 unsigned interactiveobject:1;
/*35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
/*36 unsigned title:1;
/*37 unsigned suffix:1;
/*38 unsigned padding1:1;
/*39 unsigned padding2:1;
/* do these later
32 unsigned buyer:1;
33 unsigned offline:1;
34 unsigned interactiveobject:1;
35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
36 unsigned title:1;
37 unsigned suffix:1;
38 unsigned padding1:1;
39 unsigned padding2:1;
40 unsinged padding3:1;
*/
/*
@@ -1965,39 +1965,41 @@ struct GuildBankWithdrawItem_Struct
struct GuildBankItemUpdate_Struct
{
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown016, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
action = inAction;
slot_id = inSlotID;
area = inArea;
display = inUnknown016;
item_id = inItemID;
icon_id = inIcon;
quantity = inQuantity;
permissions = inPermissions;
allow_merge = inAllowMerge;
is_useable = inUseable;
item_name[0] = '\0';
donator[0] = '\0';
who_for[0] = '\0';
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 action;
/*004*/ uint32 not_used004; //disassemble of client did not use this
/*008*/ uint32 not_used008; //disassemble of client did not use this
/*012*/ uint16 slot_id;
/*014*/ uint16 area;
/*016*/ uint32 display;
/*020*/ uint32 item_id;
/*024*/ uint32 icon_id;
/*028*/ uint32 quantity;
/*032*/ uint32 permissions;
/*036*/ uint8 allow_merge;
/*037*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char item_name[64];
/*102*/ char donator[64];
/*166*/ char who_for[64];
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
@@ -2245,17 +2247,15 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client
/*024*/
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 unknown01; // Seen 3 from Server or -1 from Client
/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client
/*024*/
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -3104,164 +3104,28 @@ struct EnvDamage2_Struct {
};
//Bazaar Stuff
enum RoF2BazaarTraderBuyerActions {
Zero = 0,
BeginTraderMode = 1,
EndTraderMode = 2,
PriceUpdate = 3,
EndTransaction = 4,
BazaarSearch = 7,
WelcomeMessage = 9,
BuyTraderItem = 10,
ListTraderItems = 11,
BazaarInspect = 18,
ClickTrader = 28,
ItemMove = 19,
ReconcileItems = 20,
FirstOpenSearch = 26
};
enum RoF2BuyerActions {
BuyerSearchResults = 0x00,
BuyerBuyLine = 0x06,
BuyerModifyBuyLine = 0x07,
BuyerRemoveItem = 0x08,
BuyerSellItem = 0x09,
BuyerBuyItem = 0x0a,
BuyerInspectBegin = 0x0b,
BuyerInspectEnd = 0x0c,
BuyerAppearance = 0x0d,
BuyerSendBuyLine = 0x0e,
BuyerItemInspect = 0x0f,
BuyerBrowsingBuyLine = 0x10,
BarterWelcomeMessage = 0x11,
BuyerWelcomeMessage = 0x13,
BuyerGreeting = 0x14,
BuyerInventoryFull = 0x16
};
struct BarterItemSearchLinkRequest_Struct {
uint32 action;
uint32 unknown_004;
uint32 seller_id;
uint32 buyer_id;
uint32 unknown_016;
uint32 slot_id; // 0xffffffff main buy line 0x0 trade_item_1, 0x1 trade_item_2
uint32 item_id;
uint32 unknown_028;
};
struct BuyerWelcomeMessageUpdate_Struct {
uint32 action;
char unknown_004[64];
uint32 unknown_068;
char welcome_message[256];
};
struct Buyer_SetAppearance_Struct {
uint32 action;
uint32 entity_id;
char unknown[64];
uint32 enabled;
};
struct BuyerRemoveItem_Struct {
uint32 action;
uint32 unknown004;
uint32 slot_id;
uint32 toggle;
};
struct BuyerLineSellItem_Struct {
uint32 action;
uint32 purchase_method; // 0 direct merchant, 1 via /barter window
uint32 unknown008;
uint32 buyer_entity_id;
uint32 seller_entity_id;
char unknown[15];
uint32 slot;
uint8 enabled;
uint32 item_id;
char item_name[64];
uint32 item_icon;
uint32 item_quantity;
uint8 item_toggle;
uint32 item_cost;
uint32 no_trade_items;
BuyerLineTradeItems_Struct trade_items[10];
char unknown2[13];
uint32 seller_quantity;
};
struct BuyerLineItemsSearch_Struct {
uint32 slot;
uint8 enabled;
uint32 item_id;
char item_name[64];
uint32 item_icon;
uint32 item_quantity;
uint8 item_toggle;
uint32 item_cost;
uint32 buyer_id;
BuyerLineTradeItems_Struct trade_items[MAX_BUYER_COMPENSATION_ITEMS];
};
struct BuyerLineSearch_Struct {
uint32 action;
uint32 no_items;
std::vector<BuyerLineItemsSearch_Struct> buy_line;
};
struct BuyerStart_Struct {
uint32 action;
uint16 no_buyer_lines;
uint32 slot;
uint8 enabled;
uint32 item_id;
char item_name[1]; // vary length
uint32 item_icon;
uint32 item_quantity;
uint8 toggle;
uint32 item_cost;
uint32 no_trade_items;
BuyerLineTradeItems_Struct trade_items[1]; // size is actually no_trade_items. If 0, then this is not in packet
char unknown[13];
};
struct BuyerItemSearchResultEntry_Struct {
char item_name[64];
uint32 item_id;
uint32 item_icon;
uint32 unknown_072;
};
struct BuyerItemSearchResults_Struct {
uint32 action;
uint32 result_count;
BuyerItemSearchResultEntry_Struct results[];
};
enum {
BazaarTrader_StartTraderMode = 1,
BazaarTrader_EndTraderMode = 2,
BazaarTrader_UpdatePrice = 3,
BazaarTrader_EndTransaction = 4,
BazaarSearchResults = 7,
BazaarWelcome = 9,
BazaarBuyItem = 10,
BazaarTrader_ShowItems = 11,
BazaarSearchDone = 12,
BazaarTrader_StartTraderMode = 1,
BazaarTrader_EndTraderMode = 2,
BazaarTrader_UpdatePrice = 3,
BazaarTrader_EndTransaction = 4,
BazaarSearchResults = 7,
BazaarWelcome = 9,
BazaarBuyItem = 10,
BazaarTrader_ShowItems = 11,
BazaarSearchDone = 12,
BazaarTrader_CustomerBrowsing = 13,
BazaarInspectItem = 18,
BazaarSearchDone2 = 19,
BazaarInspectItem = 18,
BazaarSearchDone2 = 19,
BazaarTrader_StartTraderMode2 = 22
};
enum {
BazaarPriceChange_Fail = 0,
BazaarPriceChange_Fail = 0,
BazaarPriceChange_UpdatePrice = 1,
BazaarPriceChange_RemoveItem = 2,
BazaarPriceChange_AddItem = 3
BazaarPriceChange_RemoveItem = 2,
BazaarPriceChange_AddItem = 3
};
struct BazaarWindowStart_Struct {
@@ -3270,51 +3134,34 @@ struct BazaarWindowStart_Struct {
uint16 Unknown002;
};
struct BazaarDeliveryCost_Struct {
uint32 action;
uint32 voucher_delivery_cost;
float parcel_deliver_cost; //percentage of item cost
uint32 unknown_010;
};
struct BazaarWelcome_Struct {
uint32 action;
uint32 unknown_004;
uint32 num_of_traders;
uint32 num_of_items;
uint32 Code;
uint32 EntityID;
uint32 Traders;
uint32 Items;
uint32 Traders2;
uint32 Items2;
};
struct BazaarSearch_Struct {
/*000*/ uint32 action;
/*004*/ uint8 search_scope;//1 all traders 0 local traders
/*005*/ uint8 unknown_005{0};
/*006*/ uint16 unknown_006{0};
/*008*/ uint32 unknown_008{0};
/*012*/ uint32 unknown_012{0};
/*016*/ uint32 trader_id;
/*020*/ uint32 _class;
/*024*/ uint32 race;
/*028*/ uint32 item_stat;
/*032*/ uint32 slot;
/*036*/ uint32 type;
/*040*/ char item_name[64];
/*104*/ uint32 min_cost;
/*108*/ uint32 max_cost;
/*112*/ uint32 min_level;
/*116*/ uint32 max_level;
/*120*/ uint32 max_results;
/*124*/ uint32 prestige;
/*128*/ uint32 augment;
BazaarWindowStart_Struct Beginning;
uint32 TraderID;
uint32 Class_;
uint32 Race;
uint32 ItemStat;
uint32 Slot;
uint32 Type;
char Name[64];
uint32 MinPrice;
uint32 MaxPrice;
uint32 Minlevel;
uint32 MaxLlevel;
};
struct BazaarInspect_Struct {
uint32 action;
uint32 unknown_004;
uint32 trader_id;
char serial_number[17];
char unknown_029[3];
uint32 item_id;
uint32 unknown_036;
struct BazaarInspect_Struct{
uint32 ItemID;
uint32 Unknown004;
char Name[64];
};
struct NewBazaarInspect_Struct {
@@ -3335,23 +3182,18 @@ struct BazaarReturnDone_Struct{
uint32 Unknown016;
};
struct BazaarSearchDetails_Struct { //24+name+17
/*014*/ uint32 trader_id;
/*018*/ char serial_num[17];
/*022*/ uint32 cost;
/*026*/ uint32 quanity;
/*030*/ uint32 id;
/*034*/ uint32 icon;
/*038*/ char name[1];
/*039*/ uint32 stat;
};
struct BazaarSearchResults_Struct { //14
/*000*/ uint32 unknown000;
/*004*/ uint16 zone_id;
/*006*/ uint32 entity_id;
/*010*/ uint32 num_items;
/*014*/ BazaarSearchDetails_Struct items[];
struct BazaarSearchResults_Struct {
/*000*/ BazaarWindowStart_Struct Beginning;
/*004*/ uint32 SellerID;
/*008*/ char SellerName[64];
/*072*/ uint32 NumItems;
/*076*/ uint32 ItemID;
/*080*/ uint32 SerialNumber;
/*084*/ uint32 Unknown084;
/*088*/ char ItemName[64];
/*152*/ uint32 Cost;
/*156*/ uint32 ItemStat;
/*160*/
};
struct ServerSideFilters_Struct {
@@ -3554,26 +3396,21 @@ struct WhoAllPlayerPart4 {
};
struct TraderItemSerial_Struct {
char serial_number[17];
uint8 unknown_018;
void operator=(uint32 a) {
auto _tmp = fmt::format("{:016}", a);
strn0cpy(this->serial_number, _tmp.c_str(), sizeof(this->serial_number));
}
char SerialNumber[17];
uint8 Unknown18;
};
struct BeginTrader_Struct {
/*0000*/ uint32 action;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 item_cost[200];
struct Trader_Struct {
/*0000*/ uint32 Code;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 ItemCost[200];
/*4404*/
};
struct ClickTrader_Struct {
/*0000*/ uint32 action;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 item_cost[200];
/*0000*/ uint32 Code;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 ItemCost[200];
/*4404*/
};
@@ -3582,55 +3419,67 @@ struct GetItems_Struct {
};
struct BecomeTrader_Struct {
uint32 entity_id;
uint32 action;
};
struct BazaarWindowRemoveTrader_Struct {
uint32 action;
uint32 trader_id;
};
struct TraderPriceUpdate_Struct {
uint32 action;
char serial_number[17];
char unknown_021[3];
uint32 unknown_024;
uint32 new_price;
uint32 id;
uint32 code;
};
struct Trader_ShowItems_Struct {
/*000*/ uint32 action;
/*004*/ uint32 entity_id;
/*008*/ uint32 unknown_008;
/*012*/
/*000*/ uint32 Code;
/*004*/ uint16 TraderID;
/*008*/ uint32 Unknown08;
/*012*/
};
struct Trader_ShowItems_Struct_WIP {
/*000*/ uint32 Code;
/*004*/ char SerialNumber[17];
/*021*/ uint8 Unknown21;
/*022*/ uint16 TraderID;
/*026*/ uint32 Stacksize;
/*030*/ uint32 Price;
/*032*/
};
struct TraderStatus_Struct {
/*000*/ uint32 action;
/*004*/ uint32 sub_action;
/*008*/ uint32 uknown_008;
/*000*/ uint32 Code;
/*004*/ uint32 Uknown04;
/*008*/ uint32 Uknown08;
/*012*/
};
struct TraderBuy_Struct {
/*000*/ uint32 action;
/*004*/ uint32 method;
/*008*/ uint32 sub_action;
/*012*/ uint32 unknown_012;
/*016*/ uint32 trader_id;
/*020*/ char buyer_name[64];
/*084*/ char seller_name[64];
/*148*/ char unknown_148[32];
/*180*/ char item_name[64];
/*244*/ char serial_number[17];
/*261*/ char unknown_261[3];
/*264*/ uint32 item_id;
/*268*/ uint32 price;
/*272*/ uint32 already_sold;
/*276*/ uint32 unknown_276;
/*280*/ uint32 quantity;
/*284*/
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown008;
/*012*/ uint32 Unknown012;
/*016*/ uint32 TraderID;
/*020*/ char BuyerName[64];
/*084*/ char SellerName[64];
/*148*/ char Unknown148[32];
/*180*/ char ItemName[64];
/*244*/ char SerialNumber[16];
/*260*/ uint32 Unknown076;
/*264*/ uint32 ItemID;
/*268*/ uint32 Price;
/*272*/ uint32 AlreadySold;
/*276*/ uint32 Unknown276;
/*280*/ uint32 Quantity;
/*284*/
};
struct TraderBuy_Struct_OLD {
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Price;
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 TraderID;
/*020*/ char ItemName[64];
/*084*/ uint32 Unknown076;
/*088*/ uint32 ItemID;
/*092*/ uint32 AlreadySold;
/*096*/ uint32 Quantity;
/*100*/ uint32 Unknown092;
/*104*/
};
struct TraderItemUpdate_Struct{
@@ -3651,15 +3500,15 @@ struct MoneyUpdate_Struct{
struct TraderDelItem_Struct{
/*000*/ uint32 Unknown000;
/*004*/ uint32 TraderID;
/*008*/ char SerialNumber[17];
/*008*/ char SerialNumber[16];
/*024*/ uint32 Unknown012;
/*028*/
};
struct TraderClick_Struct{
/*000*/ uint32 action;
/*004*/ uint32 trader_id;
/*008*/ uint32 unknown_008;
/*000*/ uint32 Code;
/*004*/ uint32 TraderID;
/*008*/ uint32 Approval;
/*012*/
};
@@ -3933,11 +3782,6 @@ struct NewCombine_Struct
/*24*/
};
struct TradeSkillRecipeInspect_Struct {
uint32 recipe_id;
uint32 padding[17];
};
//client requesting favorite recipies
struct TradeskillFavorites_Struct {
@@ -4728,34 +4572,37 @@ struct RoF2SlotStruct
struct ItemSerializationHeader
{
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
/*017*/ uint32 stacksize;
/*021*/ uint32 unknown004;
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
/*026*/ uint16 main_slot;
/*028*/ uint16 sub_slot;
/*030*/ uint16 aug_slot; // 0xffff
/*032*/ uint32 price;
/*036*/ uint32 merchant_slot; // 1 if not a merchant item
/*040*/ uint32 scaled_value; // 0
/*044*/ uint32 instance_id; // unique instance id if not merchant item, else is merchant slot
/*048*/ uint32 parcel_item_id;
/*052*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0
/*056*/ uint32 charges; // Total Charges an item has (-1 for unlimited)
/*060*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items)
/*064*/ uint32 unknown044; // 0
/*068*/ uint32 unknown048; // 0
/*072*/ uint32 unknown052; // 0
uint8 isEvolving;
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
/*017*/ uint32 stacksize;
/*021*/ uint32 unknown004;
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
/*026*/ uint16 main_slot;
/*028*/ uint16 sub_slot;
/*030*/ uint16 aug_slot; // 0xffff
/*032*/ uint32 price;
/*036*/ uint32 merchant_slot; //1 if not a merchant item
/*040*/ uint32 scaled_value; //0
/*044*/ uint32 instance_id; //unique instance id if not merchant item, else is merchant slot
/*048*/ uint32 unknown028; //0
/*052*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0
/*056*/ uint32 charges; //Total Charges an item has (-1 for unlimited)
/*060*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items)
/*064*/ uint32 unknown044; // 0
/*068*/ uint32 unknown048; // 0
/*072*/ uint32 unknown052; // 0
uint8 isEvolving;
};
struct EvolvingItem_Struct {
uint32 final_item_id;
int32 evolve_level;
struct EvolvingItem {
uint8 unknown001;
uint8 unknown002;
uint8 unknown003;
uint8 unknown004;
int32 evoLevel;
double progress;
uint8 activated;
int32 evolve_max_level;
uint8 unknown005[4];
uint8 Activated;
int32 evomaxlevel;
uint8 unknown005[4];
};
struct ItemSerializationHeaderFinish
@@ -5414,46 +5261,8 @@ struct Checksum_Struct {
uint8_t data[2048];
};
struct Parcel_Struct
{
/*000*/ uint32 npc_id;
/*004*/ TypelessInventorySlot_Struct inventory_slot;
/*012*/ uint32 quantity;
/*016*/ uint32 money_flag;
/*020*/ char send_to[64];
/*084*/ char note[128];
/*212*/ uint32 unknown_212;
/*216*/ uint32 unknown_216;
/*220*/ uint32 unknown_220;
};
}; /*structs*/
struct EvolveItemToggle_Struct {
uint32 action;
uint32 unknown_004;
uint64 unique_id;
uint32 percentage;
uint32 activated;
};
struct EvolveXPWindowReceive_Struct {
uint32 action;
uint32 unknown_004;
uint64 item1_unique_id;
uint64 item2_unique_id;
};
struct EvolveXPWindowSendDetails_Struct {
/*000*/ uint32 action;
/*004*/ uint64 item1_unique_id;
/*012*/ uint64 item2_unique_id;
/*020*/ uint32 compatibility;
/*024*/ uint32 max_transfer_level;
/*028*/ uint8 item1_present;
/*029*/ uint8 item2_present;
/*030*/ char serialize_data[];
};
}; /*RoF2*/
#endif /*COMMON_ROF2_STRUCTS_H*/
+2
View File
@@ -101,6 +101,7 @@ E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SkillUpdate)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnAppearance)
@@ -182,6 +183,7 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
+49 -51
View File
@@ -1946,38 +1946,38 @@ struct GuildBankItemUpdate_Struct
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
action = inAction;
unknown004 = inUnknown004;
slot_id = inSlotID;
area = inArea;
display = inUnknown012;
item_id = inItemID;
icon_id = inIcon;
quantity = inQuantity;
permissions = inPermissions;
allow_merge = inAllowMerge;
is_useable = inUseable;
item_name[0] = '\0';
donator[0] = '\0';
who_for[0] = '\0';
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 action;
/*004*/ uint32 unknown004;
/*008*/ uint32 unknown008;
/*012*/ uint16 slot_id;
/*014*/ uint16 area;
/*016*/ uint32 display;
/*020*/ uint32 item_id;
/*024*/ uint32 icon_id;
/*028*/ uint32 quantity;
/*032*/ uint32 permissions;
/*036*/ uint8 allow_merge;
/*037*/ uint8 is_useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char item_name[64];
/*102*/ char donator[64];
/*166*/ char who_for[64];
/*230*/ uint16 unknown226;
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
@@ -2200,17 +2200,15 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown020; // Seen 2592000 from Server or -1 from Client
/*024*/
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 unknown01; // Seen 3 from Server or -1 from Client
/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client
/*024*/
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -3376,17 +3374,17 @@ struct TraderStatus_Struct {
};
struct TraderBuy_Struct {
/*000*/ uint32 action;
/*004*/ uint32 unknown_004;
/*008*/ uint32 price;
/*012*/ uint32 unknown_008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 trader_id;
/*020*/ char item_name[64];
/*084*/ uint32 unknown_076;
/*088*/ uint32 item_id;
/*092*/ uint32 already_sold;
/*096*/ uint32 quantity;
/*100*/ uint32 unknown_092;
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Price;
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 TraderID;
/*020*/ char ItemName[64];
/*084*/ uint32 Unknown076;
/*088*/ uint32 ItemID;
/*092*/ uint32 AlreadySold;
/*096*/ uint32 Quantity;
/*100*/ uint32 Unknown092;
/*104*/
};
+13 -41
View File
@@ -2026,19 +2026,6 @@ namespace SoD
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
FINISH_ENCODE();
}
ENCODE(OP_SomeItemPacketMaybe)
{
// This Opcode is not named very well. It is used for the animation of arrows leaving the player's bow
@@ -2286,13 +2273,13 @@ namespace SoD
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
OUT(action);
OUT(price);
OUT(trader_id);
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
OUT(item_id);
OUT(quantity);
OUT(already_sold);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
FINISH_ENCODE();
}
@@ -3496,33 +3483,18 @@ namespace SoD
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
emu->tab_display = 0;
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_TraderBuy)
{
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
FINISH_DIRECT_DECODE();
}
-2
View File
@@ -78,7 +78,6 @@ E(OP_SendCharInfo)
E(OP_SendZonepoints)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnDoor)
E(OP_SpecialMesg)
@@ -142,7 +141,6 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
+16 -21
View File
@@ -1845,16 +1845,12 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown020; // Seen 2592000 from Server or -1 from Client
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; //1=open, 0=cancel/close
/*012*/ float rate; //cost multiplier, dosent work anymore
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -2879,21 +2875,20 @@ struct Trader_ShowItems_Struct{
};
struct TraderBuy_Struct {
/*000*/ uint32 action;
/*004*/ uint32 unknown_004;
/*008*/ uint32 price;
/*012*/ uint32 unknown_008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 trader_id;
/*020*/ char item_name[64];
/*084*/ uint32 unknown_076;
/*088*/ uint32 item_id;
/*092*/ uint32 already_sold;
/*096*/ uint32 quantity;
/*100*/ uint32 unknown_092;
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Price;
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 TraderID;
/*020*/ char ItemName[64];
/*084*/ uint32 Unknown076;
/*088*/ uint32 ItemID;
/*092*/ uint32 AlreadySold;
/*096*/ uint32 Quantity;
/*100*/ uint32 Unknown092;
/*104*/
};
struct TraderItemUpdate_Struct{
uint32 unknown0;
uint32 traderid;
+16 -44
View File
@@ -270,8 +270,8 @@ namespace SoF
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
OUT(trader_id);
OUT(action);
OUT(ID);
OUT(Code);
FINISH_ENCODE();
}
@@ -1683,19 +1683,6 @@ namespace SoF
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
FINISH_ENCODE();
}
ENCODE(OP_SomeItemPacketMaybe)
{
// This Opcode is not named very well. It is used for the animation of arrows leaving the player's bow
@@ -1902,13 +1889,13 @@ namespace SoF
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
OUT(action);
OUT(price);
OUT(trader_id);
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
OUT(item_id);
OUT(quantity);
OUT(already_sold);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
FINISH_ENCODE();
}
@@ -2349,7 +2336,7 @@ namespace SoF
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = Bug::GetID(eq->category_name);
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
@@ -2887,33 +2874,18 @@ namespace SoF
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
emu->tab_display = 0;
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_TraderBuy)
{
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
FINISH_DIRECT_DECODE();
}
-2
View File
@@ -72,7 +72,6 @@ E(OP_SendAATable)
E(OP_SendCharInfo)
E(OP_SendZonepoints)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnDoor)
E(OP_SpecialMesg)
@@ -129,7 +128,6 @@ D(OP_ReadBook)
D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
+16 -20
View File
@@ -1859,16 +1859,12 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown020; // Seen 2592000 from Server or -1 from Client
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; //1=open, 0=cancel/close
/*012*/ float rate; //cost multiplier, dosent work anymore
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -2771,8 +2767,8 @@ struct GetItems_Struct{
};
struct BecomeTrader_Struct{
uint32 trader_id;
uint32 action;
uint32 ID;
uint32 Code;
};
struct Trader_ShowItems_Struct{
@@ -2782,15 +2778,15 @@ struct Trader_ShowItems_Struct{
};
struct TraderBuy_Struct {
/*000*/ uint32 action;
/*004*/ uint32 price;
/*008*/ uint32 trader_id;
/*012*/ char item_name[64];
/*076*/ uint32 unknown_076;
/*080*/ uint32 item_id;
/*084*/ uint32 already_sold;
/*088*/ uint32 quantity;
/*092*/ uint32 unknown_092;
/*000*/ uint32 Action;
/*004*/ uint32 Price;
/*008*/ uint32 TraderID;
/*012*/ char ItemName[64];
/*076*/ uint32 Unknown076;
/*080*/ uint32 ItemID;
/*084*/ uint32 AlreadySold;
/*088*/ uint32 Quantity;
/*092*/ uint32 Unknown092;
};
struct TraderItemUpdate_Struct{
+3 -3
View File
@@ -60,7 +60,7 @@
eq_struct *eq = (eq_struct *) __packet->pBuffer; \
#define ALLOC_LEN_ENCODE(len) \
__packet->pBuffer = new unsigned char[len] {}; \
__packet->pBuffer = new unsigned char[len]; \
__packet->size = len; \
memset(__packet->pBuffer, 0, len); \
@@ -124,7 +124,7 @@
#define SETUP_DIRECT_DECODE(emu_struct, eq_struct) \
unsigned char *__eq_buffer = __packet->pBuffer; \
__packet->size = sizeof(emu_struct); \
__packet->pBuffer = new unsigned char[__packet->size] {}; \
__packet->pBuffer = new unsigned char[__packet->size]; \
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
eq_struct *eq = (eq_struct *) __eq_buffer;
@@ -133,7 +133,7 @@
eq_struct* in = (eq_struct*)__packet->pBuffer; \
auto size = strlen(in->var_field); \
__packet->size = sizeof(emu_struct) + size + 1; \
__packet->pBuffer = new unsigned char[__packet->size] {}; \
__packet->pBuffer = new unsigned char[__packet->size]; \
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
eq_struct *eq = (eq_struct *) __eq_buffer;
+70 -449
View File
@@ -32,7 +32,6 @@
#include "../strings.h"
#include "../item_instance.h"
#include "titanium_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../raid.h"
#include "../guilds.h"
@@ -198,135 +197,64 @@ namespace Titanium
ENCODE(OP_BazaarSearch)
{
if (((*p)->size == sizeof(BazaarReturnDone_Struct)) || ((*p)->size == sizeof(BazaarWelcome_Struct))) {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
return;
}
//consume the packet
EQApplicationPacket *in = *p;
*p = nullptr;
uint32 action = *(uint32 *)in->pBuffer;
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer;
switch (action) {
case BazaarSearch: {
LogTrading(
"Encode OP_BazaarSearch(Ti) BazaarSearch action <green>[{}]",
action
);
std::vector<BazaarSearchResultsFromDB_Struct> results {};
auto bsms = (BazaarSearchMessaging_Struct *)in->pBuffer;
EQ::Util::MemoryStreamReader ss(
reinterpret_cast<char *>(bsms->payload),
in->size - sizeof(BazaarSearchMessaging_Struct)
);
cereal::BinaryInputArchive ar(ss);
ar(results);
auto size = results.size() * sizeof(structs::BazaarSearchResults_Struct);
auto buffer = new uchar[size];
uchar *bufptr = buffer;
memset(buffer, 0, size);
for (auto row = results.begin(); row != results.end(); ++row) {
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, structs::TiBazaarTraderBuyerActions::BazaarSearch);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->trader_entity_id);
bufptr += 4;
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->item_id);
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number);
bufptr += 4;
if (row->stackable) {
strn0cpy(
reinterpret_cast<char *>(bufptr),
fmt::format("{}({})", row->item_name.c_str(), row->charges).c_str(),
64
);
}
else {
strn0cpy(
reinterpret_cast<char *>(bufptr),
fmt::format("{}({})", row->item_name.c_str(), row->count).c_str(),
64
);
}
bufptr += 64;
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->cost);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->item_stat);
}
auto outapp = new EQApplicationPacket(OP_BazaarSearch, size);
memcpy(outapp->pBuffer, buffer, size);
dest->FastQueuePacket(&outapp);
safe_delete(outapp);
safe_delete_array(buffer);
safe_delete(in);
break;
}
case BazaarInspect:
case WelcomeMessage: {
LogTrading(
"Encode OP_BazaarSearch(Ti) BazaarInspect/WelcomeMessage action <green>[{}]",
action
);
dest->FastQueuePacket(&in, ack_req);
break;
}
default: {
LogTrading(
"Encode OP_BazaarSearch(Ti) unhandled action <red>[{}]",
action
);
dest->FastQueuePacket(&in, ack_req);
}
//determine and verify length
int entrycount = in->size / sizeof(BazaarSearchResults_Struct);
if (entrycount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0) {
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
delete in;
return;
}
//make the EQ struct.
in->size = sizeof(structs::BazaarSearchResults_Struct)*entrycount;
in->pBuffer = new unsigned char[in->size];
structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *) in->pBuffer;
//zero out the packet. We could avoid this memset by setting all fields (including unknowns) in the loop.
memset(in->pBuffer, 0, in->size);
for (int i = 0; i < entrycount; i++, eq++, emu++) {
eq->Beginning.Action = emu->Beginning.Action;
eq->Beginning.Unknown001 = emu->Beginning.Unknown001;
eq->Beginning.Unknown002 = emu->Beginning.Unknown002;
eq->NumItems = emu->NumItems;
eq->SerialNumber = emu->SerialNumber;
eq->SellerID = emu->SellerID;
eq->Cost = emu->Cost;
eq->ItemStat = emu->ItemStat;
strcpy(eq->ItemName, emu->ItemName);
}
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_BecomeTrader)
{
uint32 action = *(uint32 *)(*p)->pBuffer;
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
switch (action)
{
case TraderOff:
{
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
LogTrading(
"Encode OP_BecomeTrader(Ti) TraderOff action <green>[{}] entity_id <green>[{}] trader_name "
"<green>[{}]",
emu->action,
emu->entity_id,
emu->trader_name
);
eq->action = structs::TiBazaarTraderBuyerActions::Zero;
eq->entity_id = emu->entity_id;
FINISH_ENCODE();
break;
}
case TraderOn:
{
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
LogTrading(
"Encode OP_BecomeTrader(Ti) TraderOn action <green>[{}] entity_id <green>[{}] trader_name "
"<green>[{}]",
emu->action,
emu->entity_id,
emu->trader_name
);
eq->action = structs::TiBazaarTraderBuyerActions::BeginTraderMode;
eq->entity_id = emu->entity_id;
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
FINISH_ENCODE();
break;
}
default:
{
LogTrading(
"Encode OP_BecomeTrader(Ti) unhandled action <red>[{}] Sending packet as is.",
action
);
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
}
}
OUT(ID);
OUT(Code);
FINISH_ENCODE();
}
ENCODE(OP_Buff)
@@ -806,7 +734,7 @@ namespace Titanium
break;
}
}
break;
break;
}
case AppearanceType::GuildShow: {
FAIL_ENCODE();
@@ -820,28 +748,6 @@ namespace Titanium
FINISH_ENCODE();
}
ENCODE(OP_GuildsList)
{
EQApplicationPacket* in = *p;
*p = nullptr;
GuildsListMessaging_Struct glms{};
EQ::Util::MemoryStreamReader ss(reinterpret_cast<char *>(in->pBuffer), in->size);
cereal::BinaryInputArchive ar(ss);
ar(glms);
auto outapp = new EQApplicationPacket(OP_GuildsList, sizeof(structs::GuildsList_Struct));
auto out = (structs::GuildsList_Struct *) outapp->pBuffer;
for (auto const& g : glms.guild_detail) {
if (g.guild_id < Titanium::constants::MAX_GUILD_ID) {
strn0cpy(out->Guilds[g.guild_id].name, g.guild_name.c_str(), sizeof(out->Guilds[g.guild_id].name));
}
}
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberAdd)
{
ENCODE_LENGTH_EXACT(GuildMemberAdd_Struct)
@@ -1952,19 +1858,6 @@ namespace Titanium
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
FINISH_ENCODE();
}
ENCODE(OP_SpecialMesg)
{
EQApplicationPacket *in = *p;
@@ -2082,170 +1975,32 @@ namespace Titanium
ENCODE(OP_Trader)
{
auto action = *(uint32 *) (*p)->pBuffer;
switch (action) {
case TraderOn: {
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Encode OP_Trader BeginTraderMode action <green>[{}]",
action
);
eq->action = structs::TiBazaarTraderBuyerActions::BeginTraderMode;
OUT(entity_id);
FINISH_ENCODE();
break;
}
case TraderOff: {
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Encode OP_Trader EndTraderMode action <green>[{}]",
action
);
eq->action = structs::TiBazaarTraderBuyerActions::EndTraderMode;
OUT(entity_id);
FINISH_ENCODE();
break;
}
case ListTraderItems: {
ENCODE_LENGTH_EXACT(Trader_Struct);
SETUP_DIRECT_ENCODE(Trader_Struct, structs::Trader_Struct);
LogTrading(
"Encode OP_Trader ListTraderItems action <green>[{}]",
action
);
eq->action = structs::TiBazaarTraderBuyerActions::ListTraderItems;
std::copy_n(emu->items, UF::invtype::BAZAAR_SIZE, eq->item_id);
std::copy_n(emu->item_cost, UF::invtype::BAZAAR_SIZE, eq->item_cost);
FINISH_ENCODE();
break;
}
case BuyTraderItem: {
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_Trader item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
eq->item_id,
eq->price,
eq->quantity,
eq->trader_id
);
eq->action = structs::TiBazaarTraderBuyerActions::BuyTraderItem;
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
FINISH_ENCODE();
break;
}
case ItemMove: {
LogTrading(
"Encode OP_Trader ItemMove action <green>[{}]",
action
);
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
break;
}
default: {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
LogError("Unknown Encode OP_Trader action <red>{} received. Unhandled.", action);
}
if ((*p)->size != sizeof(TraderBuy_Struct)) {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
return;
}
ENCODE_FORWARD(OP_TraderBuy);
}
ENCODE(OP_TraderBuy)
{
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_TraderBuy item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
emu->item_id,
emu->price,
emu->quantity,
emu->trader_id
);
OUT(action);
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
OUT_str(item_name);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
FINISH_ENCODE();
}
ENCODE(OP_TraderShop)
{
auto action = *(uint32 *)(*p)->pBuffer;
switch (action) {
case ClickTrader: {
ENCODE_LENGTH_EXACT(TraderClick_Struct);
SETUP_DIRECT_ENCODE(TraderClick_Struct, structs::TraderClick_Struct);
LogTrading(
"ClickTrader action <green>[{}] trader_id <green>[{}]",
action,
emu->TraderID
);
eq->action = 0;
eq->trader_id = emu->TraderID;
eq->approval = emu->Approval;
FINISH_ENCODE();
break;
}
case BuyTraderItem: {
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_TraderShop item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
eq->item_id,
eq->price,
eq->quantity,
eq->trader_id
);
eq->action = structs::TiBazaarTraderBuyerActions::BuyTraderItem;
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
FINISH_ENCODE();
break;
}
default: {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
LogError("Unknown Encode OP_TraderShop action <red>[{}] received. Unhandled.", action);
}
}
}
ENCODE(OP_TributeItem)
{
ENCODE_LENGTH_EXACT(TributeItem_Struct);
@@ -2496,53 +2251,6 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_BazaarSearch)
{
uint32 action = *(uint32 *) __packet->pBuffer;
switch (action) {
case structs::TiBazaarTraderBuyerActions::BazaarSearch: {
DECODE_LENGTH_EXACT(structs::BazaarSearch_Struct);
SETUP_DIRECT_DECODE(BazaarSearchCriteria_Struct, structs::BazaarSearch_Struct);
emu->action = eq->Beginning.Action;
emu->item_stat = eq->ItemStat;
emu->max_cost = eq->MaxPrice;
emu->min_cost = eq->MinPrice;
emu->max_level = eq->MaxLlevel;
emu->min_level = eq->Minlevel;
emu->race = eq->Race;
emu->slot = eq->Slot;
emu->type = eq->Type == UINT32_MAX ? UINT8_MAX : eq->Type;
emu->trader_entity_id = eq->TraderID;
emu->trader_id = 0;
emu->_class = eq->Class_;
emu->search_scope = eq->TraderID > 0 ? NonRoFBazaarSearchScope : Local_Scope;
emu->max_results = RuleI(Bazaar, MaxSearchResults);
strn0cpy(emu->item_name, eq->Name, sizeof(emu->item_name));
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::BazaarInspect: {
SETUP_DIRECT_DECODE(BazaarInspect_Struct, structs::BazaarInspect_Struct);
IN(action);
memcpy(emu->player_name, eq->player_name, sizeof(emu->player_name));
IN(serial_number);
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::WelcomeMessage: {
break;
}
default: {
LogTrading("(Ti) Unhandled action <red>[{}]", action);
}
}
}
DECODE(OP_Buff)
{
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
@@ -2567,7 +2275,7 @@ namespace Titanium
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = Bug::GetID(eq->category_name);
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
@@ -3167,105 +2875,18 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
emu->tab_display = 0;
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_Trader)
{
auto action = (uint32) __packet->pBuffer[0];
switch (action) {
case structs::TiBazaarTraderBuyerActions::BeginTraderMode: {
DECODE_LENGTH_EXACT(structs::BeginTrader_Struct);
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::BeginTrader_Struct);
LogTrading(
"Decode OP_Trader BeginTraderMode action <red>[{}]",
action
);
emu->action = TraderOn;
emu->unknown_004 = 0;
std::copy_n(eq->serial_number, Titanium::invtype::BAZAAR_SIZE, emu->serial_number);
std::copy_n(eq->cost, Titanium::invtype::BAZAAR_SIZE, emu->item_cost);
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::EndTraderMode: {
DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct);
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Decode OP_Trader(Ti) EndTraderMode action <red>[{}]",
action
);
emu->action = TraderOff;
IN(entity_id);
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::PriceUpdate:
case structs::TiBazaarTraderBuyerActions::ItemMove:
case structs::TiBazaarTraderBuyerActions::EndTransaction:
case structs::TiBazaarTraderBuyerActions::ListTraderItems: {
LogTrading(
"Decode OP_Trader(Ti) Price/ItemMove/EndTransaction/ListTraderItems action <red>[{}]",
action
);
break;
}
case structs::TiBazaarTraderBuyerActions::ReconcileItems: {
break;
}
default: {
LogError("Unhandled(Ti) action <red>[{}] received.", action);
}
}
}
DECODE(OP_TraderBuy)
{
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
FINISH_DIRECT_DECODE();
}
DECODE(OP_TraderShop)
{
DECODE_LENGTH_EXACT(structs::TraderClick_Struct);
SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct);
LogTrading(
"(Ti) action <green>[{}] trader_id <green>[{}] approval <green>[{}]",
eq->action,
eq->trader_id,
eq->approval
);
emu->Code = ClickTrader;
emu->TraderID = eq->trader_id;
emu->Approval = eq->approval;
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
FINISH_DIRECT_DECODE();
}
+1 -2
View File
@@ -286,8 +286,7 @@ namespace Titanium
const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER
const size_t SAY_LINK_BODY_SIZE = 45;
const uint32 MAX_GUILD_ID = 1500;
const size_t SAY_LINK_BODY_SIZE = 45;
} /*constants*/
-7
View File
@@ -45,7 +45,6 @@ E(OP_Emote)
E(OP_FormattedMessage)
E(OP_GroundSpawn)
E(OP_SetGuildRank)
E(OP_GuildsList)
E(OP_GuildMemberLevelUpdate)
E(OP_GuildMemberList)
E(OP_GuildMemberAdd)
@@ -75,14 +74,12 @@ E(OP_SendCharInfo)
E(OP_SendAATable)
E(OP_SetFace)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SpawnAppearance)
E(OP_SpecialMesg)
E(OP_TaskDescription)
E(OP_Track)
E(OP_Trader)
E(OP_TraderBuy)
E(OP_TraderShop)
E(OP_TributeItem)
E(OP_VetRewardsAvaliable)
E(OP_WearChange)
@@ -93,7 +90,6 @@ E(OP_ZoneSpawns)
D(OP_AdventureMerchantSell)
D(OP_ApplyPoison)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
@@ -124,10 +120,7 @@ D(OP_RaidInvite)
D(OP_ReadBook)
D(OP_SetServerFilter)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TraderShop)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
D(OP_WearChange)

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