Compare commits

..

1 Commits

Author SHA1 Message Date
Uleat a0073b4018 Metric prototype 2020-01-17 21:13:34 -05:00
156 changed files with 2101 additions and 5574 deletions
-21
View File
@@ -1,21 +0,0 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.101.1/containers/ubuntu-18.04-git
{
"name": "Ubuntu 18.04 EQEMU",
// Moved from dockerfile to image so it builds faster
"image": "eqemu/devcontainer:0.0.2",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
// Add the IDs of extensions you want installed when the container is created.
"extensions": ["ms-vscode.cpptools", "ms-azuretools.vscode-docker"],
"mounts": ["source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"],
"remoteEnv": {
"HOST_PROJECT_PATH": "${localWorkspaceFolder}"
}
}
+1 -19
View File
@@ -17,8 +17,6 @@
*.out
*.app
.bash_history
# CMake
CMakeCache.txt
CMakeFiles
@@ -37,20 +35,4 @@ perl/
submodules/*
cmake-build-debug/
.nfs.*
# Visual Studio and CMAKE Generated Files
/.vs/
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.cmake
*.ilk
*.pdb
*.sln
*.dir/
libs/
bin/
/Win32
/x64
/client_files/**/CMakeFiles/
.nfs.*
-3
View File
@@ -16,6 +16,3 @@
[submodule "submodules/recastnavigation"]
path = submodules/recastnavigation
url = https://github.com/EQEmu/recastnavigation.git
[submodule "submodules/expected"]
path = submodules/expected
url = https://github.com/TartanLlama/expected.git
+19 -11
View File
@@ -1,18 +1,26 @@
language: cpp
compiler: gcc
dist: bionic
dist: trusty
addons:
apt:
packages:
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
- uuid-dev
- libssl-dev
before_install:
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
- mkdir $HOME/usr
- export PATH="$HOME/usr/bin:$PATH"
- wget https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.sh
- chmod +x cmake-3.11.2-Linux-x86_64.sh
- ./cmake-3.11.2-Linux-x86_64.sh --prefix=$HOME/usr --exclude-subdir --skip-license
install:
- sudo apt-get install -qq g++-7
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 90
- sudo apt-get install libmysqlclient-dev
- sudo apt-get install libperl-dev
- sudo apt-get install libboost-dev
- sudo apt-get install liblua5.1-0-dev
- sudo apt-get install zlib1g-dev
- sudo apt-get install uuid-dev
- sudo apt-get install libssl-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
- make -j2
-16
View File
@@ -1,16 +0,0 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/mysql"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++17"
}
],
"version": 4
}
-155
View File
@@ -1,155 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "make",
"type": "shell",
"command": "cd build && make",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "make clean",
"type": "shell",
"command": "cd build && make clean",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "cmake",
"type": "shell",
"command": "mkdir -p build && cd build && rm CMakeCache.txt && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' ..",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher":{
"owner": "cpp",
"fileLocation": "relative",
"pattern":[
{
"regexp": "([\\w+|\\\\]*\\.\\w+)\\((\\d+)\\)\\: (warning|error) (.*)$",
"file": 1,
"location": 2,
"severity": 3,
"message": 4
}
]
}
},
{
"label": "download maps",
"type": "shell",
"command": "mkdir -p build/bin && cd build/bin && wget https://codeload.github.com/Akkadius/EQEmuMaps/zip/master -O maps.zip && unzip -o maps.zip && rm ./maps -rf && mv EQEmuMaps-master maps && rm maps.zip",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "download quests",
"type": "shell",
"command": "mkdir -p build/bin && cd build/bin && cd server && git -C ./quests pull 2> /dev/null || git clone https://github.com/ProjectEQ/projecteqquests.git quests",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "download eqemu_config",
"type": "shell",
"command": "mkdir -p build/bin && cd build/bin && wget --no-check-certificate https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/eqemu_config_docker.json -O eqemu_config.json",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "rebuild database (mariadb must be started)",
"type": "shell",
"command": "mkdir -p build/bin && cd build/bin && docker run -i --rm --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --network=eqemu -it eqemu/server:0.0.3 bash -c './eqemu_server.pl source_peq_db && ./eqemu_server.pl check_db_updates && ./eqemu_server.pl linux_login_server_setup'",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "zone 7000",
"type": "shell",
"command": "docker stop zone7000 | true && docker network create eqemu | true && docker run -i --rm --name zone7000 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu -p 7000:7000/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7000:7000",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "zone 7001",
"type": "shell",
"command": "docker stop zone7001 | true && docker network create eqemu | true && docker run -i --rm --name zone7001 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu -p 7001:7001/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./zone dynamic_zone7001:7001",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "loginserver",
"type": "shell",
"command": "docker stop loginserver | true && docker network create eqemu | true && docker run -i --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --privileged -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 --network=eqemu --name loginserver -p 5999:5999/udp -p 5998:5998/udp -e LD_LIBRARY_PATH=/src/ eqemu/server:0.0.3 gdb -ex run --args ./loginserver",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "shared_memory, world",
"type": "shell",
"command": "docker stop sharedmemory | true && docker stop world | true && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --network=eqemu --name sharedmemory eqemu/server:0.0.3 ./shared_memory && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name world -p 9000:9000 -p 9000:9000/udp -p 9001:9001 -p 9080:9080 eqemu/server:0.0.3 gdb -ex run ./world",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "queryserv",
"type": "shell",
"command": "docker stop queryserv | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin:/src --ulimit core=10000000 -e LD_LIBRARY_PATH=/src/ --network=eqemu --name queryserv eqemu/server:0.0.3 gdb -ex run ./queryserv",
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "mariadb",
"type": "shell",
"command": "docker stop mariadb | true && cd build/bin && docker network create eqemu | true && docker run --rm -v ${HOST_PROJECT_PATH}/build/bin/db:/bitnami/mariadb -p 3306:3306 -e MARIADB_DATABASE=peq -e MARIADB_USER=eqemu -e MARIADB_PASSWORD=eqemupass -e ALLOW_EMPTY_PASSWORD=yes --name mariadb --network=eqemu bitnami/mariadb:latest",
"group": {
"kind": "test",
"isDefault": true
}
}
]
}
-1
View File
@@ -270,7 +270,6 @@ INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_LIBRARY_INCLUDE}")
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/expected/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/libuv/include" )
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include")
+4 -4
View File
@@ -1,7 +1,7 @@
# EQEmulator Core Server
|Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) |
|Travis CI (Linux)|Appveyor w/ Bots (Windows) |Appveyor w/o Bots (Windows) |
|:---:|:---:|:---:|
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/v3utuu0dttm2cqd0?svg=true)](https://ci.appveyor.com/project/KimLS/server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp) |
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp/branch/master) |[![Build status](https://ci.appveyor.com/api/projects/status/mdwbr4o9l6mxqofj/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-w0pq2/branch/master) |
***
@@ -17,7 +17,7 @@
|:---:|:---:|:---:|
|**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)|
### > Windows
* [Install](https://eqemu.gitbook.io/server/categories/how-to-guides/installation/server-installation-windows)
* [Install](https://github.com/EQEmu/Server/wiki/Windows-Server)
### > Debian/Ubuntu/CentOS/Fedora
* You can use curl or wget to kick off the installer (whichever your OS has)
@@ -52,7 +52,7 @@ forum, although pull requests will be much quicker and easier on all parties.
## Resources
- [EQEmulator Forums](http://www.eqemulator.org/forums)
- [EQEmulator Wiki](https://eqemu.gitbook.io/)
- [EQEmulator Wiki](https://github.com/EQEmu/Server/wiki)
## Related Repositories
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
+3 -22
View File
@@ -9,7 +9,6 @@ SET(common_sources
crash.cpp
crc16.cpp
crc32.cpp
database/database_dump_service.cpp
database.cpp
database_conversions.cpp
database_instances.cpp
@@ -32,7 +31,6 @@ SET(common_sources
event_sub.cpp
extprofile.cpp
faction.cpp
file_util.cpp
guild_base.cpp
guilds.cpp
inventory_profile.cpp
@@ -46,6 +44,7 @@ SET(common_sources
md5.cpp
memory_buffer.cpp
memory_mapped_file.cpp
metric_manager.cpp
misc.cpp
misc_functions.cpp
mutex.cpp
@@ -122,7 +121,6 @@ SET(common_headers
cli/argh.h
cli/eqemu_command_handler.h
cli/terminal_color.hpp
database/database_dump_service.h
data_verification.h
database.h
database_schema.h
@@ -151,10 +149,8 @@ SET(common_headers
eqtime.h
errmsg.h
event_sub.h
expected.h
extprofile.h
faction.h
file_util.h
features.h
fixed_memory_hash_set.h
fixed_memory_variable_hash_set.h
@@ -178,6 +174,8 @@ SET(common_headers
md5.h
memory_buffer.h
memory_mapped_file.h
metric_event.h
metric_manager.h
misc.h
misc_functions.h
mutex.h
@@ -268,13 +266,6 @@ SET(common_headers
patches/uf_limits.h
patches/uf_ops.h
patches/uf_structs.h
shared/shared_memory.h
shared/shared_memory_error.h
shared/shared_memory_handle.h
shared/shared_memory_list.h
shared/shared_memory_map.h
shared/shared_memory_string.h
shared/shared_memory_vector.h
StackWalker/StackWalker.h
util/memory_stream.h
util/directory.h
@@ -373,16 +364,6 @@ SOURCE_GROUP(Patches FILES
patches/uf_limits.cpp
)
SOURCE_GROUP(shared FILES
shared/shared_memory.h
shared/shared_memory_error.h
shared/shared_memory_handle.h
shared/shared_memory_list.h
shared/shared_memory_map.h
shared/shared_memory_string.h
shared/shared_memory_vector.h
)
SOURCE_GROUP(StackWalker FILES
StackWalker/StackWalker.h
StackWalker/StackWalker.cpp
+1 -1
View File
@@ -96,7 +96,7 @@ namespace EQEmuCommand {
"\nCommand" <<
termcolor::reset << "\n\n" <<
termcolor::green << argv[1] << arguments_string << termcolor::reset << "\n" <<
termcolor::yellow << (!options_string.empty() ? "\nOptions\n\n" : "") <<
termcolor::yellow << (!options_string.empty() ? "\nOptions\n" : "") <<
termcolor::reset << termcolor::cyan << options_string << termcolor::reset;
std::cout << command_string.str() << std::endl;
+37 -97
View File
@@ -45,7 +45,6 @@
#include "eq_packet_structs.h"
#include "extprofile.h"
#include "string_util.h"
#include "database_schema.h"
extern Client client;
@@ -339,21 +338,6 @@ bool Database::ReserveName(uint32 account_id, char* name) {
query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name);
results = QueryDatabase(query);
if (!results.Success() || results.ErrorMessage() != ""){ return false; }
// Put character into the default guild if rule is being used.
int guild_id = RuleI(Character, DefaultGuild);
if (guild_id != 0) {
int character_id=results.LastInsertedID();
if (character_id > -1) {
query = StringFormat("INSERT INTO `guild_members` SET `char_id` = %i, `guild_id` = '%i'", character_id, guild_id);
results = QueryDatabase(query);
if (!results.Success() || results.ErrorMessage() != ""){
LogInfo("Could not put character [{}] into default Guild", name);
}
}
}
return true;
}
@@ -387,7 +371,6 @@ bool Database::DeleteCharacter(char *character_name) {
UPDATE
character_data
SET
name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64),
deleted_at = NOW()
WHERE
id = '{}'
@@ -402,18 +385,46 @@ bool Database::DeleteCharacter(char *character_name) {
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
for (const auto& iter : DatabaseSchema::GetCharacterTables()) {
std::string table_name = iter.first;
std::string character_id_column_name = iter.second;
QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id));
}
query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_tasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
#ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
QueryDatabase(query);
#else
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", character_id);
#endif
QueryDatabase(query);
return true;
}
@@ -925,38 +936,6 @@ void Database::GetCharName(uint32 char_id, char* name) {
}
}
const char* Database::GetCharNameByID(uint32 char_id) {
std::string query = fmt::format("SELECT `name` FROM `character_data` WHERE id = {}", char_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return "";
}
if (results.RowCount() == 0) {
return "";
}
auto row = results.begin();
return row[0];
}
const char* Database::GetNPCNameByID(uint32 npc_id) {
std::string query = fmt::format("SELECT `name` FROM `npc_types` WHERE id = {}", npc_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return "";
}
if (results.RowCount() == 0) {
return "";
}
auto row = results.begin();
return row[0];
}
bool Database::LoadVariables() {
auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache.last_update));
@@ -2190,44 +2169,6 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
return atoi(row[0]);
}
uint32 Database::GetGroupIDByCharID(uint32 character_id)
{
std::string query = fmt::format(
SQL(
SELECT groupid
FROM group_id
WHERE charid = '{}'
),
character_id
);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
return atoi(row[0]);
}
uint32 Database::GetRaidIDByCharID(uint32 character_id) {
std::string query = fmt::format(
SQL(
SELECT raidid
FROM raid_members
WHERE charid = '{}'
),
character_id
);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
return atoi(row[0]);
}
return 0;
}
/**
* @param log_settings
*/
@@ -2405,4 +2346,3 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
return 0;
}
+4 -8
View File
@@ -133,13 +133,9 @@ public:
uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
uint32 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id);
uint32 GetRaidIDByCharID(uint32 char_id);
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
void GetCharName(uint32 char_id, char* name);
const char *GetCharNameByID(uint32 char_id);
const char *GetNPCNameByID(uint32 npc_id);
void LoginIP(uint32 AccountID, const char* LoginIP);
/* Instancing */
@@ -196,19 +192,19 @@ public:
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 acctid);
int GetIPExemption(std::string account_ip);
int GetInstanceID(uint32 char_id, uint32 zone_id);
/* Groups */
char* GetGroupLeaderForLogin(const char* name,char* leaderbuf);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
uint32 GetGroupID(const char* name);
void ClearGroup(uint32 gid = 0);
void ClearGroupLeader(uint32 gid = 0);
void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false);
-569
View File
@@ -1,569 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <string>
#include <cstdio>
#include <iterator>
#include "database_dump_service.h"
#include "../eqemu_logsys.h"
#include "../string_util.h"
#include "../eqemu_config.h"
#include "../database_schema.h"
#include "../file_util.h"
#include <ctime>
#if _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#define DATABASE_DUMP_PATH "backups/"
/**
* @param cmd
* @param return_result
* @return
*/
std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true)
{
const char *file_name = "db-exec-result.txt";
if (return_result) {
#ifdef _WINDOWS
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#else
std::system((cmd + " > " + file_name).c_str());
#endif
}
else {
std::system((cmd).c_str());
}
std::string result;
if (return_result) {
std::ifstream file(file_name);
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
std::remove(file_name);
}
return result;
}
/**
* @return bool
*/
bool DatabaseDumpService::IsMySQLInstalled()
{
std::string version_output = GetMySQLVersion();
return version_output.find("mysql") != std::string::npos && version_output.find("Ver") != std::string::npos;
}
/**
* Linux
* @return bool
*/
bool DatabaseDumpService::IsTarAvailable()
{
std::string version_output = execute("tar --version");
return version_output.find("GNU tar") != std::string::npos;
}
/**
* Windows
* @return bool
*/
bool DatabaseDumpService::Is7ZipAvailable()
{
std::string version_output = execute("7z --help");
return version_output.find("7-Zip") != std::string::npos;
}
/**
* @return
*/
bool DatabaseDumpService::HasCompressionBinary()
{
return IsTarAvailable() || Is7ZipAvailable();
}
/**
* @return
*/
std::string DatabaseDumpService::GetMySQLVersion()
{
std::string version_output = execute("mysql --version");
return trim(version_output);
}
/**
* @return
*/
std::string DatabaseDumpService::GetBaseMySQLDumpCommand()
{
auto config = EQEmuConfig::get();
return fmt::format(
"mysqldump -u {} -p{} -h {} {}",
config->DatabaseUsername,
config->DatabasePassword,
config->DatabaseHost,
config->DatabaseDB
);
}
/**
* @return
*/
std::string DatabaseDumpService::GetPlayerTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetPlayerTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetLoginTableList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetLoginTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetQueryServTables()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetQueryServerTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetSystemTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetServerTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
tables = DatabaseSchema::GetVersionTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetStateTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetStateTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
}
/**
* @return
*/
std::string DatabaseDumpService::GetContentTablesList()
{
std::string tables_list;
std::vector<std::string> tables = DatabaseSchema::GetContentTables();
for (const auto &table : tables) {
tables_list += table + " ";
}
return trim(tables_list);
}
/**
* @return
*/
std::string GetDumpDate()
{
time_t now = time(nullptr);
struct tm time_struct{};
char buf[80];
time_struct = *localtime(&now);
strftime(buf, sizeof(buf), "%Y-%m-%d", &time_struct);
std::string time = buf;
return time;
}
/**
* @return
*/
std::string DatabaseDumpService::GetSetDumpPath()
{
return !GetDumpPath().empty() ? GetDumpPath() : DATABASE_DUMP_PATH;
}
/**
* @return
*/
std::string DatabaseDumpService::GetDumpFileNameWithPath()
{
return GetSetDumpPath() + GetDumpFileName();
}
void DatabaseDumpService::Dump()
{
if (!IsMySQLInstalled()) {
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
return;
}
if (IsDumpDropTableSyntaxOnly()) {
SetDumpOutputToConsole(true);
}
if (IsDumpOutputToConsole()) {
LogSys.SilenceConsoleLogging();
}
LogInfo("MySQL installed [{}]", GetMySQLVersion());
SetDumpFileName(EQEmuConfig::get()->DatabaseDB + '-' + GetDumpDate());
auto config = EQEmuConfig::get();
LogInfo(
"Database [{}] Host [{}] Username [{}]",
config->DatabaseDB,
config->DatabaseHost,
config->DatabaseUsername
);
std::string options = "--allow-keywords --extended-insert";
if (IsDumpWithNoData()) {
options += " --no-data";
}
if (!IsDumpTableLock()) {
options += " --skip-lock-tables";
}
std::string tables_to_dump;
std::string dump_descriptor;
if (!IsDumpAllTables()) {
if (IsDumpPlayerTables()) {
tables_to_dump += GetPlayerTablesList() + " ";
dump_descriptor += "-player";
}
if (IsDumpSystemTables()) {
tables_to_dump += GetSystemTablesList() + " ";
dump_descriptor += "-system";
}
if (IsDumpStateTables()) {
tables_to_dump += GetStateTablesList() + " ";
dump_descriptor += "-state";
}
if (IsDumpContentTables()) {
tables_to_dump += GetContentTablesList() + " ";
dump_descriptor += "-content";
}
if (IsDumpLoginServerTables()) {
tables_to_dump += GetLoginTableList() + " ";
dump_descriptor += "-login";
}
if (IsDumpQueryServerTables()) {
tables_to_dump += GetQueryServTables();
dump_descriptor += "-queryserv";
}
}
if (!dump_descriptor.empty()) {
SetDumpFileName(GetDumpFileName() + dump_descriptor);
}
/**
* If we are dumping to stdout then we don't generate a file
*/
std::string pipe_file;
if (!IsDumpOutputToConsole()) {
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
}
std::string execute_command = fmt::format(
"{} {} {} {}",
GetBaseMySQLDumpCommand(),
options,
tables_to_dump,
pipe_file
);
if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
FileUtil::mkdir(GetSetDumpPath());
}
if (IsDumpDropTableSyntaxOnly()) {
std::vector<std::string> tables = SplitString(tables_to_dump, ' ');
for (auto &table : tables) {
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
}
if (tables_to_dump.empty()) {
std::cerr << "No tables were specified" << std::endl;
}
}
else {
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
if (!execution_result.empty()) {
std::cout << execution_result;
}
}
if (!tables_to_dump.empty()) {
LogInfo("Dumping Tables [{}]", tables_to_dump);
}
LogInfo("Database dump created at [{}.sql]", GetDumpFileNameWithPath());
if (IsDumpWithCompression() && !IsDumpOutputToConsole()) {
if (HasCompressionBinary()) {
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
if (IsTarAvailable()) {
execute(
fmt::format(
"tar -zcvf {}.tar.gz -C {} {}.sql",
GetDumpFileNameWithPath(),
GetSetDumpPath(),
GetDumpFileName()
)
);
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
}
else if (Is7ZipAvailable()) {
execute(
fmt::format(
"7z a -t7z {}.zip {}.sql",
GetDumpFileNameWithPath(),
GetDumpFileNameWithPath()
)
);
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
}
else {
LogInfo("Compression requested, but no available compression binary was found");
}
}
else {
LogWarning("Compression requested but binary not found... Skipping...");
}
}
// LogDebug("[{}] dump-to-console", IsDumpOutputToConsole());
// LogDebug("[{}] dump-path", GetSetDumpPath());
// LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false"));
// LogDebug("[{}] query-serv", (IsDumpQueryServerTables() ? "true" : "false"));
// LogDebug("[{}] has-compression-binary", (HasCompressionBinary() ? "true" : "false"));
// LogDebug("[{}] content", (IsDumpContentTables() ? "true" : "false"));
// LogDebug("[{}] no-data", (IsDumpWithNoData() ? "true" : "false"));
// LogDebug("[{}] login", (IsDumpLoginServerTables() ? "true" : "false"));
// LogDebug("[{}] player", (IsDumpPlayerTables() ? "true" : "false"));
// LogDebug("[{}] system", (IsDumpSystemTables() ? "true" : "false"));
}
bool DatabaseDumpService::IsDumpSystemTables() const
{
return dump_system_tables;
}
void DatabaseDumpService::SetDumpSystemTables(bool dump_system_tables)
{
DatabaseDumpService::dump_system_tables = dump_system_tables;
}
bool DatabaseDumpService::IsDumpContentTables() const
{
return dump_content_tables;
}
void DatabaseDumpService::SetDumpContentTables(bool dump_content_tables)
{
DatabaseDumpService::dump_content_tables = dump_content_tables;
}
bool DatabaseDumpService::IsDumpPlayerTables() const
{
return dump_player_tables;
}
void DatabaseDumpService::SetDumpPlayerTables(bool dump_player_tables)
{
DatabaseDumpService::dump_player_tables = dump_player_tables;
}
bool DatabaseDumpService::IsDumpLoginServerTables() const
{
return dump_login_server_tables;
}
void DatabaseDumpService::SetDumpLoginServerTables(bool dump_login_server_tables)
{
DatabaseDumpService::dump_login_server_tables = dump_login_server_tables;
}
bool DatabaseDumpService::IsDumpWithNoData() const
{
return dump_with_no_data;
}
void DatabaseDumpService::SetDumpWithNoData(bool dump_with_no_data)
{
DatabaseDumpService::dump_with_no_data = dump_with_no_data;
}
bool DatabaseDumpService::IsDumpAllTables() const
{
return dump_all_tables;
}
void DatabaseDumpService::SetDumpAllTables(bool dump_all_tables)
{
DatabaseDumpService::dump_all_tables = dump_all_tables;
}
bool DatabaseDumpService::IsDumpTableLock() const
{
return dump_table_lock;
}
void DatabaseDumpService::SetDumpTableLock(bool dump_table_lock)
{
DatabaseDumpService::dump_table_lock = dump_table_lock;
}
bool DatabaseDumpService::IsDumpWithCompression() const
{
return dump_with_compression;
}
void DatabaseDumpService::SetDumpWithCompression(bool dump_with_compression)
{
DatabaseDumpService::dump_with_compression = dump_with_compression;
}
const std::string &DatabaseDumpService::GetDumpPath() const
{
return dump_path;
}
void DatabaseDumpService::SetDumpPath(const std::string &dump_path)
{
DatabaseDumpService::dump_path = dump_path;
}
void DatabaseDumpService::SetDumpFileName(const std::string &dump_file_name)
{
DatabaseDumpService::dump_file_name = dump_file_name;
}
const std::string &DatabaseDumpService::GetDumpFileName() const
{
return dump_file_name;
}
bool DatabaseDumpService::IsDumpQueryServerTables() const
{
return dump_query_server_tables;
}
void DatabaseDumpService::SetDumpQueryServerTables(bool dump_query_server_tables)
{
DatabaseDumpService::dump_query_server_tables = dump_query_server_tables;
}
bool DatabaseDumpService::IsDumpOutputToConsole() const
{
return dump_output_to_console;
}
void DatabaseDumpService::SetDumpOutputToConsole(bool dump_output_to_console)
{
DatabaseDumpService::dump_output_to_console = dump_output_to_console;
}
bool DatabaseDumpService::IsDumpDropTableSyntaxOnly() const
{
return dump_drop_table_syntax_only;
}
void DatabaseDumpService::SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only)
{
DatabaseDumpService::dump_drop_table_syntax_only = dump_drop_table_syntax_only;
}
bool DatabaseDumpService::IsDumpStateTables() const
{
return dump_state_tables;
}
void DatabaseDumpService::SetDumpStateTables(bool dump_state_tables)
{
DatabaseDumpService::dump_state_tables = dump_state_tables;
}
-91
View File
@@ -1,91 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_DATABASE_DUMP_SERVICE_H
#define EQEMU_DATABASE_DUMP_SERVICE_H
class DatabaseDumpService {
public:
void Dump();
bool IsDumpAllTables() const;
void SetDumpAllTables(bool dump_all_tables);
bool IsDumpWithNoData() const;
void SetDumpWithNoData(bool dump_with_no_data);
bool IsDumpSystemTables() const;
void SetDumpSystemTables(bool dump_system_tables);
bool IsDumpContentTables() const;
void SetDumpContentTables(bool dump_content_tables);
bool IsDumpPlayerTables() const;
void SetDumpPlayerTables(bool dump_player_tables);
bool IsDumpLoginServerTables() const;
void SetDumpLoginServerTables(bool dump_login_server_tables);
bool IsDumpTableLock() const;
void SetDumpTableLock(bool dump_table_lock);
bool IsDumpWithCompression() const;
void SetDumpWithCompression(bool dump_with_compression);
const std::string &GetDumpPath() const;
void SetDumpPath(const std::string &dump_path);
const std::string &GetDumpFileName() const;
void SetDumpFileName(const std::string &dump_file_name);
bool IsDumpQueryServerTables() const;
void SetDumpQueryServerTables(bool dump_query_server_tables);
bool IsDumpOutputToConsole() const;
void SetDumpOutputToConsole(bool dump_output_to_console);
bool IsDumpDropTableSyntaxOnly() const;
void SetDumpDropTableSyntaxOnly(bool dump_drop_table_syntax_only);
bool IsDumpStateTables() const;
void SetDumpStateTables(bool dump_state_tables);
private:
bool dump_all_tables = false;
bool dump_state_tables = false;
bool dump_system_tables = false;
bool dump_content_tables = false;
bool dump_player_tables = false;
bool dump_query_server_tables = false;
bool dump_login_server_tables = false;
bool dump_with_no_data = false;
bool dump_table_lock = false;
bool dump_with_compression = false;
bool dump_output_to_console = false;
bool dump_drop_table_syntax_only = false;
std::string dump_path;
std::string dump_file_name;
std::string execute(const std::string &cmd, bool return_result);
bool IsMySQLInstalled();
std::string GetMySQLVersion();
std::string GetBaseMySQLDumpCommand();
std::string GetPlayerTablesList();
std::string GetSystemTablesList();
std::string GetStateTablesList();
std::string GetContentTablesList();
std::string GetLoginTableList();
bool IsTarAvailable();
bool Is7ZipAvailable();
bool HasCompressionBinary();
std::string GetDumpFileNameWithPath();
std::string GetSetDumpPath();
std::string GetQueryServTables();
};
#endif //EQEMU_DATABASE_DUMP_SERVICE_H
+46 -94
View File
@@ -97,53 +97,42 @@ bool Database::CheckInstanceExists(uint16 instance_id) {
bool Database::CheckInstanceExpired(uint16 instance_id)
{
int32 start_time = 0;
int32 duration = 0;
int32 start_time = 0;
int32 duration = 0;
uint32 never_expires = 0;
std::string query = StringFormat(
"SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u",
instance_id
);
std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success())
return true;
}
if (results.RowCount() == 0) {
if (results.RowCount() == 0)
return true;
}
auto row = results.begin();
start_time = atoi(row[0]);
duration = atoi(row[1]);
start_time = atoi(row[0]);
duration = atoi(row[1]);
never_expires = atoi(row[2]);
if (never_expires == 1) {
if (never_expires == 1)
return false;
}
timeval tv{};
timeval tv;
gettimeofday(&tv, nullptr);
return (start_time + duration) <= tv.tv_sec;
if ((start_time + duration) <= tv.tv_sec)
return true;
return false;
}
bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration)
{
std::string query = StringFormat(
"INSERT INTO instance_list (id, zone, version, start_time, duration)"
" values (%u, %u, %u, UNIX_TIMESTAMP(), %u)",
instance_id,
zone_id,
version,
duration
);
std::string query = StringFormat("INSERT INTO instance_list (id, zone, version, start_time, duration)"
" values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)",
(unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration);
auto results = QueryDatabase(query);
return results.Success();
@@ -151,84 +140,66 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
bool Database::GetUnusedInstanceID(uint16 &instance_id)
{
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max = 32000;
std::string query = StringFormat(
"SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u",
max_reserved_instance_id,
max_reserved_instance_id
);
if (RuleB(Instances, RecycleInstanceIds)) {
query = (
SQL(
SELECT i.id + 1 AS next_available
FROM instance_list i
LEFT JOIN instance_list i2 ON i2.id = i.id + 1
WHERE i2.id IS NULL
ORDER BY i.id
LIMIT 0, 1;
)
);
}
uint32 count = RuleI(Zone, ReservedInstances);
uint32 max = 65535;
std::string query = StringFormat("SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count);
auto results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success())
{
instance_id = 0;
return false;
}
if (results.RowCount() == 0) {
instance_id = max_reserved_instance_id;
return true;
if (results.RowCount() == 0)
{
instance_id = 0;
return false;
}
auto row = results.begin();
if (atoi(row[0]) <= max) {
if (atoi(row[0]) <= max)
{
instance_id = atoi(row[0]);
return true;
}
if (instance_id < max_reserved_instance_id) {
instance_id = max_reserved_instance_id;
return true;
}
query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", max_reserved_instance_id);
query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", count);
results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success())
{
instance_id = 0;
return false;
}
if (results.RowCount() == 0) {
if (results.RowCount() == 0)
{
instance_id = 0;
return false;
}
max_reserved_instance_id++;
for (auto row = results.begin(); row != results.end(); ++row) {
if (max_reserved_instance_id < atoi(row[0])) {
instance_id = max_reserved_instance_id;
count++;
for (auto row = results.begin(); row != results.end(); ++row)
{
if (count < atoi(row[0]))
{
instance_id = count;
return true;
}
if (max_reserved_instance_id > max) {
if (count > max)
{
instance_id = 0;
return false;
}
max_reserved_instance_id++;
count++;
}
instance_id = max_reserved_instance_id;
instance_id = count;
return true;
}
@@ -577,36 +548,17 @@ 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
*/
std::string query =
SQL(
SELECT
id
FROM
instance_list
where
(start_time + duration) <= (UNIX_TIMESTAMP() - 86400)
and never_expires = 0
);
std::string query("SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0");
auto results = QueryDatabase(query);
if (!results.Success()) {
if (!results.Success())
return;
}
if (results.RowCount() == 0) {
if (results.RowCount() == 0)
return;
}
for (auto row = results.begin(); row != results.end(); ++row) {
for (auto row = results.begin(); row != results.end(); ++row)
DeleteInstance(atoi(row[0]));
}
}
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
@@ -614,4 +566,4 @@ void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), "
"duration=%u WHERE id=%u", new_duration, instance_id);
auto results = QueryDatabase(query);
}
}
+33 -107
View File
@@ -22,77 +22,17 @@
#define EQEMU_DATABASE_SCHEMA_H
#include <vector>
#include <map>
namespace DatabaseSchema {
/**
* Character-specific tables
*
* Does not included related meta-data tables such as 'guilds', 'accounts'
* @return
*/
static std::map<std::string, std::string> GetCharacterTables()
{
return {
{"adventure_stats", "player_id"},
{"buyer", "charid"},
{"char_recipe_list", "char_id"},
{"character_activities", "charid"},
{"character_alt_currency", "char_id"},
{"character_alternate_abilities", "id"},
{"character_auras", "id"},
{"character_bandolier", "id"},
{"character_bind", "id"},
{"character_buffs", "character_id"},
{"character_corpses", "id"},
{"character_currency", "id"},
{"character_data", "id"},
{"character_disciplines", "id"},
{"character_enabledtasks", "charid"},
{"character_inspect_messages", "id"},
{"character_item_recast", "id"},
{"character_languages", "id"},
{"character_leadership_abilities", "id"},
{"character_material", "id"},
{"character_memmed_spells", "id"},
{"character_pet_buffs", "char_id"},
{"character_pet_info", "char_id"},
{"character_pet_inventory", "char_id"},
{"character_potionbelt", "id"},
{"character_skills", "id"},
{"character_spells", "id"},
{"character_tasks", "charid"},
{"character_tribute", "id"},
{"completed_tasks", "charid"},
{"data_buckets", "id"},
{"faction_values", "char_id"},
{"friends", "charid"},
{"guild_members", "char_id"},
{"guilds", "id"},
{"instance_list_player", "id"},
{"inventory", "charid"},
{"inventory_snapshots", "charid"},
{"keyring", "char_id"},
{"mail", "charid"},
{"player_titlesets", "char_id"},
{"quest_globals", "charid"},
{"timers", "char_id"},
{"titles", "char_id"},
{"trader", "char_id"},
{"zone_flags", "charID"}
};
}
/**
* @description Gets all player and meta-data tables
* @note These tables have no content in the PEQ daily dump
* Gets player tables
*
* @return
*/
static std::vector<std::string> GetPlayerTables()
{
return {
std::vector<std::string> tables = {
"account",
"account_ip",
"account_flags",
@@ -130,7 +70,6 @@ namespace DatabaseSchema {
"character_tribute",
"completed_tasks",
"data_buckets",
"discovered_items",
"faction_values",
"friends",
"guild_bank",
@@ -143,18 +82,17 @@ namespace DatabaseSchema {
"inventory_snapshots",
"keyring",
"mail",
"petitions",
"player_titlesets",
"quest_globals",
"sharedbank",
"spell_buckets",
"spell_globals",
"timers",
"titles",
"trader",
"trader_audit",
"zone_flags"
};
return tables;
}
/**
@@ -164,7 +102,7 @@ namespace DatabaseSchema {
*/
static std::vector<std::string> GetContentTables()
{
return {
std::vector<std::string> tables = {
"aa_ability",
"aa_actions",
"aa_effects",
@@ -238,6 +176,7 @@ namespace DatabaseSchema {
"task_activities",
"tasks",
"tasksets",
"titles",
"tradeskill_recipe",
"tradeskill_recipe_entries",
"traps",
@@ -249,6 +188,8 @@ namespace DatabaseSchema {
"zone_server",
"zoneserver_auth",
};
return tables;
}
/**
@@ -258,48 +199,34 @@ namespace DatabaseSchema {
*/
static std::vector<std::string> GetServerTables()
{
return {
"chatchannels",
std::vector<std::string> tables = {
"banned_ips",
"bugs",
"bug_reports",
"command_settings",
"db_str",
"discovered_items",
"eqtime",
"eventlog",
"gm_ips",
"hackers",
"ip_exemptions",
"launcher",
"launcher_zones",
"level_exp_mods",
"logsys_categories",
"name_filter",
"perl_event_export_settings",
"petitions",
"profanity_list",
"reports",
"rule_sets",
"rule_values",
"saylink",
"variables",
};
}
/**
* 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",
};
return tables;
}
/**
@@ -310,17 +237,11 @@ namespace DatabaseSchema {
*/
static std::vector<std::string> GetStateTables()
{
return {
std::vector<std::string> tables = {
"adventure_members",
"banned_ips",
"bug_reports",
"bugs",
"eventlog",
"gm_ips",
"chatchannels",
"group_id",
"group_leaders",
"hackers",
"ip_exemptions",
"item_tick",
"lfguild",
"merchantlist_temp",
@@ -328,11 +249,12 @@ namespace DatabaseSchema {
"raid_details",
"raid_leaders",
"raid_members",
"reports",
"respawn_times",
"saylink",
"spell_buckets",
"spell_globals",
};
return tables;
}
/**
@@ -342,13 +264,15 @@ namespace DatabaseSchema {
*/
static std::vector<std::string> GetLoginTables()
{
return {
std::vector<std::string> tables = {
"login_accounts",
"login_api_tokens",
"login_server_admins",
"login_server_list_types",
"login_world_servers",
};
return tables;
}
/**
@@ -358,10 +282,12 @@ namespace DatabaseSchema {
*/
static std::vector<std::string> GetVersionTables()
{
return {
std::vector<std::string> tables = {
"db_version",
"inventory_versions",
};
return tables;
}
}
+10 -6
View File
@@ -115,14 +115,14 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
/**
* Error logging
*/
/* Implement Logging at the Root */
if (mysql_errno(&mysql) > 0 && strlen(query) > 0) {
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(&mysql), mysql_error(&mysql), query);
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)
Log(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
}
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer);
}
// successful query. get results.
@@ -143,7 +143,9 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
if ((strncasecmp(query, "select", 6) == 0)) {
LogMySQLQuery(
LogF(
Logs::General,
Logs::MySQLQuery,
"{0} ({1} row{2} returned) ({3}s)",
query,
requestResult.RowCount(),
@@ -152,7 +154,9 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
);
}
else {
LogMySQLQuery(
LogF(
Logs::General,
Logs::MySQLQuery,
"{0} ({1} row{2} affected) ({3}s)",
query,
requestResult.RowsAffected(),
-9
View File
@@ -317,15 +317,6 @@ namespace EQEmu
QuestControlGrid = -1
};
namespace consent {
enum eConsentType : uint8 {
Normal = 0,
Group,
Raid,
Guild
};
}; // namespace consent
} /*EQEmu*/
#endif /*COMMON_EMU_CONSTANTS_H*/
+8 -9
View File
@@ -35,8 +35,6 @@ static const uint32 MAX_MERC = 100;
static const uint32 MAX_MERC_GRADES = 10;
static const uint32 MAX_MERC_STANCES = 10;
static const uint32 BLOCKED_BUFF_COUNT = 20;
static const uint32 QUESTREWARD_COUNT = 8;
static const uint32 ADVANCED_LORE_LENGTH = 8192;
/*
@@ -2182,7 +2180,14 @@ struct QuestReward_Struct
/*024*/ uint32 silver; // Gives silver to the client
/*028*/ uint32 gold; // Gives gold to the client
/*032*/ uint32 platinum; // Gives platinum to the client
/*036*/ int32 item_id[QUESTREWARD_COUNT]; // -1 for nothing
/*036*/ uint32 item_id;
/*040*/ uint32 unknown040;
/*044*/ uint32 unknown044;
/*048*/ uint32 unknown048;
/*052*/ uint32 unknown052;
/*056*/ uint32 unknown056;
/*060*/ uint32 unknown060;
/*064*/ uint32 unknown064;
/*068*/
};
@@ -2967,12 +2972,6 @@ struct ItemViewRequest_Struct {
/*046*/ char unknown046[2];
};
struct ItemAdvancedLoreText_Struct {
int32 item_id;
char item_name[64];
char advanced_lore[ADVANCED_LORE_LENGTH];
};
struct LDONItemViewRequest_Struct {
uint32 item_id;
uint8 unknown004[4];
-2
View File
@@ -124,8 +124,6 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
/**
* RFC 5424
-4
View File
@@ -113,8 +113,6 @@ namespace Logs {
AoeCast,
EntityManagement,
Flee,
Aura,
HotReload,
MaxCategoryID /* Don't Remove this */
};
@@ -187,8 +185,6 @@ namespace Logs {
"AOE Cast",
"Entity Management",
"Flee",
"Aura",
"HotReload",
};
}
-32
View File
@@ -551,26 +551,6 @@
OutF(LogSys, Logs::Detail, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAura(message, ...) do {\
if (LogSys.log_settings[Logs::Aura].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAuraDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Aura].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogHotReload(message, ...) do {\
if (LogSys.log_settings[Logs::HotReload].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogHotReloadDetail(message, ...) do {\
if (LogSys.log_settings[Logs::HotReload].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
@@ -898,18 +878,6 @@
#define LogFleeDetail(message, ...) do {\
} while (0)
#define LogAura(message, ...) do {\
} while (0)
#define LogAuraDetail(message, ...) do {\
} while (0)
#define LogHotReload(message, ...) do {\
} while (0)
#define LogHotReloadDetail(message, ...) do {\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
} while (0)
-4
View File
@@ -25,10 +25,6 @@ namespace EQ
uv_run(&m_loop, UV_RUN_DEFAULT);
}
void Shutdown() {
uv_stop(&m_loop);
}
uv_loop_t* Handle() { return &m_loop; }
private:
-67
View File
@@ -1,67 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <fstream>
#include "file_util.h"
#ifdef _WINDOWS
#include <direct.h>
#include <conio.h>
#include <iostream>
#include <dos.h>
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#include <sys/stat.h>
#endif
/**
* @param name
* @return
*/
bool FileUtil::exists(const std::string &name)
{
std::ifstream f(name.c_str());
return f.good();
}
/**
* @param directory_name
*/
void FileUtil::mkdir(const std::string& directory_name)
{
#ifdef _WINDOWS
struct _stat st;
if (_stat(directory_name.c_str(), &st) == 0) // exists
return;
_mkdir(directory_name.c_str());
#else
struct stat st{};
if (stat(directory_name.c_str(), &st) == 0) { // exists
return;
}
::mkdir(directory_name.c_str(), 0755);
#endif
}
-32
View File
@@ -1,32 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_FILE_UTIL_H
#define EQEMU_FILE_UTIL_H
class FileUtil {
public:
static bool exists(const std::string &name);
static void mkdir(const std::string& directory_name);
};
#endif //EQEMU_FILE_UTIL_H
+4 -4
View File
@@ -912,7 +912,7 @@ bool BaseGuildManager::GetEntireGuild(uint32 guild_id, std::vector<CharGuildInfo
return(false);
//load up the rank info for each guild.
std::string query = StringFormat(GuildMemberBaseQuery " WHERE g.guild_id=%d AND c.deleted_at IS NULL", guild_id);
std::string query = StringFormat(GuildMemberBaseQuery " WHERE g.guild_id=%d", guild_id);
auto results = m_db->QueryDatabase(query);
if (!results.Success()) {
return false;
@@ -941,7 +941,7 @@ bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) {
m_db->DoEscapeString(esc, char_name, nl);
//load up the rank info for each guild.
std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.name='%s' AND c.deleted_at IS NULL", esc);
std::string query = StringFormat(GuildMemberBaseQuery " WHERE c.name='%s'", esc);
safe_delete_array(esc);
auto results = m_db->QueryDatabase(query);
if (!results.Success()) {
@@ -969,9 +969,9 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
//load up the rank info for each guild.
std::string query;
#ifdef BOTS
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C' AND c.deleted_at IS NULL", char_id);
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C'", char_id);
#else
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.deleted_at IS NULL", char_id);
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d", char_id);
#endif
auto results = m_db->QueryDatabase(query);
if (!results.Success()) {
+65
View File
@@ -0,0 +1,65 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef METRIC_EVENT_H
#define METRIC_EVENT_H
#include "types.h"
namespace EQEmu
{
class MetricEvent {
public:
enum class EventType {
eventNone,
eventNpcStatsMonitor
};
MetricEvent() {
m_finalized = false;
m_expired = false;
m_event_id = 0;
}
virtual EventType GetEventType() const = 0;
virtual void Process() = 0;
virtual void Flush() = 0;
virtual void Finalize() { m_finalized = true; } // invoke MetricEvent::Finalize() inside of derived class function if not handled locally
bool IsFinalized() const { return m_finalized; }
virtual void Expire() { m_finalized = true; m_expired = true; } // invoke MetricEvent::Expire() inside of derived class function if not handled locally
bool IsExpired() const { return m_expired; }
void SetEventId(int value) { if (m_event_id == 0) { m_event_id = value; } }
int GetEventId() const { return m_event_id; }
private:
bool m_finalized;
bool m_expired;
int m_event_id;
};
} // EQEmu
#endif // METRIC_EVENT_H
+112
View File
@@ -0,0 +1,112 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "metric_manager.h"
#include "metric_event.h"
EQEmu::MetricManager::MetricManager() {
m_current_event_id = 0;
}
void EQEmu::MetricManager::Process() {
for (std::list<MetricEvent*>::iterator iter = m_event_list.begin(); iter != m_event_list.end(); ) {
if ((*iter)->IsExpired()) {
iter = m_event_list.erase(iter);
continue;
}
(*iter)->Process();
++iter;
}
}
int EQEmu::MetricManager::RegisterEvent(MetricEvent* event_object) {
if (event_object == nullptr) {
return 0;
}
event_object->SetEventId(get_next_event_id());
m_event_list.push_back(event_object);
return event_object->GetEventId();
}
void EQEmu::MetricManager::FlushAll() {
for (auto iter : m_event_list) {
iter->Flush();
}
}
void EQEmu::MetricManager::FlushById(int event_id) {
for (auto iter : m_event_list) {
if (iter->GetEventId() == event_id) {
iter->Flush();
break;
}
}
}
void EQEmu::MetricManager::FinalizeAll() {
for (auto iter : m_event_list) {
iter->Finalize();
}
}
void EQEmu::MetricManager::FinalizeById(int event_id) {
for (auto iter : m_event_list) {
if (iter->GetEventId() == event_id) {
iter->Finalize();
break;
}
}
}
void EQEmu::MetricManager::ExpireAll() {
for (auto iter : m_event_list) {
iter->Expire();
}
}
void EQEmu::MetricManager::ExpireById(int event_id) {
for (auto iter : m_event_list) {
if (iter->GetEventId() == event_id) {
iter->Expire();
break;
}
}
}
int EQEmu::MetricManager::get_next_event_id() {
return ++m_current_event_id;
}
@@ -1,32 +1,58 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) EQEMu Development Team (http://eqemulator.net)
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#ifndef METRIC_MANAGER_H
#define METRIC_MANAGER_H
namespace eq
#include <list>
namespace EQEmu
{
namespace shared
{
enum class shared_memory_error
{
no_error,
error_mapping_memory,
error_alloc
};
}
}
class MetricEvent;
class MetricManager {
public:
MetricManager();
void Process();
int RegisterEvent(MetricEvent*);
void FlushAll();
void FlushById(int);
void FinalizeAll();
void FinalizeById(int);
void ExpireAll();
void ExpireById(int);
private:
int get_next_event_id();
int m_current_event_id;
std::list<MetricEvent*> m_event_list;
};
} // EQEmu
#endif // METRIC_MANAGER_H
+2 -4
View File
@@ -1047,14 +1047,12 @@ void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t leng
uint8_t new_buffer[2048] = { 0 };
uint8_t *buffer = (uint8_t*)p.Data() + offset;
uint32_t new_length = 0;
bool send_uncompressed = true;
if (length > 30) {
new_length = Deflate(buffer, (uint32_t)length, new_buffer + 1, 2048) + 1;
new_buffer[0] = 0x5a;
send_uncompressed = (new_length > length);
}
if (send_uncompressed) {
else {
memcpy(new_buffer + 1, buffer, length);
new_buffer[0] = 0xa5;
new_length = length + 1;
@@ -1382,7 +1380,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
}
auto stream = &m_streams[stream_id];
auto max_raw_size = m_max_packet_size - m_crc_bytes - DaybreakReliableHeader::size() - 1; // -1 for compress flag
auto max_raw_size = m_max_packet_size - m_crc_bytes - DaybreakReliableHeader::size();
size_t length = p.Length();
if (length > max_raw_size) {
DaybreakReliableFragmentHeader first_header;
+4 -4
View File
@@ -89,9 +89,9 @@ namespace EQ {
public:
StaticPacket(void *data, size_t size) { m_data = data; m_data_length = size; m_max_data_length = size; }
virtual ~StaticPacket() { }
StaticPacket(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; m_max_data_length = o.m_max_data_length; }
StaticPacket(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; }
StaticPacket& operator=(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; return *this; }
StaticPacket(StaticPacket &&o) noexcept { m_data = o.m_data; m_data_length = o.m_data_length; }
StaticPacket(StaticPacket &&o) { m_data = o.m_data; m_data_length = o.m_data_length; }
virtual const void *Data() const { return m_data; }
virtual void *Data() { return m_data; }
@@ -112,7 +112,7 @@ namespace EQ {
public:
DynamicPacket() { }
virtual ~DynamicPacket() { }
DynamicPacket(DynamicPacket &&o) noexcept { m_data = std::move(o.m_data); }
DynamicPacket(DynamicPacket &&o) { m_data = std::move(o.m_data); }
DynamicPacket(const DynamicPacket &o) { m_data = o.m_data; }
DynamicPacket& operator=(const DynamicPacket &o) { m_data = o.m_data; return *this; }
@@ -127,4 +127,4 @@ namespace EQ {
std::vector<char> m_data;
};
}
}
}
+1 -1
View File
@@ -4401,7 +4401,7 @@ struct SendAA_Struct {
/*0104*/ uint32 special_category;
/*0108*/ uint8 shroud;
/*0109*/ uint8 unknown109;
/*0110*/ uint8 reset_on_death; // timer is reset on death
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
/*0111*/ uint8 unknown111;
/*0112*/ uint32 total_abilities;
/*0116*/ AA_Ability abilities[0];
+1 -1
View File
@@ -4341,7 +4341,7 @@ struct SendAA_Struct {
/*0104*/ uint32 special_category;
/*0108*/ uint8 shroud;
/*0109*/ uint8 unknown109;
/*0110*/ uint8 reset_on_death; // timer is reset on death
/*0110*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
/*0111*/ uint8 unknown111;
/*0112*/ uint32 total_abilities;
/*0116*/ AA_Ability abilities[0];
+1 -1
View File
@@ -3780,7 +3780,7 @@ struct SendAA_Struct {
/*0092*/ uint32 special_category;
/*0096*/ uint8 shroud;
/*0097*/ uint8 unknown97;
/*0098*/ uint8 reset_on_death; // timer is reset on death
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
/*0099*/ uint8 unknown99;
/*0100*/ uint32 total_abilities;
/*0104*/ AA_Ability abilities[0];
+1 -1
View File
@@ -3704,7 +3704,7 @@ struct SendAA_Struct {
/*0088*/ uint32 aa_expansion;
/*0092*/ uint32 special_category;
/*0096*/ uint8 shroud;
/*0097*/ uint8 reset_on_death; // timer is reset on death -- guess
/*0097*/ uint8 unknown97;
/*0098*/ uint32 total_abilities;
/*0102*/ AA_Ability abilities[0];
};
+1 -1
View File
@@ -3835,7 +3835,7 @@ struct SendAA_Struct {
/*0092*/ uint32 special_category;
/*0096*/ uint8 shroud;
/*0097*/ uint8 unknown97;
/*0098*/ uint8 reset_on_death; // timer is reset on death
/*0098*/ uint8 layonhands; // 1 for lay on hands -- doesn't seem to matter?
/*0099*/ uint8 unknown99;
/*0100*/ uint32 total_abilities;
/*0104*/ AA_Ability abilities[0];
+2 -20
View File
@@ -121,7 +121,6 @@ RULE_BOOL(Character, EnableAggroMeter, true, "Enable Aggro Meter, for users with
RULE_BOOL(Character, KeepLevelOverMax, false, "Don't delevel a character that has somehow gone over the level cap")
RULE_INT(Character, FoodLossPerUpdate, 32, "How much food/water you lose per stamina update")
RULE_BOOL(Character, EnableHungerPenalties, false, "being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties")
RULE_BOOL(Character, EnableFoodRequirement, true, "if disabled, food is no longer required")
RULE_INT(Character, BaseInstrumentSoftCap, 36, "Softcap for instrument mods, 36 commonly referred to as \"3.6\" as well")
RULE_BOOL(Character, UseSpellFileSongCap, true, "When they removed the AA that increased the cap they removed the above and just use the spell field")
RULE_INT(Character, BaseRunSpeedCap, 158, "Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225")
@@ -160,8 +159,6 @@ RULE_BOOL(Character, PetsUseReagents, true, "Pets use reagent on spells")
RULE_BOOL(Character, DismountWater, true, "Dismount horses when entering water")
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated")
RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
@@ -198,7 +195,6 @@ RULE_INT(Skills, SwimmingStartValue, 100, "")
RULE_BOOL(Skills, TrainSenseHeading, false, "")
RULE_INT(Skills, SenseHeadingStartValue, 200, "")
RULE_BOOL(Skills, SelfLanguageLearning, true, "")
RULE_BOOL(Skills, RequireTomeHandin, false, "Disable click-to-learn and force turnin to Guild Master")
RULE_CATEGORY_END()
RULE_CATEGORY(Pets)
@@ -270,6 +266,7 @@ RULE_INT(Zone, PEQZoneDebuff1, 4454, "First debuff casted by #peqzone Default is
RULE_INT(Zone, PEQZoneDebuff2, 2209, "Second debuff casted by #peqzone Default is Tendrils of Apathy")
RULE_BOOL(Zone, UsePEQZoneDebuffs, true, "Will determine if #peqzone will debuff players or not when used")
RULE_REAL(Zone, HotZoneBonus, 0.75, "")
RULE_INT(Zone, ReservedInstances, 30, "Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running")
RULE_INT(Zone, EbonCrystalItemID, 40902, "")
RULE_INT(Zone, RadiantCrystalItemID, 40903, "")
RULE_BOOL(Zone, LevelBasedEXPMods, false, "Allows you to use the level_exp_mods table in consideration to your players EXP hits")
@@ -297,7 +294,6 @@ RULE_BOOL(Pathing, Find, true, "Enable pathing for FindPerson requests from the
RULE_BOOL(Pathing, Fear, true, "Enable pathing for fear")
RULE_REAL(Pathing, NavmeshStepSize, 100.0f, "")
RULE_REAL(Pathing, ShortMovementUpdateRange, 130.0f, "")
RULE_INT(Pathing, MaxNavmeshNodes, 4092, "Max navmesh nodes in a traversable path")
RULE_CATEGORY_END()
RULE_CATEGORY(Watermap)
@@ -496,7 +492,6 @@ RULE_INT(Combat, NPCAssistCapTimer, 6000, "Time in milliseconds a NPC will take
RULE_BOOL(Combat, UseRevampHandToHand, false, "use h2h revamped dmg/delays I believe this was implemented during SoF")
RULE_BOOL(Combat, ClassicMasterWu, false, "classic master wu uses a random special, modern doesn't")
RULE_INT(Combat, LevelToStopDamageCaps, 0, "1 will effectively disable them, 20 should give basically same results as old incorrect system")
RULE_INT(Combat, LevelToStopACTwinkControl, 50, "1 will effectively disable it, 50 should give basically same results as current system")
RULE_BOOL(Combat, ClassicNPCBackstab, false, "true disables npc facestab - npcs get normal attack if not behind")
RULE_BOOL(Combat, UseNPCDamageClassLevelMods, true, "Uses GetClassLevelDamageMod calc in npc_scale_manager")
RULE_BOOL(Combat, UseExtendedPoisonProcs, false, "Allow old school poisons to last until characrer zones, at a lower proc rate")
@@ -524,11 +519,10 @@ RULE_INT(NPC, NPCToNPCAggroTimerMin, 500, "")
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000, "")
RULE_BOOL(NPC, UseClassAsLastName, true, "Uses class archetype as LastName for npcs with none")
RULE_BOOL(NPC, NewLevelScaling, true, "Better level scaling, use old if new formulas would break your server")
RULE_INT(NPC, NPCGatePercent, 20, "% at which the NPC Will attempt to gate at")
RULE_INT(NPC, NPCGatePercent, 5, "% at which the NPC Will attempt to gate at")
RULE_BOOL(NPC, NPCGateNearBind, false, "Will NPC attempt to gate when near bind location?")
RULE_INT(NPC, NPCGateDistanceBind, 75, "Distance from bind before NPC will attempt to gate")
RULE_BOOL(NPC, NPCHealOnGate, true, "Will the NPC Heal on Gate")
RULE_BOOL(NPC, UseMeditateBasedManaRegen, false, "Based NPC ooc regen on Meditate skill")
RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the npc will heal on gate if enabled")
RULE_CATEGORY_END()
@@ -768,18 +762,6 @@ RULE_CATEGORY(Logging)
RULE_BOOL(Logging, PrintFileFunctionAndLine, false, "Ex: [World Server] [net.cpp::main:309] Loading variables...")
RULE_CATEGORY_END()
RULE_CATEGORY(HotReload)
RULE_BOOL(HotReload, QuestsRepopWithReload, true, "When a hot reload is triggered, the zone will repop")
RULE_BOOL(HotReload, QuestsRepopWhenPlayersNotInCombat, true, "When a hot reload is triggered, the zone will repop when no clients are in combat")
RULE_BOOL(HotReload, QuestsResetTimersWithReload, true, "When a hot reload is triggered, quest timers will be reset")
RULE_CATEGORY_END()
RULE_CATEGORY(Instances)
RULE_INT(Instances, ReservedInstances, 30, "Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running")
RULE_BOOL(Instances, RecycleInstanceIds, true, "Will recycle free instance ids instead of gradually running out at 32k")
RULE_INT(Instances, GuildHallExpirationDays, 90, "Amount of days before a Guild Hall instance expires")
RULE_CATEGORY_END()
#undef RULE_CATEGORY
#undef RULE_INT
#undef RULE_REAL
+4 -14
View File
@@ -197,11 +197,7 @@
#define ServerOP_CZSetEntityVariableByClientName 0x4012
#define ServerOP_UCSServerStatusRequest 0x4013
#define ServerOP_UCSServerStatusReply 0x4014
#define ServerOP_HotReloadQuests 0x4015
/**
* QueryServer
*/
/* Query Server OP Codes */
#define ServerOP_QSPlayerLogTrades 0x5010
#define ServerOP_QSPlayerLogHandins 0x5011
#define ServerOP_QSPlayerLogNPCKills 0x5012
@@ -870,12 +866,10 @@ struct SpawnPlayerCorpse_Struct {
struct ServerOP_Consent_Struct {
char grantname[64];
char ownername[64];
char zonename[32];
uint8 permission;
uint32 zone_id;
uint16 instance_id;
uint8 consent_type; // 0 = normal, 1 = group, 2 = raid, 3 = guild
uint32 consent_id;
uint32 message_string_id;
};
struct ReloadTasks_Struct {
@@ -1355,16 +1349,12 @@ struct CZSetEntVarByClientName_Struct {
char m_var[256];
};
struct ReloadWorld_Struct {
struct ReloadWorld_Struct{
uint32 Option;
};
struct HotReloadQuestsStruct {
char zone_short_name[200];
};
struct ServerRequestTellQueue_Struct {
char name[64];
char name[64];
};
struct UCSServerStatus_Struct {
-82
View File
@@ -1,82 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#pragma once
#include "../expected.h"
#include "shared_memory_error.h"
#include "shared_memory_handle.h"
#include <boost/interprocess/managed_mapped_file.hpp>
#include <memory>
namespace eq
{
namespace shared
{
namespace detail {
typedef boost::interprocess::managed_mapped_file::segment_manager segment_manager_t;
typedef boost::interprocess::allocator<void, segment_manager_t> allocator;
}
using allocator = detail::allocator;
class shared_memory
{
public:
shared_memory(const std::string &path, size_t sz) {
_path = path;
_sz = sz;
}
~shared_memory() = default;
template<typename Ty>
expected<handle<Ty>, shared_memory_error> map(const std::string& key) {
if (!_memory) {
try {
_memory.reset(new boost::interprocess::managed_mapped_file(boost::interprocess::open_or_create, _path.c_str(), _sz));
}
catch (boost::interprocess::interprocess_exception) {
return eq::make_unexpected(shared_memory_error::error_mapping_memory);
}
}
handle<Ty> inst;
auto ir = inst.initialize(key, _memory.get());
if (ir) {
return eq::expected<handle<Ty>, shared_memory_error>(inst);
}
else {
return make_unexpected(ir.error());
}
return expected<handle<Ty>, shared_memory_error>(inst);
}
template<typename Ty, typename... Args>
Ty construct(Args&&... args) {
return Ty(std::forward<Args>(args)..., _memory->get_allocator<void>());
}
private:
std::unique_ptr<boost::interprocess::managed_mapped_file> _memory;
std::string _path;
size_t _sz;
};
}
}
-70
View File
@@ -1,70 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#pragma once
#include "shared_memory_error.h"
#include "../expected.h"
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <type_traits>
namespace eq
{
namespace shared
{
namespace detail
{
template<typename Ty>
struct type_factory {
static_assert(std::is_trivially_constructible<Ty>::value,
"Non-specialized types must be trivially constructible, consider creating a type_factory in eq::shared::detail if you want to use this type.");
Ty* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
return mmf->find_or_construct<Ty>(key.c_str())();
}
};
}
template<typename Ty>
class handle {
public:
handle() = default;
~handle() = default;
expected<void, shared_memory_error> initialize(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
try {
_mmf = mmf;
detail::type_factory<Ty> fac;
_ptr = fac.create(key, mmf);
return expected<void, shared_memory_error>();
}
catch (boost::interprocess::interprocess_exception) {
return make_unexpected(shared_memory_error::error_mapping_memory);
}
}
operator Ty& () {
return *_ptr;
}
private:
Ty* _ptr;
boost::interprocess::managed_mapped_file* _mmf;
};
}
}
-43
View File
@@ -1,43 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#pragma once
#include "shared_memory_handle.h"
#include <boost/interprocess/containers/list.hpp>
namespace eq
{
namespace shared
{
template<typename Ty>
using list = boost::interprocess::list<Ty, boost::interprocess::allocator<Ty, boost::interprocess::managed_mapped_file::segment_manager>>;
namespace detail
{
template<typename Ty>
struct type_factory<list<Ty>>
{
list<Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
return mmf->find_or_construct<list<Ty>>(key.c_str())(mmf->get_allocator<void>());
}
};
}
}
}
-77
View File
@@ -1,77 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#pragma once
#include "shared_memory_handle.h"
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/flat_map.hpp>
#include <boost/unordered_map.hpp>
namespace eq
{
namespace shared
{
template<typename Ky, typename Ty>
using unordered_map = boost::unordered_map<int,
Ty,
boost::hash<Ky>,
std::equal_to<Ky>,
boost::interprocess::allocator<std::pair<const Ky, Ty>, boost::interprocess::managed_mapped_file::segment_manager>>;
template<typename Ky, typename Ty>
using map = boost::interprocess::map<Ky,
Ty,
std::less<Ky>,
boost::interprocess::allocator<std::pair<const Ky, Ty>, boost::interprocess::managed_mapped_file::segment_manager>>;
template<typename Ky, typename Ty>
using flat_map = boost::interprocess::flat_map<Ky,
Ty,
std::less<Ky>,
boost::interprocess::allocator<std::pair<const Ky, Ty>, boost::interprocess::managed_mapped_file::segment_manager>>;
namespace detail
{
template<typename Ky, typename Ty>
struct type_factory<unordered_map<Ky, Ty>>
{
unordered_map<Ky, Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
return mmf->find_or_construct<unordered_map<Ky, Ty>>(key.c_str())(3, boost::hash<Ky>(), std::equal_to<Ky>(), mmf->get_allocator<void>());
}
};
template<typename Ky, typename Ty>
struct type_factory<map<Ky, Ty>>
{
map<Ky, Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
return mmf->find_or_construct<map<Ky, Ty>>(key.c_str())(std::less<Ky>(), mmf->get_allocator<void>());
}
};
template<typename Ky, typename Ty>
struct type_factory<flat_map<Ky, Ty>>
{
flat_map<Ky, Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
return mmf->find_or_construct<flat_map<Ky, Ty>>(key.c_str())(std::less<Ky>(), mmf->get_allocator<void>());
}
};
}
}
}
-52
View File
@@ -1,52 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#pragma once
#pragma once
#include "shared_memory_handle.h"
#include <boost/interprocess/containers/string.hpp>
namespace eq
{
namespace shared
{
template<typename Ty>
using basic_string = boost::interprocess::basic_string<Ty, std::char_traits<Ty>, boost::interprocess::allocator<Ty, boost::interprocess::managed_mapped_file::segment_manager>>;
using string = basic_string<char>;
namespace detail
{
template<typename Ty>
struct type_factory<basic_string<Ty>>
{
list<Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
return mmf->find_or_construct<list<Ty>>(key.c_str())(mmf->get_allocator<void>());
}
};
}
template<typename Ty>
std::basic_string<Ty> to_std_string(const eq::shared::basic_string<Ty> &in) {
return std::basic_string<Ty>(in.begin(), in.end());
}
}
}
-43
View File
@@ -1,43 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#pragma once
#include "shared_memory_handle.h"
#include <boost/interprocess/containers/vector.hpp>
namespace eq
{
namespace shared
{
template<typename Ty>
using vector = boost::interprocess::vector<Ty, boost::interprocess::allocator<Ty, boost::interprocess::managed_mapped_file::segment_manager>>;
namespace detail
{
template<typename Ty>
struct type_factory<vector<Ty>>
{
vector<Ty>* create(const std::string& key, boost::interprocess::managed_mapped_file* mmf) {
return mmf->find_or_construct<vector<Ty>>(key.c_str())(mmf->get_allocator<void>());
}
};
}
}
}
+141 -139
View File
@@ -1656,19 +1656,21 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill
return ret;
}
int SharedDatabase::LoadDamageShieldType(int spell_id) {
void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) {
std::string query = StringFormat("SELECT `type` FROM `damageshieldtypes` WHERE `spellid` = %i", spell_id);
std::string query = StringFormat("SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 "
"AND `spellid` <= %i", iMaxSpellID);
auto results = QueryDatabase(query);
if (!results.Success()) {
return 0;
return;
}
for(auto &row : results) {
return atoi(row[0]);
for(auto row = results.begin(); row != results.end(); ++row) {
int spellID = atoi(row[0]);
if((spellID > 0) && (spellID <= iMaxSpellID))
sp[spellID].DamageShieldType = atoi(row[1]);
}
return 0;
}
const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) {
@@ -1687,18 +1689,6 @@ int SharedDatabase::GetMaxSpellID() {
return atoi(row[0]);
}
int SharedDatabase::GetSpellCount() {
std::string query = "SELECT COUNT(id) FROM spells_new";
auto results = QueryDatabase(query);
if (!results.Success()) {
return -1;
}
auto row = results.begin();
return atoi(row[0]);
}
bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) {
spells_mmf.reset(nullptr);
@@ -1720,163 +1710,175 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const
return true;
}
void SharedDatabase::LoadSpells(std::function<void(const SPDat_Spell_Struct & sp)> on_load) {
void SharedDatabase::LoadSpells(void *data, int max_spells) {
*(uint32*)data = max_spells;
SPDat_Spell_Struct *sp = reinterpret_cast<SPDat_Spell_Struct*>((char*)data + sizeof(uint32));
const std::string query = "SELECT * FROM spells_new ORDER BY id ASC";
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
if(results.ColumnCount() <= SPELL_LOAD_FIELD_COUNT) {
LogSpells("Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT([{}])", SPELL_LOAD_FIELD_COUNT);
return;
}
for (auto &row : results) {
SPDat_Spell_Struct sp;
int tempid = 0;
int counter = 0;
sp.id = atoi(row[0]);
strn0cpy(sp.name, row[1], sizeof(sp.name));
strn0cpy(sp.player_1, row[2], sizeof(sp.player_1));
strn0cpy(sp.teleport_zone, row[3], sizeof(sp.teleport_zone));
strn0cpy(sp.you_cast, row[4], sizeof(sp.you_cast));
strn0cpy(sp.other_casts, row[5], sizeof(sp.other_casts));
strn0cpy(sp.cast_on_you, row[6], sizeof(sp.cast_on_you));
strn0cpy(sp.cast_on_other, row[7], sizeof(sp.cast_on_other));
strn0cpy(sp.spell_fades, row[8], sizeof(sp.spell_fades));
for (auto row = results.begin(); row != results.end(); ++row) {
tempid = atoi(row[0]);
if(tempid >= max_spells) {
LogSpells("Non fatal error: spell.id >= max_spells, ignoring");
continue;
}
sp.range = static_cast<float>(atof(row[9]));
sp.aoerange = static_cast<float>(atof(row[10]));
sp.pushback = static_cast<float>(atof(row[11]));
sp.pushup = static_cast<float>(atof(row[12]));
sp.cast_time = atoi(row[13]);
sp.recovery_time = atoi(row[14]);
sp.recast_time = atoi(row[15]);
sp.buffdurationformula = atoi(row[16]);
sp.buffduration = atoi(row[17]);
sp.AEDuration = atoi(row[18]);
sp.mana = atoi(row[19]);
++counter;
sp[tempid].id = tempid;
strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name));
strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1));
strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone));
strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast));
strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts));
strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you));
strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other));
strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades));
int y = 0;
for (y = 0; y < EFFECT_COUNT; y++)
sp.base[y] = atoi(row[20 + y]); // effect_base_value
sp[tempid].range=static_cast<float>(atof(row[9]));
sp[tempid].aoerange=static_cast<float>(atof(row[10]));
sp[tempid].pushback=static_cast<float>(atof(row[11]));
sp[tempid].pushup=static_cast<float>(atof(row[12]));
sp[tempid].cast_time=atoi(row[13]);
sp[tempid].recovery_time=atoi(row[14]);
sp[tempid].recast_time=atoi(row[15]);
sp[tempid].buffdurationformula=atoi(row[16]);
sp[tempid].buffduration=atoi(row[17]);
sp[tempid].AEDuration=atoi(row[18]);
sp[tempid].mana=atoi(row[19]);
for (y = 0; y < EFFECT_COUNT; y++)
sp.base2[y] = atoi(row[32 + y]); // effect_limit_value
int y=0;
for(y=0; y< EFFECT_COUNT;y++)
sp[tempid].base[y]=atoi(row[20+y]); // effect_base_value
for (y = 0; y < EFFECT_COUNT; y++)
sp.max[y] = atoi(row[44 + y]);
for(y=0; y < EFFECT_COUNT; y++)
sp[tempid].base2[y]=atoi(row[32+y]); // effect_limit_value
for (y = 0; y < 4; y++)
sp.components[y] = atoi(row[58 + y]);
for(y=0; y< EFFECT_COUNT;y++)
sp[tempid].max[y]=atoi(row[44+y]);
for (y = 0; y < 4; y++)
sp.component_counts[y] = atoi(row[62 + y]);
for(y=0; y< 4;y++)
sp[tempid].components[y]=atoi(row[58+y]);
for (y = 0; y < 4; y++)
sp.NoexpendReagent[y] = atoi(row[66 + y]);
for(y=0; y< 4;y++)
sp[tempid].component_counts[y]=atoi(row[62+y]);
for (y = 0; y < EFFECT_COUNT; y++)
sp.formula[y] = atoi(row[70 + y]);
for(y=0; y< 4;y++)
sp[tempid].NoexpendReagent[y]=atoi(row[66+y]);
sp.goodEffect = atoi(row[83]);
sp.Activated = atoi(row[84]);
sp.resisttype = atoi(row[85]);
for(y=0; y< EFFECT_COUNT;y++)
sp[tempid].formula[y]=atoi(row[70+y]);
for (y = 0; y < EFFECT_COUNT; y++)
sp.effectid[y] = atoi(row[86 + y]);
sp[tempid].goodEffect=atoi(row[83]);
sp[tempid].Activated=atoi(row[84]);
sp[tempid].resisttype=atoi(row[85]);
sp.targettype = (SpellTargetType)atoi(row[98]);
sp.basediff = atoi(row[99]);
for(y=0; y< EFFECT_COUNT;y++)
sp[tempid].effectid[y]=atoi(row[86+y]);
sp[tempid].targettype = (SpellTargetType) atoi(row[98]);
sp[tempid].basediff=atoi(row[99]);
int tmp_skill = atoi(row[100]);;
if (tmp_skill < 0 || tmp_skill > EQEmu::skills::HIGHEST_SKILL)
sp.skill = EQEmu::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated
else
sp.skill = (EQEmu::skills::SkillType) tmp_skill;
sp[tempid].skill = EQEmu::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated
else
sp[tempid].skill = (EQEmu::skills::SkillType) tmp_skill;
sp.zonetype = atoi(row[101]);
sp.EnvironmentType = atoi(row[102]);
sp.TimeOfDay = atoi(row[103]);
sp[tempid].zonetype=atoi(row[101]);
sp[tempid].EnvironmentType=atoi(row[102]);
sp[tempid].TimeOfDay=atoi(row[103]);
for (y = 0; y < PLAYER_CLASS_COUNT; y++)
sp.classes[y] = atoi(row[104 + y]);
for(y=0; y < PLAYER_CLASS_COUNT;y++)
sp[tempid].classes[y]=atoi(row[104+y]);
sp.CastingAnim = atoi(row[120]);
sp.SpellAffectIndex = atoi(row[123]);
sp.disallow_sit = atoi(row[124]);
sp.diety_agnostic = atoi(row[125]);
sp[tempid].CastingAnim=atoi(row[120]);
sp[tempid].SpellAffectIndex=atoi(row[123]);
sp[tempid].disallow_sit=atoi(row[124]);
sp[tempid].diety_agnostic=atoi(row[125]);
for (y = 0; y < 16; y++)
sp.deities[y] = atoi(row[126 + y]);
sp[tempid].deities[y]=atoi(row[126+y]);
sp.new_icon = atoi(row[144]);
sp.uninterruptable = atoi(row[146]) != 0;
sp.ResistDiff = atoi(row[147]);
sp.dot_stacking_exempt = atoi(row[148]) != 0;
sp.RecourseLink = atoi(row[150]);
sp.no_partial_resist = atoi(row[151]) != 0;
sp[tempid].new_icon=atoi(row[144]);
sp[tempid].uninterruptable=atoi(row[146]) != 0;
sp[tempid].ResistDiff=atoi(row[147]);
sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0;
sp[tempid].RecourseLink = atoi(row[150]);
sp[tempid].no_partial_resist = atoi(row[151]) != 0;
sp.short_buff_box = atoi(row[154]);
sp.descnum = atoi(row[155]);
sp.typedescnum = atoi(row[156]);
sp.effectdescnum = atoi(row[157]);
sp[tempid].short_buff_box = atoi(row[154]);
sp[tempid].descnum = atoi(row[155]);
sp[tempid].typedescnum = atoi(row[156]);
sp[tempid].effectdescnum = atoi(row[157]);
sp.npc_no_los = atoi(row[159]) != 0;
sp.reflectable = atoi(row[161]) != 0;
sp.bonushate = atoi(row[162]);
sp[tempid].npc_no_los = atoi(row[159]) != 0;
sp[tempid].reflectable = atoi(row[161]) != 0;
sp[tempid].bonushate=atoi(row[162]);
sp.ldon_trap = atoi(row[165]) != 0;
sp.EndurCost = atoi(row[166]);
sp.EndurTimerIndex = atoi(row[167]);
sp.IsDisciplineBuff = atoi(row[168]) != 0;
sp.HateAdded = atoi(row[173]);
sp.EndurUpkeep = atoi(row[174]);
sp.numhitstype = atoi(row[175]);
sp.numhits = atoi(row[176]);
sp.pvpresistbase = atoi(row[177]);
sp.pvpresistcalc = atoi(row[178]);
sp.pvpresistcap = atoi(row[179]);
sp.spell_category = atoi(row[180]);
sp.pcnpc_only_flag = atoi(row[183]);
sp.cast_not_standing = atoi(row[184]) != 0;
sp.can_mgb = atoi(row[185]);
sp.dispel_flag = atoi(row[186]);
sp.MinResist = atoi(row[189]);
sp.MaxResist = atoi(row[190]);
sp.viral_targets = atoi(row[191]);
sp.viral_timer = atoi(row[192]);
sp.NimbusEffect = atoi(row[193]);
sp.directional_start = static_cast<float>(atoi(row[194]));
sp.directional_end = static_cast<float>(atoi(row[195]));
sp.sneak = atoi(row[196]) != 0;
sp.not_focusable = atoi(row[197]) != 0;
sp.no_detrimental_spell_aggro = atoi(row[198]) != 0;
sp.suspendable = atoi(row[200]) != 0;
sp.viral_range = atoi(row[201]);
sp.songcap = atoi(row[202]);
sp.no_block = atoi(row[205]);
sp.spellgroup = atoi(row[207]);
sp.rank = atoi(row[208]);
sp.no_resist = atoi(row[209]);
sp.CastRestriction = atoi(row[211]);
sp.AllowRest = atoi(row[212]) != 0;
sp.InCombat = atoi(row[213]) != 0;
sp.OutofCombat = atoi(row[214]) != 0;
sp.override_crit_chance = atoi(row[217]);
sp.aemaxtargets = atoi(row[218]);
sp.no_heal_damage_item_mod = atoi(row[219]);
sp.persistdeath = atoi(row[224]) != 0;
sp.min_dist = atof(row[227]);
sp.min_dist_mod = atof(row[228]);
sp.max_dist = atof(row[229]);
sp.max_dist_mod = atof(row[230]);
sp.min_range = static_cast<float>(atoi(row[231]));
sp.no_remove = atoi(row[232]) != 0;
sp.DamageShieldType = LoadDamageShieldType(sp.id); //ideally we could do this with a simple join but we need to formalize the table first.
on_load(sp);
sp[tempid].ldon_trap = atoi(row[165]) != 0;
sp[tempid].EndurCost=atoi(row[166]);
sp[tempid].EndurTimerIndex=atoi(row[167]);
sp[tempid].IsDisciplineBuff = atoi(row[168]) != 0;
sp[tempid].HateAdded=atoi(row[173]);
sp[tempid].EndurUpkeep=atoi(row[174]);
sp[tempid].numhitstype = atoi(row[175]);
sp[tempid].numhits = atoi(row[176]);
sp[tempid].pvpresistbase=atoi(row[177]);
sp[tempid].pvpresistcalc=atoi(row[178]);
sp[tempid].pvpresistcap=atoi(row[179]);
sp[tempid].spell_category=atoi(row[180]);
sp[tempid].pcnpc_only_flag=atoi(row[183]);
sp[tempid].cast_not_standing = atoi(row[184]) != 0;
sp[tempid].can_mgb=atoi(row[185]);
sp[tempid].dispel_flag = atoi(row[186]);
sp[tempid].MinResist = atoi(row[189]);
sp[tempid].MaxResist = atoi(row[190]);
sp[tempid].viral_targets = atoi(row[191]);
sp[tempid].viral_timer = atoi(row[192]);
sp[tempid].NimbusEffect = atoi(row[193]);
sp[tempid].directional_start = static_cast<float>(atoi(row[194]));
sp[tempid].directional_end = static_cast<float>(atoi(row[195]));
sp[tempid].sneak = atoi(row[196]) != 0;
sp[tempid].not_focusable = atoi(row[197]) != 0;
sp[tempid].no_detrimental_spell_aggro = atoi(row[198]) != 0;
sp[tempid].suspendable = atoi(row[200]) != 0;
sp[tempid].viral_range = atoi(row[201]);
sp[tempid].songcap = atoi(row[202]);
sp[tempid].no_block = atoi(row[205]);
sp[tempid].spellgroup=atoi(row[207]);
sp[tempid].rank = atoi(row[208]);
sp[tempid].no_resist=atoi(row[209]);
sp[tempid].CastRestriction = atoi(row[211]);
sp[tempid].AllowRest = atoi(row[212]) != 0;
sp[tempid].InCombat = atoi(row[213]) != 0;
sp[tempid].OutofCombat = atoi(row[214]) != 0;
sp[tempid].override_crit_chance = atoi(row[217]);
sp[tempid].aemaxtargets = atoi(row[218]);
sp[tempid].no_heal_damage_item_mod = atoi(row[219]);
sp[tempid].persistdeath = atoi(row[224]) != 0;
sp[tempid].min_dist = atof(row[227]);
sp[tempid].min_dist_mod = atof(row[228]);
sp[tempid].max_dist = atof(row[229]);
sp[tempid].max_dist_mod = atof(row[230]);
sp[tempid].min_range = static_cast<float>(atoi(row[231]));
sp[tempid].no_remove = atoi(row[232]) != 0;
sp[tempid].DamageShieldType = 0;
}
LoadDamageShieldTypes(sp, max_spells);
}
int SharedDatabase::GetMaxBaseDataLevel() {
+2 -3
View File
@@ -140,10 +140,9 @@ class SharedDatabase : public Database
uint8 GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level);
int GetMaxSpellID();
int GetSpellCount();
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
void LoadSpells(std::function<void(const SPDat_Spell_Struct & sp)> on_load);
int LoadDamageShieldType(int spell_id);
void LoadSpells(void *data, int max_spells);
void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID);
int GetMaxBaseDataLevel();
bool LoadBaseData(const std::string &prefix);
+1 -1
View File
@@ -607,7 +607,7 @@ typedef enum {
#define SE_LimitSpellGroup 385 // implemented - Limits to spell group(ie type 3 reuse reduction augs that are class specific and thus all share s SG)
#define SE_CastOnCurer 386 // implemented - Casts a spell on the person curing
#define SE_CastOnCure 387 // implemented - Casts a spell on the cured person
#define SE_SummonCorpseZone 388 // implemented - summons a corpse from any zone(nec AA)
//#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
#define SE_LimitManaMax 391 // implemented
+4 -8
View File
@@ -129,17 +129,13 @@ void Timer::SetTimer(uint32 set_timer_time) {
}
}
uint32 Timer::GetRemainingTime() const
{
uint32 Timer::GetRemainingTime() const {
if (enabled) {
if (current_time - start_time > timer_time) {
if (current_time - start_time > timer_time)
return 0;
}
else {
else
return (start_time + timer_time) - current_time;
}
}
else {
} else {
return 0xFFFFFFFF;
}
}
+2 -2
View File
@@ -34,10 +34,10 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9152
#define CURRENT_BINARY_DATABASE_VERSION 9146
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026
#else
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
#endif
+16 -23
View File
@@ -19,35 +19,28 @@
#include "spells.h"
#include "../common/global_define.h"
#include "../common/shareddb.h"
#include "../common/ipc_mutex.h"
#include "../common/memory_mapped_file.h"
#include "../common/eqemu_exception.h"
#include "../common/spdat.h"
#include "../common/shared/shared_memory.h"
#include "../common/shared/shared_memory_map.h"
namespace eqs = eq::shared;
void LoadSpells(SharedDatabase *database, const std::string &prefix) {
int records = database->GetSpellCount();
int max_spell_id = database->GetMaxSpellID() + 1;
auto size = records * sizeof(SPDat_Spell_Struct) * 125 / 100 + (64 * 1024);
eqs::shared_memory shared("shared/spells", size);
auto spells_result = shared.map<eqs::unordered_map<int, SPDat_Spell_Struct>>("spells");
if (!spells_result) {
//todo: get rid of the exceptions entirely.
EQ_EXCEPT("Shared Memory", "Unable to map shared memory");
EQEmu::IPCMutex mutex("spells");
mutex.Lock();
int records = database->GetMaxSpellID() + 1;
if(records == 0) {
EQ_EXCEPT("Shared Memory", "Unable to get any spells from the database.");
}
auto max_spell_id_result = shared.map<int>("max_spell_id");
if (!max_spell_id_result) {
EQ_EXCEPT("Shared Memory", "Unable to map shared memory");
}
uint32 size = records * sizeof(SPDat_Spell_Struct) + sizeof(uint32);
eqs::unordered_map<int, SPDat_Spell_Struct>& spells_shm = spells_result.value();
int& max_spell_id_shm = max_spell_id_result.value();
max_spell_id_shm = max_spell_id;
auto Config = EQEmuConfig::get();
std::string file_name = Config->SharedMemDir + prefix + std::string("spells");
EQEmu::MemoryMappedFile mmf(file_name, size);
mmf.ZeroFile();
database->LoadSpells([&spells_shm](const SPDat_Spell_Struct &spell) {
spells_shm.insert_or_assign(spell.id, spell);
});
void *ptr = mmf.Get();
database->LoadSpells(ptr, records);
mutex.Unlock();
}
+12 -17
View File
@@ -47,13 +47,8 @@ ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string in
Moderated = false;
LogDebug(
"New ChatChannel created: Name: [[{}]], Owner: [[{}]], Password: [[{}]], MinStatus: [{}]",
Name.c_str(),
Owner.c_str(),
Password.c_str(),
MinimumStatus
);
LogInfo("New ChatChannel created: Name: [[{}]], Owner: [[{}]], Password: [[{}]], MinStatus: [{}]",
Name.c_str(), Owner.c_str(), Password.c_str(), MinimumStatus);
}
@@ -159,7 +154,7 @@ void ChatChannelList::SendAllChannels(Client *c) {
void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
LogDebug("RemoveChannel ([{}])", Channel->GetName().c_str());
LogInfo("RemoveChannel([{}])", Channel->GetName().c_str());
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
@@ -180,7 +175,7 @@ void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
void ChatChannelList::RemoveAllChannels() {
LogDebug("RemoveAllChannels");
LogInfo("RemoveAllChannels");
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
@@ -247,7 +242,7 @@ void ChatChannel::AddClient(Client *c) {
int AccountStatus = c->GetAccountStatus();
LogDebug("Adding [{}] to channel [{}]", c->GetName().c_str(), Name.c_str());
LogInfo("Adding [{}] to channel [{}]", c->GetName().c_str(), Name.c_str());
LinkedListIterator<Client*> iterator(ClientsInChannel);
@@ -272,7 +267,7 @@ bool ChatChannel::RemoveClient(Client *c) {
if(!c) return false;
LogDebug("RemoveClient [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str());
LogInfo("RemoveClient [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str());
bool HideMe = c->GetHideMe();
@@ -309,7 +304,7 @@ bool ChatChannel::RemoveClient(Client *c) {
if((Password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0))
return false;
LogDebug("Starting delete timer for empty password protected channel [{}]", Name.c_str());
LogInfo("Starting delete timer for empty password protected channel [{}]", Name.c_str());
DeleteTimer.Start(RuleI(Channels, DeleteTimer) * 60000);
}
@@ -407,7 +402,7 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
if(ChannelClient)
{
LogDebug("Sending message to [{}] from [{}]",
LogInfo("Sending message to [{}] from [{}]",
ChannelClient->GetName().c_str(), Sender->GetName().c_str());
if (cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())].length() == 0) {
@@ -510,7 +505,7 @@ ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client
return nullptr;
}
LogDebug("AddClient to channel [[{}]] with password [[{}]]", NormalisedName.c_str(), Password.c_str());
LogInfo("AddClient to channel [[{}]] with password [[{}]]", NormalisedName.c_str(), Password.c_str());
ChatChannel *RequiredChannel = FindChannel(NormalisedName);
@@ -586,7 +581,7 @@ void ChatChannelList::Process() {
if(CurrentChannel && CurrentChannel->ReadyToDelete()) {
LogDebug("Empty temporary password protected channel [{}] being destroyed",
LogInfo("Empty temporary password protected channel [{}] being destroyed",
CurrentChannel->GetName().c_str());
RemoveChannel(CurrentChannel);
@@ -602,7 +597,7 @@ void ChatChannel::AddInvitee(const std::string &Invitee)
if (!IsInvitee(Invitee)) {
Invitees.push_back(Invitee);
LogDebug("Added [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
LogInfo("Added [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
}
}
@@ -613,7 +608,7 @@ void ChatChannel::RemoveInvitee(std::string Invitee)
if(it != std::end(Invitees)) {
Invitees.erase(it);
LogDebug("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
LogInfo("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
}
}
+16 -35
View File
@@ -235,7 +235,7 @@ std::vector<std::string> ParseRecipients(std::string RecipientString) {
static void ProcessMailTo(Client *c, std::string MailMessage) {
LogDebug("MAILTO: From [{}], [{}]", c->MailBoxName().c_str(), MailMessage.c_str());
LogInfo("MAILTO: From [{}], [{}]", c->MailBoxName().c_str(), MailMessage.c_str());
std::vector<std::string> Recipients;
@@ -304,7 +304,7 @@ static void ProcessMailTo(Client *c, std::string MailMessage) {
if (!database.SendMail(Recipient, c->MailBoxName(), Subject, Body, RecipientsString)) {
LogError("Failed in SendMail([{}], [{}], [{}], [{}])", Recipient.c_str(),
LogInfo("Failed in SendMail([{}], [{}], [{}], [{}])", Recipient.c_str(),
c->MailBoxName().c_str(), Subject.c_str(), RecipientsString.c_str());
int PacketLength = 10 + Recipient.length() + Subject.length();
@@ -556,17 +556,6 @@ void Client::CloseConnection() {
ClientStream->ReleaseFromUse();
}
void Clientlist::CheckForStaleConnectionsAll()
{
LogDebug("Checking for stale connections");
auto it = ClientChatConnections.begin();
while (it != ClientChatConnections.end()) {
(*it)->SendKeepAlive();
++it;
}
}
void Clientlist::CheckForStaleConnections(Client *c) {
if (!c) return;
@@ -645,12 +634,10 @@ void Clientlist::Process()
//
std::string::size_type LastPeriod = MailBoxString.find_last_of(".");
if (LastPeriod == std::string::npos) {
if (LastPeriod == std::string::npos)
CharacterName = MailBoxString;
}
else {
else
CharacterName = MailBoxString.substr(LastPeriod + 1);
}
LogInfo("Received login for user [{}] with key [{}]",
MailBox, Key);
@@ -665,9 +652,8 @@ void Clientlist::Process()
database.GetAccountStatus((*it));
if ((*it)->GetConnectionType() == ConnectionTypeCombined) {
if ((*it)->GetConnectionType() == ConnectionTypeCombined)
(*it)->SendFriends();
}
(*it)->SendMailBoxes();
@@ -879,9 +865,7 @@ void Clientlist::CloseAllConnections() {
void Client::AddCharacter(int CharID, const char *CharacterName, int Level) {
if (!CharacterName) return;
LogDebug("Adding character [{}] with ID [{}] for [{}]", CharacterName, CharID, GetName().c_str());
LogInfo("Adding character [{}] with ID [{}] for [{}]", CharacterName, CharID, GetName().c_str());
CharacterEntry NewCharacter;
NewCharacter.CharID = CharID;
NewCharacter.Name = CharacterName;
@@ -890,10 +874,6 @@ void Client::AddCharacter(int CharID, const char *CharacterName, int Level) {
Characters.push_back(NewCharacter);
}
void Client::SendKeepAlive() {
QueuePacket(new EQApplicationPacket(OP_SessionReady, 0));
}
void Client::SendMailBoxes() {
int Count = Characters.size();
@@ -950,7 +930,7 @@ void Client::AddToChannelList(ChatChannel *JoinedChannel) {
for (int i = 0; i < MAX_JOINED_CHANNELS; i++)
if (JoinedChannels[i] == nullptr) {
JoinedChannels[i] = JoinedChannel;
LogDebug("Added Channel [{}] to slot [{}] for [{}]", JoinedChannel->GetName().c_str(), i + 1, GetName().c_str());
LogInfo("Added Channel [{}] to slot [{}] for [{}]", JoinedChannel->GetName().c_str(), i + 1, GetName().c_str());
return;
}
}
@@ -2366,17 +2346,18 @@ void Client::SendFriends() {
}
}
std::string Client::MailBoxName()
{
if ((Characters.empty()) || (CurrentMailBox > (Characters.size() - 1))) {
LogDebug("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
CurrentMailBox, Characters.size());
std::string Client::MailBoxName() {
return std::string();
if ((Characters.empty()) || (CurrentMailBox > (Characters.size() - 1)))
{
LogInfo("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
CurrentMailBox, Characters.size());
return "";
}
LogDebug("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
CurrentMailBox, Characters.size());
LogInfo("MailBoxName() called with CurrentMailBox set to [{}] and Characters.size() is [{}]",
CurrentMailBox, Characters.size());
return Characters[CurrentMailBox].Name;
+1 -3
View File
@@ -143,7 +143,7 @@ public:
void SetConnectionType(char c);
ConnectionType GetConnectionType() { return TypeOfConnection; }
EQEmu::versions::ClientVersion GetClientVersion() { return ClientVersion_; }
inline bool IsMailConnection() { return (TypeOfConnection == ConnectionTypeMail) || (TypeOfConnection == ConnectionTypeCombined); }
void SendNotification(int MailBoxNumber, std::string From, std::string Subject, int MessageID);
void ChangeMailBox(int NewMailBox);
@@ -151,7 +151,6 @@ public:
void SendFriends();
int GetCharID();
void SendUptime();
void SendKeepAlive();
private:
unsigned int CurrentMailBox;
@@ -184,7 +183,6 @@ public:
void Process();
void CloseAllConnections();
Client *FindCharacter(std::string CharacterName);
void CheckForStaleConnectionsAll();
void CheckForStaleConnections(Client *c);
Client *IsCharacterOnline(std::string CharacterName);
void ProcessOPMailCommand(Client *c, std::string CommandString);
+3 -3
View File
@@ -108,7 +108,7 @@ void Database::GetAccountStatus(Client *client)
{
std::string query = StringFormat(
"SELECT `status`, `hideme`, `karma`, `revoked` FROM `account` WHERE `id` = %i LIMIT 1",
"SELECT `status`, `hideme`, `karma`, `revoked` FROM `account` WHERE `id` = '%i' LIMIT 1",
client->GetAccountID()
);
@@ -173,7 +173,7 @@ int Database::FindAccount(const char *characterName, Client *client)
query = StringFormat(
"SELECT `id`, `name`, `level` FROM `character_data` "
"WHERE `account_id` = %i AND `name` != '%s' AND deleted_at is NULL",
"WHERE `account_id` = %i AND `name` != '%s'",
accountID, characterName
);
@@ -320,7 +320,7 @@ void Database::SendHeaders(Client *client)
int unknownField3 = 1;
int characterID = FindCharacter(client->MailBoxName().c_str());
LogDebug("Sendheaders for [{}], CharID is [{}]", client->MailBoxName().c_str(), characterID);
LogInfo("Sendheaders for [{}], CharID is [{}]", client->MailBoxName().c_str(), characterID);
if (characterID <= 0) {
return;
+8 -16
View File
@@ -70,18 +70,17 @@ int main() {
// Check every minute for unused channels we can delete
//
Timer ChannelListProcessTimer(60000);
Timer ClientConnectionPruneTimer(60000);
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
LogInfo("Starting EQEmu Universal Chat Server");
if (!ucsconfig::LoadConfig()) {
LogInfo("Loading server configuration failed");
if (!ucsconfig::LoadConfig()) {
LogInfo("Loading server configuration failed");
return 1;
}
Config = ucsconfig::get();
Config = ucsconfig::get();
WorldShortName = Config->ShortName;
@@ -145,26 +144,19 @@ int main() {
worldserver = new WorldServer;
auto loop_fn = [&](EQ::Timer* t) {
while(RunLoops) {
Timer::SetCurrentTime();
g_Clientlist->Process();
if (ChannelListProcessTimer.Check()) {
if(ChannelListProcessTimer.Check())
ChannelList->Process();
}
if (ClientConnectionPruneTimer.Check()) {
g_Clientlist->CheckForStaleConnectionsAll();
}
EQ::EventLoop::Get().Process();
};
EQ::Timer process_timer(loop_fn);
process_timer.Start(32, true);
EQ::EventLoop::Get().Run();
Sleep(5);
}
ChannelList->RemoveAllChannels();
+1 -1
View File
@@ -61,7 +61,7 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
ServerPacket tpack(opcode, p);
ServerPacket *pack = &tpack;
LogNetcode("Received Opcode: {:#04x}", opcode);
LogInfo("Received Opcode: {:#04x}", opcode);
switch (opcode)
{
+1 -1
View File
@@ -331,7 +331,7 @@ OP_LDoNButton=0x596e
OP_SetStartCity=0x7936 # Was 0x2d1b
OP_VoiceMacroIn=0x202e
OP_VoiceMacroOut=0x3920
OP_ItemAdvancedLoreText=0x0b64
OP_ItemViewUnknown=0x0b64
OP_VetRewardsAvaliable=0x05d9
OP_VetClaimRequest=0xcdde
OP_VetClaimReply=0x361b
-2
View File
@@ -448,8 +448,6 @@ OP_FinishWindow2=0x40ef
OP_ItemVerifyRequest=0x189c
OP_ItemVerifyReply=0x097b
OP_ItemAdvancedLoreText=0x023b
# merchant stuff
OP_ShopPlayerSell=0x791b
OP_ShopRequest=0x4fed
+1 -1
View File
@@ -327,7 +327,7 @@ OP_LDoNButton=0x41b5 # C
OP_SetStartCity=0x7bf6 # C
OP_VoiceMacroIn=0x31b1 # C
OP_VoiceMacroOut=0x7880 # C
OP_ItemAdvancedLoreText=0x21c7 # C
OP_ItemViewUnknown=0x21c7 # C
OP_VetRewardsAvaliable=0x4e4e # C
OP_VetClaimRequest=0x771f # C
OP_VetClaimReply=0x2f95 # C
+1 -1
View File
@@ -576,7 +576,7 @@ OP_QueryResponseThing=0x0000 #
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
OP_LoginUnknown1=0x22cf
OP_LoginUnknown2=0x43ba
OP_ItemAdvancedLoreText=0x4db4
OP_ItemViewUnknown=0x4db4
#Petition Opcodes
OP_PetitionSearch=0x0000 #search term for petition
+1 -1
View File
@@ -336,7 +336,7 @@ OP_LDoNButton=0x1031 # C
OP_SetStartCity=0x68f0 # C
OP_VoiceMacroIn=0x1524 # C
OP_VoiceMacroOut=0x1d99 # C
OP_ItemAdvancedLoreText=0x4eb3 # C
OP_ItemViewUnknown=0x4eb3 # C
OP_VetRewardsAvaliable=0x0baa # C Mispelled?
OP_VetClaimRequest=0x34f8 # C
OP_VetClaimReply=0x6a5d # C
+262 -217
View File
@@ -52,10 +52,6 @@ if (-e "eqemu_server_skip_update.txt") {
$skip_self_update_check = 1;
}
if (-e "eqemu_server_skip_maps_update.txt") {
$skip_self_maps_update_check = 1;
}
#::: Check for script self update
check_xml_to_json_conversion() if $ARGV[0] eq "convert_xml";
do_self_update_check_routine() if !$skip_self_update_check;
@@ -464,7 +460,7 @@ sub do_installer_routines {
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
}
map_files_fetch_bulk() if !$skip_self_maps_update_check;
map_files_fetch_bulk();
opcodes_fetch();
plugins_fetch();
quest_files_fetch();
@@ -497,7 +493,9 @@ sub do_installer_routines {
#::: Download PEQ latest
fetch_peq_db_full();
print "[Database] Fetching and Applying Latest Database Updates...\n";
print "[Database] Fetching Latest Database Updates...\n";
main_db_management();
print "[Database] Applying Latest Database Updates...\n";
main_db_management();
remove_duplicate_rule_values();
@@ -533,14 +531,35 @@ sub check_for_world_bootup_database_update {
}
$binary_database_version = trim($db_version[1]);
$local_database_version = get_main_db_version();
$local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
#::: Bots
$bots_binary_version = trim($db_version[2]);
if ($bots_binary_version > 0) {
$bots_local_db_version = get_bots_db_version();
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
if ($bots_local_db_version < $bots_binary_version && $ARGV[0] eq "ran_from_world") {
print "[Update] Bots Database not up to date with binaries... Automatically updating...\n";
print "[Update] Issuing database backup first...\n";
database_dump_compress();
print "[Update] Updating bots database...\n";
sleep(1);
bots_db_management();
run_database_check();
print "[Update] Continuing bootup\n";
analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
exit;
}
else {
print "[Update] Bots database up to Date: Continuing World Bootup...\n";
}
}
if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") {
print "[Update] Database up to date...\n";
if (trim($db_version[2]) == 0) {
print "[Update] Continuing bootup\n";
exit;
}
exit;
}
else {
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
@@ -548,61 +567,22 @@ sub check_for_world_bootup_database_update {
print "[Update] Database not up to date with binaries... Automatically updating...\n";
print "[Update] Issuing database backup first...\n";
database_dump_compress();
$db_already_backed_up = 1;
print "[Update] Updating database...\n";
sleep(1);
main_db_management();
main_db_management();
print "[Update] Continuing bootup\n";
analytics_insertion("auto database upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
exit;
}
#::: Make sure that we didn't pass any arugments to the script
else {
if ($local_database_version > $binary_database_version) {
print "[Update] Database version is ahead of current binaries...\n";
}
if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; }
show_menu_prompt();
}
}
#::: Bots
$binary_database_version = trim($db_version[2]);
if ($binary_database_version > 0) {
$local_database_version = get_bots_db_version();
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") {
print "[Update] Bots database up to date...\n";
}
else {
if ($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world") {
print "[Update] Bots Database not up to date with binaries... Automatically updating...\n";
if (!$db_already_backed_up) {
print "[Update] Issuing database backup first...\n";
database_dump_compress();
}
print "[Update] Updating bots database...\n";
sleep(1);
bots_db_management();
analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
}
#::: Make sure that we didn't pass any arugments to the script
else {
if ($local_database_version > $binary_database_version) {
print "[Update] Bots database version is ahead of current binaries...\n";
}
if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; }
show_menu_prompt();
}
}
}
print "[Update] Continuing bootup\n";
}
sub check_internet_connection {
@@ -649,7 +629,7 @@ sub do_self_update_check_routine {
#::: Check for internet connection before updating
if (!$has_internet_connection) {
print "[Update] Cannot check self-update without internet connection...\n";
print "[Update] Cannot check update without internet connection...\n";
return;
}
@@ -839,6 +819,7 @@ sub setup_bots {
build_linux_source("bots");
}
bots_db_management();
run_database_check();
print "Bots should be setup, run your server and the bot command should be available in-game (type '^help')\n";
}
@@ -972,11 +953,13 @@ sub show_menu_prompt {
$dc = 1;
}
elsif ($input eq "check_db_updates") {
main_db_management();
main_db_management();
$dc = 1;
}
elsif ($input eq "check_bot_db_updates") {
bots_db_management();
run_database_check();
$dc = 1;
}
elsif ($input eq "setup_loginserver") {
@@ -1417,7 +1400,6 @@ sub remove_duplicate_rule_values {
sub copy_file {
$l_source_file = $_[0];
$l_destination_file = $_[1];
if ($l_destination_file =~ /\//i) {
my @directory_path = split('/', $l_destination_file);
$build_path = "";
@@ -1436,7 +1418,6 @@ sub copy_file {
$directory_index++;
}
}
copy $l_source_file, $l_destination_file;
}
@@ -1712,22 +1693,26 @@ sub fetch_server_dlls {
sub fetch_peq_db_full {
print "[Install] Downloading latest PEQ Database... Please wait...\n";
get_remote_file("http://db.projecteq.net/api/v1/dump/latest", "updates_staged/peq-latest.zip", 1);
get_remote_file("http://edit.projecteq.net/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1);
print "[Install] Downloaded latest PEQ Database... Extracting...\n";
unzip('updates_staged/peq-latest.zip', 'updates_staged/peq_db/');
my $start_dir = "updates_staged/peq_db/peq-dump";
unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/');
my $start_dir = "updates_staged/peq_db";
find(
sub { push @files, $File::Find::name unless -d; },
$start_dir
);
for my $file (@files) {
$destination_file = $file;
$destination_file =~ s/updates_staged\/peq_db\/peq-dump\///g;
if ($file =~ /create_tables_content|create_tables_login|create_tables_player|create_tables_queryserv|create_tables_state|create_tables_system/i) {
$destination_file =~ s/updates_staged\/peq_db\///g;
if ($file =~ /peqbeta|player_tables/i) {
print "[Install] DB :: Installing :: " . $destination_file . "\n";
get_mysql_result_from_file($file);
}
}
#::: PEQ DB baseline version
print get_mysql_result("DELETE FROM db_version");
print get_mysql_result("INSERT INTO `db_version` (`version`) VALUES (9130);");
}
sub map_files_fetch_bulk {
@@ -2016,6 +2001,15 @@ sub do_bots_db_schema_drop {
print get_mysql_result_from_file("db_update/drop_bots.sql");
print "[Database] Removing bot database tables...\n";
print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';");
if (get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db) {
print get_mysql_result("DELETE FROM `commands` WHERE `command` LIKE 'bot';");
}
if (get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && $db) {
print get_mysql_result("DELETE FROM `command_settings` WHERE `command` LIKE 'bot';");
}
if (get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db) {
print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;");
@@ -2049,6 +2043,70 @@ sub modify_db_for_bots {
}
print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`);");
if (get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && get_mysql_result("SELECT `command` FROM `command_settings` WHERE `command` LIKE 'bot'") eq "" && $db) {
print get_mysql_result("INSERT INTO `command_settings` VALUES ('bot', '0', '');");
}
if (get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && get_mysql_result("SELECT `command` FROM `commands` WHERE `command` LIKE 'bot'") eq "" && $db) {
print get_mysql_result("INSERT INTO `commands` VALUES ('bot', '0');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:FinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:GroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:ManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpawnLimit', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\\\'s (Anita_Thrall.pl) Bot Spell Scriber quests.');");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount'") ne "" && $db) {
print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount';");
}
if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit'") eq "" && $db) {
print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:SpawnLimit', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid');");
}
convert_existing_bot_data();
}
@@ -2147,49 +2205,47 @@ sub convert_existing_bot_data {
}
}
sub get_main_db_version {
$main_local_db_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
return $main_local_db_version;
}
sub get_bots_db_version {
#::: Check if bots_version column exists...
if (get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db) {
print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;");
print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n";
}
$bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1"));
return $bots_local_db_version;
}
#::: Safe for call from world startup or menu option
sub bots_db_management {
if ($OS eq "Windows") {
@db_version = split(': ', `world db_version`);
}
if ($OS eq "Linux") {
@db_version = split(': ', `./world db_version`);
}
#::: Main Binary Database version
$binary_database_version = trim($db_version[2]);
#::: If we have stale data from main db run
if ($db_run_stage > 0 && $bots_db_management == 0) {
clear_database_runs();
}
#::: Main Binary Database version
$binary_database_version = trim($db_version[2]);
if ($binary_database_version == 0) {
print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n";
return;
}
$local_database_version = get_bots_db_version();
#::: Set on flag for running bot updates...
$bots_db_management = 1;
if ($local_database_version > $binary_database_version) {
print "[Update] Bots database version is ahead of current binaries...\n";
return;
}
$bots_local_db_version = get_bots_db_version();
$local_database_version = $bots_local_db_version;
run_database_check();
}
#::: Safe for call from world startup or menu option
sub main_db_management {
#::: If we have stale data from bots db run
if ($db_run_stage > 0 && $bots_db_management == 1) {
@@ -2198,15 +2254,8 @@ sub main_db_management {
#::: Main Binary Database version
$binary_database_version = trim($db_version[1]);
$local_database_version = get_main_db_version();
$bots_db_management = 0;
if ($local_database_version > $binary_database_version) {
print "[Update] Database version is ahead of current binaries...\n";
return;
}
run_database_check();
}
@@ -2216,70 +2265,148 @@ sub clear_database_runs {
%m_d = ();
#::: Clear updates...
@total_updates = ();
#::: Clear stage
$db_run_stage = 0;
}
#::: Responsible for Database Upgrade Routines
sub run_database_check {
if (!$db) {
print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n";
return;
}
#::: Pull down bots database manifest
if ($bots_db_management == 1) {
print "[Database] Retrieving latest bots database manifest...\n";
get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt");
}
#::: Pull down mainstream database manifest
else {
print "[Database] Retrieving latest database manifest...\n";
get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt");
}
#::: Parse manifest
print "[Database] Reading manifest...\n";
use Data::Dumper;
open(FILE, "db_update/db_update_manifest.txt");
while (<FILE>) {
chomp;
$o = $_;
if ($o =~ /#/i) {
next;
if (!@total_updates) {
#::: Pull down bots database manifest
if ($bots_db_management == 1) {
print "[Database] Retrieving latest bots database manifest...\n";
get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt");
}
#::: Pull down mainstream database manifest
else {
print "[Database] Retrieving latest database manifest...\n";
get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt");
}
@manifest = split('\|', $o);
$m_d{$manifest[0]} = [ @manifest ];
}
#::: Run 2 - Running pending updates...
if (@total_updates || $db_run_stage == 1) {
@total_updates = sort @total_updates;
foreach my $val (@total_updates) {
$file_name = trim($m_d{$val}[1]);
print "[Database] Running Update: " . $val . " - " . $file_name . "\n";
print get_mysql_result_from_file("db_update/$file_name");
print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val");
if ($bots_db_management == 1 && $val == 9000) {
modify_db_for_bots();
}
if ($val == 9138) {
fix_quest_factions();
}
}
$db_run_stage = 2;
}
#::: Run 1 - Initial checking of needed updates...
else {
print "[Database] Reading manifest...\n";
use Data::Dumper;
open(FILE, "db_update/db_update_manifest.txt");
while (<FILE>) {
chomp;
$o = $_;
if ($o =~ /#/i) {
next;
}
@manifest = split('\|', $o);
$m_d{$manifest[0]} = [ @manifest ];
}
#::: Setting Manifest stage...
$db_run_stage = 1;
}
@total_updates = ();
#::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest...
if ($local_database_version >= 9000) {
$revision_check = $local_database_version + 1;
$revision_check = $local_database_version;
}
else {
#::: This does not negatively affect bots
$revision_check = 1000;
if (get_mysql_result("SHOW TABLES LIKE 'character_data'") ne "") {
$revision_check = 8999;
}
}
@total_updates = ();
#::: Fetch and register sqls for this database update cycle
#::: Iterate through Manifest backwards from binary version down to local version...
for ($i = $revision_check; $i <= $binary_database_version; $i++) {
if (!defined($m_d{$i}[0])) {
next;
}
$file_name = trim($m_d{$i}[1]);
print "[Database] fetching update: " . $i . " '" . $file_name . "' \n";
fetch_missing_db_update($i, $file_name);
push(@total_updates, $i);
$file_name = trim($m_d{$i}[1]);
$query_check = trim($m_d{$i}[2]);
$match_type = trim($m_d{$i}[3]);
$match_text = trim($m_d{$i}[4]);
#::: Match type update
if ($match_type eq "contains") {
if (trim(get_mysql_result($query_check)) =~ /$match_text/i) {
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
fetch_missing_db_update($i, $file_name);
push(@total_updates, $i);
}
else {
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
}
print_match_debug();
print_break();
}
if ($match_type eq "missing") {
if (get_mysql_result($query_check) =~ /$match_text/i) {
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
next;
}
else {
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
fetch_missing_db_update($i, $file_name);
push(@total_updates, $i);
}
print_match_debug();
print_break();
}
if ($match_type eq "empty") {
if (get_mysql_result($query_check) eq "") {
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
fetch_missing_db_update($i, $file_name);
push(@total_updates, $i);
}
else {
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
}
print_match_debug();
print_break();
}
if ($match_type eq "not_empty") {
if (get_mysql_result($query_check) ne "") {
print "[Database] missing update: " . $i . " '" . $file_name . "' \n";
fetch_missing_db_update($i, $file_name);
push(@total_updates, $i);
}
else {
print "[Database] has update (" . $i . ") '" . $file_name . "' \n";
}
print_match_debug();
print_break();
}
}
if (scalar(@total_updates) == 0) {
print "\n";
if (scalar(@total_updates) == 0 && $db_run_stage == 2) {
print "[Database] No updates need to be run...\n";
if ($bots_db_management == 1) {
print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n";
@@ -2289,106 +2416,24 @@ sub run_database_check {
print "[Database] Setting Database to Binary Version (" . $binary_database_version . ") if not already...\n\n";
get_mysql_result("UPDATE db_version SET version = $binary_database_version ");
}
clear_database_runs();
return;
}
#::: Execute pending updates
@total_updates = sort @total_updates;
foreach my $val (@total_updates) {
$file_name = trim($m_d{$val}[1]);
$query_check = trim($m_d{$val}[2]);
$match_type = trim($m_d{$val}[3]);
$match_text = trim($m_d{$val}[4]);
#::: Match type update
if ($match_type eq "contains") {
if (trim(get_mysql_result($query_check)) =~ /$match_text/i) {
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
print get_mysql_result_from_file("db_update/$file_name");
}
else {
print "[Database] Has update [" . $val . "]:[" . $file_name . "]\n";
}
print_match_debug();
print_break();
}
if ($match_type eq "missing") {
if (get_mysql_result($query_check) =~ /$match_text/i) {
print "[Database] Has update [" . $val . "]:[" . $file_name . "]\n";
}
else {
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
print get_mysql_result_from_file("db_update/$file_name");
}
print_match_debug();
print_break();
}
if ($match_type eq "empty") {
if (get_mysql_result($query_check) eq "") {
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
print get_mysql_result_from_file("db_update/$file_name");
}
else {
print "[Database] Has update [" . $val . "]:[" . $file_name . "' \n";
}
print_match_debug();
print_break();
}
if ($match_type eq "not_empty") {
if (get_mysql_result($query_check) ne "") {
print "[Database] Applying update [" . $val . "]:[" . $file_name . "]\n";
print get_mysql_result_from_file("db_update/$file_name");
}
else {
print "[Database] Has update [" . $val . "]:[" . $file_name . "]\n";
}
print_match_debug();
print_break();
}
if ($bots_db_management == 1) {
print get_mysql_result("UPDATE db_version SET bots_version = $val WHERE bots_version < $val");
if ($val == 9000) {
modify_db_for_bots();
}
}
else {
print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val");
if ($val == 9138) {
fix_quest_factions();
}
}
}
if ($bots_db_management == 1) {
print "[Database] Bots database update cycle complete at version [" . get_bots_db_version() . "]\n";
}
else {
print "[Database] Mainstream database update cycle complete at version [" . get_main_db_version() . "]\n";
}
}
sub fetch_missing_db_update {
$db_update = $_[0];
$update_file = $_[1];
if ($bots_db_management == 1) {
if ($db_update >= 9000) {
if ($db_update >= 9000) {
if ($bots_db_management == 1) {
get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . "");
}
}
else {
if ($db_update >= 9000) {
else {
get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . "");
}
elsif ($db_update >= 5000 && $db_update <= 9000) {
get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . "");
}
}
elsif ($db_update >= 5000 && $db_update <= 9000) {
get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . "");
}
}
+57
View File
@@ -0,0 +1,57 @@
account
account_ip
account_flags
account_rewards
adventure_details
adventure_stats
buyer
char_recipe_list
character_activities
character_alt_currency
character_alternate_abilities
character_auras
character_bandolier
character_bind
character_buffs
character_corpse_items
character_corpses
character_currency
character_data
character_disciplines
character_enabledtasks
character_inspect_messages
character_item_recast
character_languages
character_leadership_abilities
character_material
character_memmed_spells
character_pet_buffs
character_pet_info
character_pet_inventory
character_potionbelt
character_skills
character_spells
character_tasks
character_tribute
completed_tasks
data_buckets
faction_values
friends
guild_bank
guild_members
guild_ranks
guild_relations
guilds
instance_list_player
inventory
inventory_snapshots
keyring
mail
player_titlesets
quest_globals
sharedbank
timers
titles
trader
trader_audit
zone_flags"
+6
View File
@@ -0,0 +1,6 @@
command_settings
inventory_versions
launcher
rule_sets
rule_values
variables
-6
View File
@@ -400,12 +400,6 @@
9144|2019_11_09_logsys_description_update.sql|SELECT * FROM db_version WHERE version >= 9143|empty|
9145|2019_12_24_banned_ips_update.sql|SHOW TABLES LIKE 'Banned_IPs'|not_empty|
9146|2020_01_10_character_soft_deletes.sql|SHOW COLUMNS FROM `character_data` LIKE 'deleted_at'|empty|
9147|2020_01_24_grid_centerpoint_wp.sql|SHOW COLUMNS FROM `grid_entries` LIKE 'centerpoint'|empty|
9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty|
9149|2020_02_06_globalloot.sql|SHOW COLUMNS FROM `global_loot` LIKE 'hot_zone'|empty|
9150|2020_02_06_aa_reset_on_death.sql|SHOW COLUMNS FROM `aa_ability` LIKE 'reset_on_death'|empty|
9151|2020_03_05_npc_always_aggro.sql|SHOW COLUMNS FROM `npc_types` LIKE 'always_aggro'|empty|
9152|2020_03_09_convert_myisam_to_innodb.sql|SELECT * FROM db_version WHERE version >= 9152|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not
@@ -25,7 +25,6 @@
9024|2019_06_27_bots_pet_get_lost.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'petgetlost'|empty|
9025|2019_08_26_bots_owner_option_spawn_message.sql|SELECT * FROM db_version WHERE bots_version >= 9025|empty|
9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty|
9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not
@@ -1,24 +0,0 @@
DROP VIEW IF EXISTS `vw_bot_character_mobs`;
-- Views
CREATE VIEW `vw_bot_character_mobs` AS
SELECT
_utf8'C' AS mob_type,
c.`id`,
c.`name`,
c.`class`,
c.`level`,
c.`last_login`,
c.`zone_id`,
c.`deleted_at`
FROM `character_data` AS c
UNION ALL
SELECT _utf8'B' AS mob_type,
b.`bot_id` AS id,
b.`name`,
b.`class`,
b.`level`,
b.`last_spawn` AS last_login,
b.`zone_id`,
NULL AS `deleted_at`
FROM `bot_data` AS b;
@@ -1,12 +0,0 @@
-- Run this to un-reserve deleted characters
UPDATE
character_data
SET
name = SUBSTRING(
CONCAT(name, '-deleted-', UNIX_TIMESTAMP()),
1,
64
)
WHERE
deleted_at IS NOT NULL
AND name NOT LIKE '%-deleted-%';
@@ -1,2 +0,0 @@
alter table grid_entries add column `centerpoint` tinyint(4) not null default 0;
alter table spawngroup add column `wp_spawns` tinyint(1) unsigned not null default 0;
@@ -1 +0,0 @@
ALTER TABLE `character_corpses` ADD COLUMN `guild_consent_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `time_of_death`;
@@ -1,2 +0,0 @@
ALTER TABLE `aa_ability` ADD `reset_on_death` TINYINT(4) NOT NULL DEFAULT '0';
UPDATE `aa_ability` SET `reset_on_death` = '1' WHERE `id` = 6001;
@@ -1,2 +0,0 @@
ALTER TABLE `global_loot` ADD `hot_zone` TINYINT NULL;
@@ -1 +0,0 @@
ALTER TABLE `npc_types` ADD COLUMN `always_aggro` tinyint(1) NOT NULL DEFAULT 0;
@@ -1,95 +0,0 @@
ALTER TABLE `account_flags` ENGINE=InnoDB;
ALTER TABLE `account_ip` ENGINE=InnoDB;
ALTER TABLE `account` ENGINE=InnoDB;
ALTER TABLE `adventure_template_entry_flavor` ENGINE=InnoDB;
ALTER TABLE `adventure_template_entry` ENGINE=InnoDB;
ALTER TABLE `altadv_vars` ENGINE=InnoDB;
ALTER TABLE `alternate_currency` ENGINE=InnoDB;
ALTER TABLE `banned_ips` ENGINE=InnoDB;
ALTER TABLE `base_data` ENGINE=InnoDB;
ALTER TABLE `blocked_spells` ENGINE=InnoDB;
ALTER TABLE `buyer` ENGINE=InnoDB;
ALTER TABLE `char_create_combinations` ENGINE=InnoDB;
ALTER TABLE `char_create_point_allocations` ENGINE=InnoDB;
ALTER TABLE `character_activities` ENGINE=InnoDB;
ALTER TABLE `character_enabledtasks` ENGINE=InnoDB;
ALTER TABLE `character_tasks` ENGINE=InnoDB;
ALTER TABLE `chatchannels` ENGINE=InnoDB;
ALTER TABLE `completed_tasks` ENGINE=InnoDB;
ALTER TABLE `damageshieldtypes` ENGINE=InnoDB;
ALTER TABLE `discovered_items` ENGINE=InnoDB;
ALTER TABLE `eqtime` ENGINE=InnoDB;
ALTER TABLE `eventlog` ENGINE=InnoDB;
ALTER TABLE `faction_list_mod` ENGINE=InnoDB;
ALTER TABLE `faction_list` ENGINE=InnoDB;
ALTER TABLE `faction_values` ENGINE=InnoDB;
ALTER TABLE `friends` ENGINE=InnoDB;
ALTER TABLE `goallists` ENGINE=InnoDB;
ALTER TABLE `guild_bank` ENGINE=InnoDB;
ALTER TABLE `guild_members` ENGINE=InnoDB;
ALTER TABLE `guild_ranks` ENGINE=InnoDB;
ALTER TABLE `guild_relations` ENGINE=InnoDB;
ALTER TABLE `guilds` ENGINE=InnoDB;
ALTER TABLE `hackers` ENGINE=InnoDB;
ALTER TABLE `horses` ENGINE=InnoDB;
ALTER TABLE `inventory_versions` ENGINE=InnoDB;
ALTER TABLE `item_tick` ENGINE=InnoDB;
ALTER TABLE `items` ENGINE=InnoDB;
ALTER TABLE `keyring` ENGINE=InnoDB;
ALTER TABLE `launcher_zones` ENGINE=InnoDB;
ALTER TABLE `launcher` ENGINE=InnoDB;
ALTER TABLE `ldon_trap_entries` ENGINE=InnoDB;
ALTER TABLE `ldon_trap_templates` ENGINE=InnoDB;
ALTER TABLE `lfguild` ENGINE=InnoDB;
ALTER TABLE `lootdrop_entries` ENGINE=InnoDB;
ALTER TABLE `lootdrop` ENGINE=InnoDB;
ALTER TABLE `loottable_entries` ENGINE=InnoDB;
ALTER TABLE `loottable` ENGINE=InnoDB;
ALTER TABLE `mail` ENGINE=InnoDB;
ALTER TABLE `merc_armorinfo` ENGINE=InnoDB;
ALTER TABLE `merc_buffs` ENGINE=InnoDB;
ALTER TABLE `merc_inventory` ENGINE=InnoDB;
ALTER TABLE `merc_merchant_entries` ENGINE=InnoDB;
ALTER TABLE `merc_merchant_template_entries` ENGINE=InnoDB;
ALTER TABLE `merc_merchant_templates` ENGINE=InnoDB;
ALTER TABLE `merc_name_types` ENGINE=InnoDB;
ALTER TABLE `merc_npc_types` ENGINE=InnoDB;
ALTER TABLE `merc_spell_list_entries` ENGINE=InnoDB;
ALTER TABLE `merc_spell_lists` ENGINE=InnoDB;
ALTER TABLE `merc_stance_entries` ENGINE=InnoDB;
ALTER TABLE `merc_stats` ENGINE=InnoDB;
ALTER TABLE `merc_subtypes` ENGINE=InnoDB;
ALTER TABLE `merc_templates` ENGINE=InnoDB;
ALTER TABLE `merc_types` ENGINE=InnoDB;
ALTER TABLE `merc_weaponinfo` ENGINE=InnoDB;
ALTER TABLE `mercs` ENGINE=InnoDB;
ALTER TABLE `name_filter` ENGINE=InnoDB;
ALTER TABLE `npc_types` ENGINE=InnoDB;
ALTER TABLE `object_contents` ENGINE=InnoDB;
ALTER TABLE `petitions` ENGINE=InnoDB;
ALTER TABLE `pets_equipmentset_entries` ENGINE=InnoDB;
ALTER TABLE `pets_equipmentset` ENGINE=InnoDB;
ALTER TABLE `player_titlesets` ENGINE=InnoDB;
ALTER TABLE `proximities` ENGINE=InnoDB;
ALTER TABLE `races` ENGINE=InnoDB;
ALTER TABLE `raid_details` ENGINE=InnoDB;
ALTER TABLE `raid_leaders` ENGINE=InnoDB;
ALTER TABLE `raid_members` ENGINE=InnoDB;
ALTER TABLE `rule_sets` ENGINE=InnoDB;
ALTER TABLE `rule_values` ENGINE=InnoDB;
ALTER TABLE `saylink` ENGINE=InnoDB;
ALTER TABLE `sharedbank` ENGINE=InnoDB;
ALTER TABLE `skill_caps` ENGINE=InnoDB;
ALTER TABLE `spell_globals` ENGINE=InnoDB;
ALTER TABLE `spells_new` ENGINE=InnoDB;
ALTER TABLE `task_activities` ENGINE=InnoDB;
ALTER TABLE `tasks` ENGINE=InnoDB;
ALTER TABLE `tasksets` ENGINE=InnoDB;
ALTER TABLE `timers` ENGINE=InnoDB;
ALTER TABLE `titles` ENGINE=InnoDB;
ALTER TABLE `trader_audit` ENGINE=InnoDB;
ALTER TABLE `trader` ENGINE=InnoDB;
ALTER TABLE `tradeskill_recipe_entries` ENGINE=InnoDB;
ALTER TABLE `tradeskill_recipe` ENGINE=InnoDB;
ALTER TABLE `variables` ENGINE=InnoDB;
ALTER TABLE `veteran_reward_templates` ENGINE=InnoDB;
-71
View File
@@ -1,71 +0,0 @@
#!/usr/bin/env bash
# Run from the context of server directory
world_path=""
#############################################
# world path
#############################################
if [ -d "bin" ]
then
world_path="bin/"
fi
world_bin="${world_path}world"
echo "World path is [$world_path] bin is [$world_bin]"
#############################################
# dump
#############################################
dump_path=/tmp/peq-dump/
echo "Generating dump path [${dump_path}]"
rm -rf ${dump_path}
mkdir -p ${dump_path}
#############################################
# generate "drop_" table files
#############################################
echo "Generating [drop_*] table exports..."
bash -c "${world_bin} database:dump --content-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_content.sql"
bash -c "${world_bin} database:dump --login-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_login.sql"
bash -c "${world_bin} database:dump --player-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_player.sql"
bash -c "${world_bin} database:dump --system-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_system.sql"
bash -c "${world_bin} database:dump --state-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_state.sql"
bash -c "${world_bin} database:dump --query-serv-tables --drop-table-syntax-only --dump-output-to-console > ${dump_path}drop_tables_queryserv.sql"
#############################################
# generate "create_" table files
#############################################
echo "Generating [create_*] table exports..."
# structure only
bash -c "${world_bin} database:dump --login-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_login.sql"
bash -c "${world_bin} database:dump --player-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_player.sql"
bash -c "${world_bin} database:dump --state-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_state.sql"
echo 'REPLACE INTO `instance_list` VALUES (1,25,1,1,0,0,1),(2,25,2,1,0,0,1),(3,151,1,1,0,0,1),(4,114,1,1,0,0,1),(5,344,1,1,0,0,1),(6,202,0,1,0,0,1);' >> "${dump_path}create_tables_state.sql"
bash -c "${world_bin} database:dump --query-serv-tables --table-structure-only --dump-output-to-console | sed 's/ AUTO_INCREMENT=[0-9]*\b//g' > ${dump_path}create_tables_queryserv.sql"
# with content
bash -c "${world_bin} database:dump --content-tables --dump-output-to-console > ${dump_path}create_tables_content.sql"
bash -c "${world_bin} database:dump --system-tables --dump-output-to-console > ${dump_path}create_tables_system.sql"
#############################################
# "all" exports
#############################################
bash -c "cd ${dump_path} && ls * | grep create | sed 's/.*/source &;/' > create_all_tables.sql"
bash -c "cd ${dump_path} && ls * | grep drop | sed 's/.*/source &;/' > drop_all_tables.sql"
#############################################
# zip
#############################################
human_date=$(date +"%B-%d-%Y" | tr '[:upper:]' '[:lower:]')
echo "Compressing..."
bash -c "cd /tmp/ && rm -rf peq-latest.zip && zip peq-latest.zip peq-dump/* && mv ${dump_path}peq-latest.zip /tmp/peq-latest.zip"
echo "Cleaning up..."
rm -rf ${dump_path}
echo "Dump located [/tmp/peq-latest.zip]"
+113
View File
@@ -0,0 +1,113 @@
aa_ability
aa_actions
aa_effects
aa_rank_effects
aa_rank_prereqs
aa_ranks
aa_required_level_cost
adventure_template
adventure_template_entry
adventure_template_entry_flavor
altadv_vars
alternate_currency
auras
base_data
blocked_spells
books
bug_reports
char_create_combinations
char_create_point_allocations
class_skill
damageshieldtypes
data_buckets
db_str
doors
eqtime
faction_base_data
faction_list
faction_list_mod
fear_hints
fishing
forage
global_loot
goallists
graveyard
grid
grid_entries
ground_spawns
horses
instance_list
items
ip_exemptions
ldon_trap_entries
ldon_trap_templates
level_exp_mods
logsys_categories
lootdrop
lootdrop_entries
loottable
loottable_entries
merc_armorinfo
merc_buffs
merc_inventory
merc_merchant_entries
merc_merchant_template_entries
merc_merchant_templates
merc_name_types
merc_npc_types
merc_spell_list_entries
merc_spell_lists
merc_stance_entries
merc_stats
merc_subtypes
merc_templates
merc_types
merc_weaponinfo
merchantlist
mercs
name_filter
npc_emotes
npc_faction
npc_faction_entries
npc_scale_global_base
npc_spells
npc_spells_effects
npc_spells_effects_entries
npc_spells_entries
npc_types
npc_types_metadata
npc_types_tint
object
perl_event_export_settings
pets
pets_equipmentset
pets_equipmentset_entries
profanity_list
proximities
races
saylink
skill_caps
spawn2
spawn_condition_values
spawn_conditions
spawn_events
spawnentry
spawngroup
spells_new
start_zones
starting_items
task_activities
tasks
tasksets
titles
tradeskill_recipe
tradeskill_recipe_entries
traps
tribute_levels
tributes
veteran_reward_templates
zone
zone_points
zone_server
zone_state_dump
zoneserver_auth
+94
View File
@@ -0,0 +1,94 @@
aa_timers
account
account_flags
account_ip
account_rewards
adventure_details
adventure_members
adventure_stats
banned_ips
bugs
buyer
char_recipe_list
character_activities
character_alt_currency
character_alternate_abilities
character_auras
character_bandolier
character_bind
character_buffs
character_corpse_items
character_corpses
character_currency
character_data
character_disciplines
character_enabledtasks
character_inspect_messages
character_item_recast
character_languages
character_leadership_abilities
character_material
character_memmed_spells
character_pet_buffs
character_pet_info
character_pet_inventory
character_potionbelt
character_skills
character_spells
character_tasks
character_tribute
chatchannels
completed_tasks
discovered_items
eventlog
faction_values
friends
gm_ips
group_id
group_leaders
guild_bank
guild_members
guild_ranks
guild_relations
guilds
hackers
instance_list_player
inventory
inventory_snapshots
item_tick
keyring
launcher_zones
lfguild
mail
merchantlist_temp
object_contents
petitions
player_titlesets
qs_merchant_transaction_record
qs_merchant_transaction_record_entries
qs_player_aa_rate_hourly
qs_player_delete_record
qs_player_delete_record_entries
qs_player_events
qs_player_handin_record
qs_player_handin_record_entries
qs_player_move_record
qs_player_move_record_entries
qs_player_npc_kill_record
qs_player_npc_kill_record_entries
qs_player_speech
qs_player_trade_record
qs_player_trade_record_entries
quest_globals
raid_details
raid_leaders
raid_members
reports
respawn_times
sharedbank
spell_buckets
spell_globals
timers
trader
trader_audit
zone_flags
+7 -36
View File
@@ -802,9 +802,9 @@ void ConsoleIpLookup(
const std::vector<std::string> &args
)
{
if (!args.empty()) {
if (args.size() > 0) {
WorldConsoleTCPConnection console_connection(connection);
client_list.SendCLEList(connection->Admin(), nullptr, &console_connection, args[0].c_str());
client_list.SendCLEList(connection->Admin(), 0, &console_connection, args[0].c_str());
}
}
@@ -855,34 +855,6 @@ void ConsoleReloadWorld(
safe_delete(pack);
}
/**
* @param connection
* @param command
* @param args
*/
void ConsoleReloadZoneQuests(
EQ::Net::ConsoleServerConnection *connection,
const std::string &command,
const std::vector<std::string> &args
)
{
if (args.empty()) {
connection->SendLine("[zone_short_name] required as argument");
return;
}
std::string zone_short_name = args[0];
connection->SendLine(fmt::format("Reloading Zone [{}]...", zone_short_name));
auto pack = new ServerPacket(ServerOP_HotReloadQuests, sizeof(HotReloadQuestsStruct));
auto *hot_reload_quests = (HotReloadQuestsStruct *) pack->pBuffer;
strn0cpy(hot_reload_quests->zone_short_name, (char *) zone_short_name.c_str(), 200);
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
/**
* @param connection
* @param command
@@ -920,19 +892,18 @@ void RegisterConsoleFunctions(std::unique_ptr<EQ::Net::ConsoleServer>& console)
console->RegisterCall("md5", 50, "md5", std::bind(ConsoleMd5, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("ooc", 50, "ooc [message]", std::bind(ConsoleOOC, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("reloadworld", 200, "reloadworld", std::bind(ConsoleReloadWorld, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("reloadzonequests", 200, "reloadzonequests [zone_short_name]", std::bind(ConsoleReloadZoneQuests, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("setpass", 200, "setpass [account_name] [new_password]", std::bind(ConsoleSetPass, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("setpass", 200, "setpass [accountname] [newpass]", std::bind(ConsoleSetPass, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("signalcharbyname", 50, "signalcharbyname charname ID", std::bind(ConsoleSignalCharByName, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("tell", 50, "tell [name] [message]", std::bind(ConsoleTell, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("unlock", 150, "unlock", std::bind(ConsoleUnlock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("uptime", 50, "uptime [zone_server_id]", std::bind(ConsoleUptime, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("uptime", 50, "uptime [zoneID#]", std::bind(ConsoleUptime, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("version", 50, "version", std::bind(ConsoleVersion, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("who", 50, "who", std::bind(ConsoleWho, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("whoami", 50, "whoami", std::bind(ConsoleWhoami, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("worldshutdown", 200, "worldshutdown", std::bind(ConsoleWorldShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("zonebootup", 150, "zonebootup [zone_server_id] [zone_short_name]", std::bind(ConsoleZoneBootup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("zonelock", 150, "zonelock [list|lock|unlock] [zone_short_name]", std::bind(ConsoleZoneLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("zoneshutdown", 150, "zoneshutdown [zone_short_name or zone_server_id]", std::bind(ConsoleZoneShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("zonebootup", 150, "zonebootup [ZoneServerID] [zonename]", std::bind(ConsoleZoneBootup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("zonelock", 150, "zonelock [list|lock|unlock] [zonename]", std::bind(ConsoleZoneLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("zoneshutdown", 150, "zoneshutdown [zonename or ZoneServerID]", std::bind(ConsoleZoneShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("zonestatus", 50, "zonestatus", std::bind(ConsoleZoneStatus, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));console->RegisterCall("ping", 50, "ping", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("quit", 50, "quit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("exit", 50, "exit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
-1
View File
@@ -415,7 +415,6 @@ int main(int argc, char** argv) {
RegisterConsoleFunctions(console);
}
zoneserver_list.Init();
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
server_connection.reset(new EQ::Net::ServertalkServer());
+11 -30
View File
@@ -6,38 +6,29 @@
#include "../common/misc_functions.h"
#include "../common/md5.h"
#include "../common/packet_dump.h"
#include "../common/event/timer.h"
UCSConnection::UCSConnection()
{
connection = 0;
Stream = 0;
}
void UCSConnection::SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> inStream)
{
if (inStream && connection && connection->Handle()) {
if (Stream && Stream->Handle())
{
LogInfo("Incoming UCS Connection while we were already connected to a UCS");
connection->Handle()->Disconnect();
}
connection = inStream;
if (connection) {
connection->OnMessage(
std::bind(
&UCSConnection::ProcessPacket,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
Stream->Handle()->Disconnect();
}
m_keepalive.reset(new EQ::Timer(5000, true, std::bind(&UCSConnection::OnKeepAlive, this, std::placeholders::_1)));
Stream = inStream;
if (Stream) {
Stream->OnMessage(std::bind(&UCSConnection::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
}
}
void UCSConnection::ProcessPacket(uint16 opcode, EQ::Net::Packet &p)
{
if (!connection)
if (!Stream)
return;
ServerPacket tpack(opcode, p);
@@ -69,10 +60,10 @@ void UCSConnection::ProcessPacket(uint16 opcode, EQ::Net::Packet &p)
void UCSConnection::SendPacket(ServerPacket* pack)
{
if (!connection)
if (!Stream)
return;
connection->SendPacket(pack);
Stream->SendPacket(pack);
}
void UCSConnection::SendMessage(const char *From, const char *Message)
@@ -87,13 +78,3 @@ void UCSConnection::SendMessage(const char *From, const char *Message)
SendPacket(pack);
safe_delete(pack);
}
void UCSConnection::OnKeepAlive(EQ::Timer *t)
{
if (!connection) {
return;
}
ServerPacket pack(ServerOP_KeepAlive, 0);
connection->SendPacket(&pack);
}
+3 -10
View File
@@ -4,7 +4,6 @@
#include "../common/types.h"
#include "../common/net/servertalk_server_connection.h"
#include "../common/servertalk.h"
#include "../common/event/timer.h"
#include <memory>
class UCSConnection
@@ -14,17 +13,11 @@ public:
void SetConnection(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection);
void ProcessPacket(uint16 opcode, EQ::Net::Packet &p);
void SendPacket(ServerPacket* pack);
void Disconnect() { if(connection && connection->Handle()) connection->Handle()->Disconnect(); }
void Disconnect() { if(Stream && Stream->Handle()) Stream->Handle()->Disconnect(); }
void SendMessage(const char *From, const char *Message);
private:
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
/**
* Keepalive
*/
std::unique_ptr<EQ::Timer> m_keepalive;
void OnKeepAlive(EQ::Timer *t);
inline std::string GetIP() const { return (Stream && Stream->Handle()) ? Stream->Handle()->RemoteIP() : 0; }
std::shared_ptr<EQ::Net::ServertalkServerConnection> Stream;
};
#endif /*UCS_H_*/
+1 -70
View File
@@ -24,7 +24,6 @@
#include "../common/version.h"
#include "worlddb.h"
#include "../common/database_schema.h"
#include "../common/database/database_dump_service.h"
namespace WorldserverCommandHandler {
@@ -52,7 +51,6 @@ namespace WorldserverCommandHandler {
function_map["database:version"] = &WorldserverCommandHandler::DatabaseVersion;
function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus;
function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema;
function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump;
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
}
@@ -147,7 +145,7 @@ namespace WorldserverCommandHandler {
*/
void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description)
{
description = "Displays server database schema";
description = "Displays server database schema";
if (cmd[{"-h", "--help"}]) {
return;
@@ -204,71 +202,4 @@ namespace WorldserverCommandHandler {
std::cout << payload.str() << std::endl;
}
/**
* @param argc
* @param argv
* @param cmd
* @param description
*/
void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description)
{
description = "Dumps server database tables";
if (cmd[{"-h", "--help"}]) {
return;
}
std::vector<std::string> arguments = {};
std::vector<std::string> options = {
"--all",
"--content-tables",
"--login-tables",
"--player-tables",
"--state-tables",
"--system-tables",
"--query-serv-tables",
"--table-structure-only",
"--table-lock",
"--dump-path=",
"--dump-output-to-console",
"--drop-table-syntax-only",
"--compress"
};
if (argc < 3) {
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
return;
}
auto database_dump_service = new DatabaseDumpService();
bool dump_all = cmd[{"-a", "--all"}];
if (!cmd("--dump-path").str().empty()) {
database_dump_service->SetDumpPath(cmd("--dump-path").str());
}
/**
* Set Option
*/
database_dump_service->SetDumpContentTables(cmd[{"--content-tables"}] || dump_all);
database_dump_service->SetDumpLoginServerTables(cmd[{"--login-tables"}] || dump_all);
database_dump_service->SetDumpPlayerTables(cmd[{"--player-tables"}] || dump_all);
database_dump_service->SetDumpStateTables(cmd[{"--state-tables"}] || dump_all);
database_dump_service->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all);
database_dump_service->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all);
database_dump_service->SetDumpAllTables(dump_all);
database_dump_service->SetDumpWithNoData(cmd[{"--table-structure-only"}]);
database_dump_service->SetDumpTableLock(cmd[{"--table-lock"}]);
database_dump_service->SetDumpWithCompression(cmd[{"--compress"}]);
database_dump_service->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]);
database_dump_service->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]);
/**
* Dump
*/
database_dump_service->Dump();
}
}
-1
View File
@@ -30,7 +30,6 @@ namespace WorldserverCommandHandler {
void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description);
void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description);
void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description);
void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description);
};
+23 -20
View File
@@ -39,6 +39,7 @@ ZSList::ZSList()
{
NextID = 1;
CurGroupID = 1;
LastAllocatedPort = 0;
memset(pLockedZones, 0, sizeof(pLockedZones));
m_tick.reset(new EQ::Timer(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1)));
@@ -75,12 +76,7 @@ void ZSList::Remove(const std::string &uuid)
auto iter = zone_server_list.begin();
while (iter != zone_server_list.end()) {
if ((*iter)->GetUUID().compare(uuid) == 0) {
auto port = (*iter)->GetCPort();
zone_server_list.erase(iter);
if (port != 0) {
m_ports_free.push_back(port);
}
return;
}
iter++;
@@ -243,14 +239,6 @@ bool ZSList::SetLockedZone(uint16 iZoneID, bool iLock) {
return false;
}
void ZSList::Init()
{
const WorldConfig* Config = WorldConfig::get();
for (uint16 i = Config->ZonePortLow; i <= Config->ZonePortHigh; ++i) {
m_ports_free.push_back(i);
}
}
bool ZSList::IsZoneLocked(uint16 iZoneID) {
for (auto &zone : pLockedZones) {
if (zone == iZoneID)
@@ -589,15 +577,30 @@ void ZSList::RebootZone(const char* ip1, uint16 port, const char* ip2, uint32 sk
safe_delete_array(tmp);
}
uint16 ZSList::GetAvailableZonePort()
uint16 ZSList::GetAvailableZonePort()
{
if (m_ports_free.empty()) {
return 0;
}
const WorldConfig *Config = WorldConfig::get();
int i;
uint16 port = 0;
auto first = m_ports_free.front();
m_ports_free.pop_front();
return first;
if (LastAllocatedPort == 0)
i = Config->ZonePortLow;
else
i = LastAllocatedPort + 1;
while (i != LastAllocatedPort && port == 0) {
if (i>Config->ZonePortHigh)
i = Config->ZonePortLow;
if (!FindByPort(i)) {
port = i;
break;
}
i++;
}
LastAllocatedPort = port;
return port;
}
uint32 ZSList::TriggerBootup(uint32 iZoneID, uint32 iInstanceID) {
+2 -3
View File
@@ -7,7 +7,6 @@
#include "../common/event/timer.h"
#include <vector>
#include <memory>
#include <deque>
class WorldTCPConnection;
class ServerPacket;
@@ -23,7 +22,6 @@ public:
ZSList();
~ZSList();
void Init();
bool IsZoneLocked(uint16 iZoneID);
bool SendPacket(ServerPacket *pack);
bool SendPacket(uint32 zoneid, ServerPacket *pack);
@@ -75,7 +73,8 @@ private:
uint32 NextID;
uint16 pLockedZones[MaxLockedZones];
uint32 CurGroupID;
std::deque<uint16> m_ports_free;
uint16 LastAllocatedPort;
std::unique_ptr<EQ::Timer> m_tick;
std::unique_ptr<EQ::Timer> m_keepalive;
+99 -31
View File
@@ -1057,42 +1057,110 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
break;
}
case ServerOP_Consent: {
zoneserver_list.SendPacket(pack); // update corpses in all zones
// Message string id's likely to be used here are:
// CONSENT_YOURSELF = 399
// CONSENT_INVALID_NAME = 397
// TARGET_NOT_FOUND = 101
ZoneServer* zs;
ServerOP_Consent_Struct* s = (ServerOP_Consent_Struct*)pack->pBuffer;
ClientListEntry* cle = client_list.FindCharacter(s->grantname);
if (cle) {
if (cle->instance() != 0)
{
zs = zoneserver_list.FindByInstanceID(cle->instance());
if (zs) {
zs->SendPacket(pack);
}
else
{
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
strcpy(scs->grantname, s->grantname);
strcpy(scs->ownername, s->ownername);
scs->permission = s->permission;
scs->zone_id = s->zone_id;
scs->instance_id = s->instance_id;
scs->message_string_id = 101;
zs = zoneserver_list.FindByInstanceID(s->instance_id);
if (zs) {
zs->SendPacket(pack);
}
else {
LogInfo("Unable to locate zone record for instance id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->instance_id);
}
safe_delete(pack);
}
}
else
{
zs = zoneserver_list.FindByZoneID(cle->zone());
if (zs) {
zs->SendPacket(pack);
}
else {
// send target not found back to requester
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
strcpy(scs->grantname, s->grantname);
strcpy(scs->ownername, s->ownername);
scs->permission = s->permission;
scs->zone_id = s->zone_id;
scs->message_string_id = 101;
zs = zoneserver_list.FindByZoneID(s->zone_id);
if (zs) {
zs->SendPacket(pack);
}
else {
LogInfo("Unable to locate zone record for zone id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id);
}
safe_delete(pack);
}
}
}
else {
// send target not found back to requester
auto pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct));
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
strcpy(scs->grantname, s->grantname);
strcpy(scs->ownername, s->ownername);
scs->permission = s->permission;
scs->zone_id = s->zone_id;
scs->message_string_id = 397;
zs = zoneserver_list.FindByZoneID(s->zone_id);
if (zs) {
zs->SendPacket(pack);
}
else {
LogInfo("Unable to locate zone record for zone id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id);
}
safe_delete(pack);
}
break;
}
case ServerOP_Consent_Response: {
// Message string id's likely to be used here are:
// CONSENT_YOURSELF = 399
// CONSENT_INVALID_NAME = 397
// TARGET_NOT_FOUND = 101
ServerOP_Consent_Struct* s = (ServerOP_Consent_Struct*)pack->pBuffer;
ZoneServer* owner_zs = nullptr;
if (s->instance_id == 0) {
owner_zs = zoneserver_list.FindByZoneID(s->zone_id);
if (s->instance_id != 0)
{
ZoneServer* zs = zoneserver_list.FindByInstanceID(s->instance_id);
if (zs) {
zs->SendPacket(pack);
}
else {
LogInfo("Unable to locate zone record for instance id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->instance_id);
}
}
else {
owner_zs = zoneserver_list.FindByInstanceID(s->instance_id);
}
if (owner_zs) {
owner_zs->SendPacket(pack);
}
else {
LogInfo("Unable to locate zone record for zone id [{}] or instance id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id, s->instance_id);
}
if (s->consent_type == EQEmu::consent::Normal) {
// send the message to the client being granted or denied permission
ClientListEntry* cle = client_list.FindCharacter(s->grantname);
if (cle) {
ZoneServer* granted_zs = nullptr;
if (cle->instance() == 0) {
granted_zs = zoneserver_list.FindByZoneID(cle->zone());
}
else {
granted_zs = zoneserver_list.FindByInstanceID(cle->instance());
}
// avoid sending twice if owner and granted are in same zone
if (granted_zs && granted_zs != owner_zs) {
granted_zs->SendPacket(pack);
}
else
{
ZoneServer* zs = zoneserver_list.FindByZoneID(s->zone_id);
if (zs) {
zs->SendPacket(pack);
}
else {
LogInfo("Unable to locate zone record for zone id [{}] in zoneserver list for ServerOP_Consent_Response operation", s->zone_id);
}
}
break;
+2 -3
View File
@@ -82,6 +82,7 @@ SET(zone_sources
main.cpp
map.cpp
merc.cpp
metric_event_types.cpp
mob.cpp
mob_ai.cpp
mob_appearance.cpp
@@ -141,7 +142,6 @@ SET(zone_sources
zone.cpp
zone_config.cpp
zonedb.cpp
zone_reload.cpp
zoning.cpp
)
@@ -248,8 +248,7 @@ SET(zone_headers
zone.h
zone_config.h
zonedb.h
zonedump.h
zone_reload.h )
zonedump.h)
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
+2 -21
View File
@@ -1023,24 +1023,6 @@ void Client::ResetAlternateAdvancementTimers() {
safe_delete(outapp);
}
void Client::ResetOnDeathAlternateAdvancement() {
for (const auto &aa : aa_ranks) {
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first);
auto ability = ability_rank.first;
auto rank = ability_rank.second;
if (!ability)
continue;
if (!rank)
continue;
// since they're dying, we just need to clear the DB
if (ability->reset_on_death)
p_timers.Clear(&database, rank->spell_type + pTimerAAStart);
}
}
void Client::PurchaseAlternateAdvancementRank(int rank_id) {
AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id);
if(!rank) {
@@ -1664,7 +1646,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
LogInfo("Loading Alternate Advancement Abilities");
abilities.clear();
std::string query = "SELECT id, name, category, classes, races, deities, drakkin_heritage, status, type, charges, "
"grant_only, reset_on_death, first_rank_id FROM aa_ability WHERE enabled = 1";
"grant_only, first_rank_id FROM aa_ability WHERE enabled = 1";
auto results = QueryDatabase(query);
if(results.Success()) {
for(auto row = results.begin(); row != results.end(); ++row) {
@@ -1681,8 +1663,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
ability->type = atoi(row[8]);
ability->charges = atoi(row[9]);
ability->grant_only = atoi(row[10]) != 0 ? true : false;
ability->reset_on_death = atoi(row[11]) != 0 ? true : false;
ability->first_rank_id = atoi(row[12]);
ability->first_rank_id = atoi(row[11]);
ability->first = nullptr;
abilities[ability->id] = std::unique_ptr<AA::Ability>(ability);
-1
View File
@@ -50,7 +50,6 @@ public:
int drakkin_heritage;
int status;
bool grant_only;
bool reset_on_death;
int type;
int charges;
int first_rank_id;
+3 -11
View File
@@ -32,7 +32,6 @@
#endif
#include "map.h"
#include "water_map.h"
extern Zone* zone;
//#define LOSDEBUG 6
@@ -140,7 +139,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
if (RuleB(Aggro, UseLevelAggro))
{
if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3 && !AlwaysAggro())
if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3)
{
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2);
return;
@@ -148,7 +147,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
}
else
{
if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY && !AlwaysAggro()) {
if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY ) {
towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(),
dist2, iAggroRange2);
return;
@@ -238,11 +237,6 @@ bool Mob::CheckWillAggro(Mob *mob) {
if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn() || mob->CastToClient()->bZoning)
return false;
}
// We don't want to aggro clients outside of water if we're water only.
if (mob->IsClient() && mob->CastToClient()->GetLastRegion() != RegionTypeWater && IsUnderwaterOnly()) {
return false;
}
/**
* Pets shouldn't scan for aggro
@@ -324,7 +318,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
//old InZone check taken care of above by !mob->CastToClient()->Connected()
(
( GetLevel() >= RuleI(Aggro, MinAggroLevel))
||(GetBodyType() == 3) || AlwaysAggro()
||(GetBodyType() == 3)
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
@@ -358,7 +352,6 @@ bool Mob::CheckWillAggro(Mob *mob) {
//old InZone check taken care of above by !mob->CastToClient()->Connected()
(
( GetINT() <= RuleI(Aggro, IntAggroThreshold) )
|| AlwaysAggro()
||( mob->IsClient() && mob->CastToClient()->IsSitting() )
||( mob->GetLevelCon(GetLevel()) != CON_GRAY)
@@ -390,7 +383,6 @@ bool Mob::CheckWillAggro(Mob *mob) {
LogAggro("Dist^2: [{}]\n", dist2);
LogAggro("Range^2: [{}]\n", iAggroRange2);
LogAggro("Faction: [{}]\n", fv);
LogAggro("AlwaysAggroFlag: [{}]\n", AlwaysAggro());
LogAggro("Int: [{}]\n", GetINT());
LogAggro("Con: [{}]\n", GetLevelCon(mob->GetLevel()));
+10 -21
View File
@@ -724,20 +724,20 @@ int Mob::GetClassRaceACBonus()
hardcap = 32;
softcap = 15;
}
int weight = IsClient() ? CastToClient()->CalcCurrentWeight()/10 : 0;
int weight = IsClient() ? CastToClient()->CalcCurrentWeight() : 0;
if (weight < hardcap - 1) {
double temp = level + 5;
int temp = level + 5;
if (weight > softcap) {
double redux = static_cast<double>(weight - softcap) * 6.66667;
double redux = (weight - softcap) * 6.66667;
redux = (100.0 - std::min(100.0, redux)) * 0.01;
temp = std::max(0.0, temp * redux);
temp = std::max(0, static_cast<int>(temp * redux));
}
ac_bonus = static_cast<int>((4.0 * temp) / 3.0);
ac_bonus = (4 * temp) / 3;
}
else if (weight > hardcap + 1) {
double temp = level + 5;
double multiplier = std::min(1.0, (weight - (static_cast<double>(hardcap) - 10.0)) / 100.0);
temp = (4.0 * temp) / 3.0;
int temp = level + 5;
double multiplier = std::min(1.0, (weight - (hardcap - 10.0)) / 100.0);
temp = (4 * temp) / 3;
ac_bonus -= static_cast<int>(temp * multiplier);
}
}
@@ -799,7 +799,7 @@ int Mob::ACSum()
// EQ math
ac = (ac * 4) / 3;
// anti-twink
if (IsClient() && GetLevel() < RuleI(Combat, LevelToStopACTwinkControl))
if (IsClient() && GetLevel() < 50)
ac = std::min(ac, 25 + 6 * GetLevel());
ac = std::max(0, ac + GetClassRaceACBonus());
if (IsNPC()) {
@@ -1852,17 +1852,6 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk
BuffFadeDetrimental();
}
/*
Reset AA reuse timers that need to be, live-like this is only Lay on Hands
*/
ResetOnDeathAlternateAdvancement();
/*
Reset reuse timer for classic skill based Lay on Hands (For tit I guess)
*/
if (GetClass() == PALADIN) // we could check if it's not expired I guess, but should be fine not to
p_timers.Clear(&database, pTimerLayHands);
/*
Finally, send em home
@@ -5502,4 +5491,4 @@ int32 Mob::GetHPRegen() const
int32 Mob::GetManaRegen() const
{
return mana_regen;
}
}
+235 -424
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -73,7 +73,7 @@ private:
int m_owner;
int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell
int spell_id; // spell we cast
float distance; // distance we remove
int distance; // distance we remove
Timer remove_timer; // when we depop
Timer process_timer; // rate limit process calls
Timer cast_timer; // some auras pulse
+1 -1
View File
@@ -56,7 +56,7 @@ Beacon::Beacon(Mob *at_mob, int lifetime)
:Mob
(
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
),
remove_timer(lifetime),
spell_timer(0)
+30 -153
View File
@@ -6421,52 +6421,32 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
bool taunt_time = taunt_timer.Check();
bool ca_time = classattack_timer.Check(false);
bool ma_time = monkattack_timer.Check(false);
bool ka_time = knightattack_timer.Check(false);
if (taunt_time) {
// Bots without this skill shouldn't be 'checking' on this timer..let's just disable it and avoid the extra IsAttackAllowed() checks
// Note: this is done here instead of NPC::ctor() because taunt skill can be acquired during level ups (the timer is re-enabled in CalcBotStats())
if (!GetSkill(EQEmu::skills::SkillTaunt)) {
taunt_timer.Disable();
return;
}
if (!IsAttackAllowed(target)) {
return;
}
}
if ((ca_time || ma_time || ka_time) && !IsAttackAllowed(target)) {
if((taunt_time || ca_time || ka_time) && !IsAttackAllowed(target))
return;
}
if(ka_time){
int knightreuse = 1000;
switch(GetClass()){
case SHADOWKNIGHT: {
case SHADOWKNIGHT:
case SHADOWKNIGHTGM: {
CastSpell(SPELL_NPC_HARM_TOUCH, target->GetID());
knightattack_timer.Start(HarmTouchReuseTime * 1000);
knightreuse = (HarmTouchReuseTime * 1000);
break;
}
case PALADIN: {
case PALADIN:
case PALADINGM: {
if(GetHPRatio() < 20) {
CastSpell(SPELL_LAY_ON_HANDS, GetID());
knightattack_timer.Start(LayOnHandsReuseTime * 1000);
}
else {
knightattack_timer.Start(2000);
knightreuse = (LayOnHandsReuseTime * 1000);
}
else
knightreuse = 2000;
break;
}
default: {
break;
}
}
knightattack_timer.Start(knightreuse);
}
if(taunting && target && target->IsNPC() && taunt_time) {
@@ -6477,66 +6457,8 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
}
}
if (ma_time) {
switch (GetClass()) {
case MONK: {
int reuse = (MonkSpecialAttack(target, EQEmu::skills::SkillTigerClaw) - 1);
// Live AA - Technique of Master Wu
int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack;
if (wuchance) {
const int MonkSPA[5] = {
EQEmu::skills::SkillFlyingKick,
EQEmu::skills::SkillDragonPunch,
EQEmu::skills::SkillEagleStrike,
EQEmu::skills::SkillTigerClaw,
EQEmu::skills::SkillRoundKick
};
int extra = 0;
// always 1/4 of the double attack chance, 25% at rank 5 (100/4)
while (wuchance > 0) {
if (zone->random.Roll(wuchance)) {
++extra;
}
else {
break;
}
wuchance /= 4;
}
Mob* bo = GetBotOwner();
if (bo && bo->IsClient() && bo->CastToClient()->GetBotOption(Client::booMonkWuMessage)) {
bo->Message(
GENERIC_EMOTE,
"The spirit of Master Wu fills %s! %s gains %d additional attack(s).",
GetCleanName(),
GetCleanName(),
extra
);
}
auto classic = RuleB(Combat, ClassicMasterWu);
while (extra) {
MonkSpecialAttack(GetTarget(), (classic ? MonkSPA[zone->random.Int(0, 4)] : EQEmu::skills::SkillTigerClaw));
--extra;
}
}
float HasteModifier = (GetHaste() * 0.01f);
monkattack_timer.Start((reuse * 1000) / HasteModifier);
break;
}
default:
break;;
}
}
if (!ca_time) {
if(!ca_time)
return;
}
float HasteModifier = (GetHaste() * 0.01f);
uint16 skill_to_use = -1;
@@ -6571,22 +6493,18 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
}
break;
case MONK:
if (GetLevel() >= 30) {
if(GetLevel() >= 30)
skill_to_use = EQEmu::skills::SkillFlyingKick;
}
else if (GetLevel() >= 25) {
else if(GetLevel() >= 25)
skill_to_use = EQEmu::skills::SkillDragonPunch;
}
else if (GetLevel() >= 20) {
else if(GetLevel() >= 20)
skill_to_use = EQEmu::skills::SkillEagleStrike;
}
else if (GetLevel() >= 5) {
else if(GetLevel() >= 10)
skill_to_use = EQEmu::skills::SkillTigerClaw;
else if(GetLevel() >= 5)
skill_to_use = EQEmu::skills::SkillRoundKick;
}
else {
else
skill_to_use = EQEmu::skills::SkillKick;
}
break;
case ROGUE:
skill_to_use = EQEmu::skills::SkillBackstab;
@@ -6637,54 +6555,19 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
}
}
if (
skill_to_use == EQEmu::skills::SkillFlyingKick ||
skill_to_use == EQEmu::skills::SkillDragonPunch ||
skill_to_use == EQEmu::skills::SkillEagleStrike ||
skill_to_use == EQEmu::skills::SkillRoundKick
) {
if (skill_to_use == EQEmu::skills::SkillFlyingKick || skill_to_use == EQEmu::skills::SkillDragonPunch || skill_to_use == EQEmu::skills::SkillEagleStrike || skill_to_use == EQEmu::skills::SkillTigerClaw || skill_to_use == EQEmu::skills::SkillRoundKick) {
reuse = (MonkSpecialAttack(target, skill_to_use) - 1);
// Live AA - Technique of Master Wu
int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack;
MonkSpecialAttack(target, skill_to_use);
uint32 bDoubleSpecialAttack = (itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack);
if(bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0, 100))) {
int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick };
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]);
int TripleChance = 25;
if (bDoubleSpecialAttack > 100)
TripleChance += (TripleChance * (100 - bDoubleSpecialAttack) / 100);
if (wuchance) {
const int MonkSPA[5] = {
EQEmu::skills::SkillFlyingKick,
EQEmu::skills::SkillDragonPunch,
EQEmu::skills::SkillEagleStrike,
EQEmu::skills::SkillTigerClaw,
EQEmu::skills::SkillRoundKick
};
int extra = 0;
// always 1/4 of the double attack chance, 25% at rank 5 (100/4)
while (wuchance > 0) {
if (zone->random.Roll(wuchance)) {
++extra;
}
else {
break;
}
wuchance /= 4;
}
Mob* bo = GetBotOwner();
if (bo && bo->IsClient() && bo->CastToClient()->GetBotOption(Client::booMonkWuMessage)) {
bo->Message(
GENERIC_EMOTE,
"The spirit of Master Wu fills %s! %s gains %d additional attack(s).",
GetCleanName(),
GetCleanName(),
extra
);
}
auto classic = RuleB(Combat, ClassicMasterWu);
while (extra) {
MonkSpecialAttack(GetTarget(), (classic ? MonkSPA[zone->random.Int(0, 4)] : skill_to_use));
--extra;
}
if(TripleChance > zone->random.Int(0,100))
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]);
}
reuse *= 1000;
@@ -9083,12 +8966,6 @@ void Bot::CalcBotStats(bool showtext) {
skills[sindex] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)sindex, GetLevel());
}
taunt_timer.Start(1000);
if (GetClass() == MONK && GetLevel() >= 10) {
monkattack_timer.Start(1000);
}
LoadAAs();
GenerateSpecialAttacks();
+8 -36
View File
@@ -3928,16 +3928,6 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
"<td><c \"#00CCCC\">null</td>"
"<td><c \"#888888\">(toggles)</td>"
"</tr>"
"<tr>"
"<td><c \"#CCCCCC\">monkwumessage</td>"
"<td><c \"#00CC00\">enable <c \"#CCCCCC\">| <c \"#00CC00\">disable</td>"
"<td><c \"#888888\">displays monk wu trigger messages</td>"
"</tr>"
"<tr>"
"<td></td>"
"<td><c \"#00CCCC\">null</td>"
"<td><c \"#888888\">(toggles)</td>"
"</tr>"
"<tr>"
"<td><c \"#CCCCCC\">current</td>"
"<td></td>"
@@ -4113,22 +4103,6 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
c->Message(m_action, "Bot 'buff counter' is now %s.", (c->GetBotOption(Client::booBuffCounter) == true ? "enabled" : "disabled"));
}
else if (!owner_option.compare("monkwumessage")) {
if (!argument.compare("enable")) {
c->SetBotOption(Client::booMonkWuMessage, true);
}
else if (!argument.compare("disable")) {
c->SetBotOption(Client::booMonkWuMessage, false);
}
else {
c->SetBotOption(Client::booMonkWuMessage, !c->GetBotOption(Client::booMonkWuMessage));
}
database.botdb.SaveOwnerOption(c->CharacterID(), Client::booMonkWuMessage, c->GetBotOption(Client::booMonkWuMessage));
c->Message(m_action, "Bot 'monk wu message' is now %s.", (c->GetBotOption(Client::booMonkWuMessage) == true ? "enabled" : "disabled"));
}
else if (!owner_option.compare("current")) {
std::string window_title = "Current Bot Owner Options Settings";
@@ -4138,14 +4112,13 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
"<td><c \"#FFFFFF\">Option<br>------</td>"
"<td><c \"#00FF00\">Argument<br>-------</td>"
"</tr>"
"<tr>" "<td><c \"#CCCCCC\">deathmarquee</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">statsupdate</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">spawnmessage</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">spawnmessage</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">altcombat</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">autodefend</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">buffcounter</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">monkwumessage</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">deathmarquee</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">statsupdate</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">spawnmessage</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">spawnmessage</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">altcombat</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">autodefend</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"<tr>" "<td><c \"#CCCCCC\">buffcounter</td>" "<td><c \"#00CC00\">{}</td>" "</tr>"
"</table>",
(c->GetBotOption(Client::booDeathMarquee) ? "enabled" : "disabled"),
(c->GetBotOption(Client::booStatsUpdate) ? "enabled" : "disabled"),
@@ -4153,8 +4126,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
(c->GetBotOption(Client::booSpawnMessageClassSpecific) ? "class" : "default"),
(RuleB(Bots, AllowOwnerOptionAltCombat) ? (c->GetBotOption(Client::booAltCombat) ? "enabled" : "disabled") : "restricted"),
(RuleB(Bots, AllowOwnerOptionAutoDefend) ? (c->GetBotOption(Client::booAutoDefend) ? "enabled" : "disabled") : "restricted"),
(c->GetBotOption(Client::booBuffCounter) ? "enabled" : "disabled"),
(c->GetBotOption(Client::booMonkWuMessage) ? "enabled" : "disabled")
(c->GetBotOption(Client::booBuffCounter) ? "enabled" : "disabled")
);
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
-1
View File
@@ -2257,7 +2257,6 @@ bool BotDatabase::SaveOwnerOption(const uint32 owner_id, size_t type, const bool
case Client::booAltCombat:
case Client::booAutoDefend:
case Client::booBuffCounter:
case Client::booMonkWuMessage:
{
query = fmt::format(
"REPLACE INTO `bot_owner_options`(`owner_id`, `option_type`, `option_value`) VALUES ('{}', '{}', '{}')",
+6 -137
View File
@@ -121,8 +121,7 @@ Client::Client(EQStreamInterface* ieqs)
0,
0,
0,
0,
false
0
),
hpupdate_timer(2000),
camp_timer(29000),
@@ -166,7 +165,6 @@ Client::Client(EQStreamInterface* ieqs)
hp_self_update_throttle_timer(300),
hp_other_update_throttle_timer(500),
position_update_timer(10000),
consent_throttle_timer(2000),
tmSitting(0)
{
@@ -256,7 +254,6 @@ Client::Client(EQStreamInterface* ieqs)
TotalSecondsPlayed = 0;
keyring.clear();
bind_sight_target = nullptr;
p_raid_instance = nullptr;
mercid = 0;
mercSlot = 0;
InitializeMercInfo();
@@ -360,7 +357,6 @@ Client::Client(EQStreamInterface* ieqs)
bot_owner_options[booAltCombat] = RuleB(Bots, AllowOwnerOptionAltCombat);
bot_owner_options[booAutoDefend] = RuleB(Bots, AllowOwnerOptionAutoDefend);
bot_owner_options[booBuffCounter] = false;
bot_owner_options[booMonkWuMessage] = false;
SetBotPulling(false);
SetBotPrecombat(false);
@@ -1919,7 +1915,7 @@ void Client::CheckManaEndUpdate() {
else if (group) {
group->SendEndurancePacketFrom(this);
}
auto endurance_packet = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct));
EnduranceUpdate_Struct* endurance_update = (EnduranceUpdate_Struct*)endurance_packet->pBuffer;
endurance_update->cur_end = GetEndurance();
@@ -6258,52 +6254,6 @@ void Client::DragCorpses()
}
}
void Client::ConsentCorpses(std::string consent_name, bool deny)
{
if (strcasecmp(consent_name.c_str(), GetName()) == 0) {
MessageString(Chat::Red, CONSENT_YOURSELF);
}
else if (!consent_throttle_timer.Check()) {
MessageString(Chat::Red, CONSENT_WAIT);
}
else {
auto pack = new ServerPacket(ServerOP_Consent, sizeof(ServerOP_Consent_Struct));
ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer;
strn0cpy(scs->grantname, consent_name.c_str(), sizeof(scs->grantname));
strn0cpy(scs->ownername, GetName(), sizeof(scs->ownername));
strn0cpy(scs->zonename, "Unknown", sizeof(scs->zonename));
scs->permission = deny ? 0 : 1;
scs->zone_id = zone->GetZoneID();
scs->instance_id = zone->GetInstanceID();
scs->consent_type = EQEmu::consent::Normal;
scs->consent_id = 0;
if (strcasecmp(scs->grantname, "group") == 0) {
if (!deny) {
Group* grp = GetGroup();
scs->consent_id = grp ? grp->GetID() : 0;
}
scs->consent_type = EQEmu::consent::Group;
}
else if (strcasecmp(scs->grantname, "raid") == 0) {
if (!deny) {
Raid* raid = GetRaid();
scs->consent_id = raid ? raid->GetID() : 0;
}
scs->consent_type = EQEmu::consent::Raid;
}
else if (strcasecmp(scs->grantname, "guild") == 0) {
if (!deny) {
scs->consent_id = GuildID();
}
scs->consent_type = EQEmu::consent::Guild;
// update all corpses in db so buried/unloaded corpses see new consent id
database.UpdateCharacterCorpseConsent(CharacterID(), scs->consent_id);
}
worldserver.SendPacket(pack);
safe_delete(pack);
}
}
void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration)
{
if(!target || !IsValidSpell(spell_id) || this->GetID() == target->GetID())
@@ -7798,8 +7748,6 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra
// few optimizations
if (GetFeigned())
return FACTION_INDIFFERENT;
if(!zone->CanDoCombat())
return FACTION_INDIFFERENT;
if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead())
return FACTION_INDIFFERENT;
if (IsInvisible(tnpc))
@@ -8585,13 +8533,13 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name
qr->mob_id = target->GetID(); // Entity ID for the from mob name
qr->target_id = GetID(); // The Client ID (this)
qr->copper = copper;
qr->silver = silver;
qr->gold = gold;
qr->platinum = platinum;
qr->item_id[0] = itemid;
qr->item_id = itemid;
qr->exp_reward = exp;
if (copper > 0 || silver > 0 || gold > 0 || platinum > 0)
@@ -8602,7 +8550,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
if (faction)
{
if (target && target->IsNPC())
if (target->IsNPC())
{
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
@@ -8618,42 +8566,6 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
safe_delete(outapp);
}
void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction)
{
auto outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct));
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
memcpy(qr, &reward, sizeof(QuestReward_Struct));
// not set in caller because reasons
qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name
if (reward.copper > 0 || reward.silver > 0 || reward.gold > 0 || reward.platinum > 0)
AddMoneyToPP(reward.copper, reward.silver, reward.gold, reward.platinum, false);
for (int i = 0; i < QUESTREWARD_COUNT; ++i)
if (reward.item_id[i] > 0)
SummonItem(reward.item_id[i], 0, 0, 0, 0, 0, 0, false, EQEmu::invslot::slotCursor);
if (faction)
{
if (target && target->IsNPC())
{
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
qr->faction = target->CastToNPC()->GetPrimaryFaction();
qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow.
}
}
if (reward.exp_reward> 0)
AddEXP(reward.exp_reward);
QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
safe_delete(outapp);
}
void Client::SendHPUpdateMarquee(){
if (!this || !this->IsClient() || !this->current_hp || !this->max_hp)
return;
@@ -8758,11 +8670,6 @@ void Client::CheckRegionTypeChanges()
if (last_region_type == new_region)
return;
// If we got out of water clear any water aggro for water only npcs
if (last_region_type == RegionTypeWater) {
entity_list.ClearWaterAggro(this);
}
// region type changed
last_region_type = new_region;
@@ -9204,7 +9111,7 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id)
secondary_item->SetOrnamentationIDFile(model_id);
SendItemPacket(EQEmu::invslot::slotSecondary, secondary_item, ItemPacketTrade);
WearChange(EQEmu::textures::weaponSecondary, static_cast<uint16>(model_id), 0);
Message(Chat::Yellow, "Your secondary weapon appearance has been modified");
}
}
@@ -9293,41 +9200,3 @@ void Client::SetBotOption(BotOwnerOption boo, bool flag) {
}
#endif
void Client::SendToGuildHall()
{
std::string zone_short_name = "guildhall";
uint32 zone_id = database.GetZoneID(zone_short_name.c_str());
if (zone_id == 0) {
return;
}
uint32 expiration_time = (RuleI(Instances, GuildHallExpirationDays) * 86400);
uint16 instance_id = 0;
std::string guild_hall_instance_key = fmt::format("guild-hall-instance-{}", GuildID());
std::string instance_data = DataBucket::GetData(guild_hall_instance_key);
if (!instance_data.empty() && std::stoi(instance_data) > 0) {
instance_id = std::stoi(instance_data);
}
if (instance_id <= 0) {
if (!database.GetUnusedInstanceID(instance_id)) {
Message(Chat::Red, "Server was unable to find a free instance id.");
return;
}
if (!database.CreateInstance(instance_id, zone_id, 1, expiration_time)) {
Message(Chat::Red, "Server was unable to create a new instance.");
return;
}
DataBucket::SetData(
guild_hall_instance_key,
std::to_string(instance_id),
std::to_string(expiration_time)
);
}
AssignToInstance(instance_id);
MovePC(345, instance_id, -1.00, -1.00, 3.34, 0, 1);
}
+8 -21
View File
@@ -633,7 +633,6 @@ public:
void MovePC(uint32 zoneID, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
void MovePC(float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
void MovePC(uint32 zoneID, uint32 instanceID, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
void SendToGuildHall();
void AssignToInstance(uint16 instance_id);
void RemoveFromInstance(uint16 instance_id);
void WhoAll();
@@ -692,7 +691,7 @@ public:
int GetClientMaxLevel() const { return client_max_level; }
void SetClientMaxLevel(int max_level) { client_max_level = max_level; }
void CheckManaEndUpdate();
void SendManaUpdate();
void SendEnduranceUpdate();
@@ -794,9 +793,6 @@ public:
virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); }
inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; }
inline bool AutoConsentGroupEnabled() const { return m_pp.groupAutoconsent != 0; }
inline bool AutoConsentRaidEnabled() const { return m_pp.raidAutoconsent != 0; }
inline bool AutoConsentGuildEnabled() const { return m_pp.guildAutoconsent != 0; }
void SummonHorse(uint16 spell_id);
void SetHorseId(uint16 horseid_in);
@@ -839,7 +835,6 @@ public:
void SendAlternateAdvancementTimers();
void ResetAlternateAdvancementTimer(int ability);
void ResetAlternateAdvancementTimers();
void ResetOnDeathAlternateAdvancement();
void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); }
void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); }
@@ -902,14 +897,14 @@ public:
void BreakFeignDeathWhenCastOn(bool IsResisted);
void LeaveGroup();
bool Hungry() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.hunger_level <= 3000;}
bool Thirsty() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.thirst_level <= 3000;}
bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;}
bool Thirsty() const {if (GetGM()) return false; return m_pp.thirst_level <= 3000;}
int32 GetHunger() const { return m_pp.hunger_level; }
int32 GetThirst() const { return m_pp.thirst_level; }
void SetHunger(int32 in_hunger);
void SetThirst(int32 in_thirst);
void SetConsumption(int32 in_hunger, int32 in_thirst);
bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; }
bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; }
bool CheckTradeLoreConflict(Client* other);
bool CheckTradeNonDroppable();
@@ -962,6 +957,7 @@ public:
void EnteringMessages(Client* client);
void SendRules(Client* client);
std::list<std::string> consent_list;
const bool GetGMSpeed() const { return (gmspeed > 0); }
bool CanUseReport;
@@ -1141,7 +1137,6 @@ public:
inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); }
void DragCorpses();
inline void ClearDraggedCorpses() { DraggedCorpses.clear(); }
void ConsentCorpses(std::string consent_name, bool deny = false);
void SendAltCurrencies();
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0);
@@ -1287,7 +1282,6 @@ public:
int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false);
void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false);
void QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction); // TODO: Fix faction processing
void ResetHPUpdateTimer() { hpupdate_timer.Start(); }
@@ -1295,8 +1289,6 @@ public:
void CheckRegionTypeChanges();
WaterRegionType GetLastRegion() { return last_region_type; }
int32 CalcATK();
uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns.
@@ -1304,8 +1296,6 @@ public:
void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update);
glm::vec4 &GetLastPositionBeforeBulkUpdate();
Raid *p_raid_instance;
protected:
friend class Mob;
void CalcItemBonuses(StatBonuses* newbon);
@@ -1345,7 +1335,6 @@ protected:
char *adv_data;
private:
eqFilterMode ClientFilters[_FilterCount];
int32 HandlePacket(const EQApplicationPacket *app);
void OPTGB(const EQApplicationPacket *app);
@@ -1538,7 +1527,6 @@ private:
Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */
Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
Timer consent_throttle_timer;
glm::vec3 m_Proximity;
glm::vec4 last_position_before_bulk_update;
@@ -1639,9 +1627,9 @@ private:
bool InterrogateInventory_error(int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, int depth);
int client_max_level;
#ifdef BOTS
public:
enum BotOwnerOption : size_t {
booDeathMarquee,
@@ -1652,13 +1640,12 @@ public:
booAltCombat,
booAutoDefend,
booBuffCounter,
booMonkWuMessage,
_booCount
};
bool GetBotOption(BotOwnerOption boo) const;
void SetBotOption(BotOwnerOption boo, bool flag = true);
bool GetBotPulling() { return m_bot_pulling; }
void SetBotPulling(bool flag = true) { m_bot_pulling = flag; }

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