mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 17:22:29 +00:00
Compare commits
469 Commits
hp-fix
...
development
| Author | SHA1 | Date | |
|---|---|---|---|
| 296d48993e | |||
| 1d4438ae1f | |||
| 03adf20fe9 | |||
| dd6cde68bb | |||
| 95c8b60ec6 | |||
| fa418172d6 | |||
| 7b106fc622 | |||
| 62a453f0d7 | |||
| fa9314811e | |||
| d2d7b8108d | |||
| 99793cab8b | |||
| e2484997dd | |||
| 66935fe21b | |||
| db988e4261 | |||
| fdd260d5fa | |||
| 9110bc863e | |||
| 4a41583805 | |||
| 5396c0c88b | |||
| 968ae26c99 | |||
| 7bf466cf3f | |||
| 49d7eb1402 | |||
| d83ced6f76 | |||
| 1ea8888607 | |||
| f9eb4603a3 | |||
| d656be6be4 | |||
| fbbbd3b09d | |||
| a6d1652f44 | |||
| f0bf285836 | |||
| 1f560529da | |||
| f65a6d2761 | |||
| 79f250da2d | |||
| 752e6c89f3 | |||
| e962ad3a35 | |||
| 872d494bb6 | |||
| 8a48473dbc | |||
| a208801d1f | |||
| a5d8a64792 | |||
| ee1f0ea91f | |||
| 7c20a86f23 | |||
| dbe6adbed0 | |||
| d300e78b39 | |||
| 0400504adc | |||
| 5ce2889210 | |||
| cc0371c16e | |||
| 4e297f3d96 | |||
| e9f48d5fba | |||
| 00c41dda8c | |||
| 7b235a6ede | |||
| 58d5983ef1 | |||
| 7749c626f0 | |||
| a6cd0bc33a | |||
| cba95851a2 | |||
| 7f5706abcf | |||
| 44b8c9203a | |||
| afdbc0ce80 | |||
| e850d80656 | |||
| b9722c6d28 | |||
| 5a7ee28740 | |||
| e4f2aec11e | |||
| e99c8dafc5 | |||
| 936043a53c | |||
| 3c09448e90 | |||
| e09a8f8f8f | |||
| 804f0681a9 | |||
| 71c53cb18b | |||
| 176bfc8524 | |||
| 28b1abe1a7 | |||
| 3a94132749 | |||
| 5ebbbf647b | |||
| 5f482a9b30 | |||
| 91aa950304 | |||
| 613066976d | |||
| 1a556f4451 | |||
| d10145fc6f | |||
| f3002d9656 | |||
| 59c373bcff | |||
| ae8273e0b1 | |||
| 10083387b6 | |||
| 7e065ad966 | |||
| ffa968f64f | |||
| 6bf5608cf3 | |||
| 3853c4f150 | |||
| d6d4c458e7 | |||
| 26b160c59b | |||
| d107ff3069 | |||
| 220d8497dd | |||
| 645251992d | |||
| 9815f50efa | |||
| c0f57bed1f | |||
| d280d54446 | |||
| c99c5c1f1c | |||
| e45f02af95 | |||
| 323b35989c | |||
| 7f23c93ce5 | |||
| 6a7782ab8d | |||
| 5457f30659 | |||
| 652ea89dea | |||
| c79fbb99aa | |||
| 4f0e9945c6 | |||
| 4fbb98a5f7 | |||
| 8c78a19c95 | |||
| 6a77764f8b | |||
| d0ec0872b9 | |||
| 724d47432b | |||
| f26d56d6d5 | |||
| 886b321e66 | |||
| 85971590c8 | |||
| 898b1ea4d1 | |||
| d460fb3db8 | |||
| fbc5d045de | |||
| 3414d3a1ae | |||
| feed584a41 | |||
| 119b2d023f | |||
| 73acc3310c | |||
| 6da7116c66 | |||
| 26b21673ad | |||
| ef1f6adf18 | |||
| 1c2e1ea228 | |||
| 7cf66a2daa | |||
| 91c958ae63 | |||
| 8de410ebb7 | |||
| 550485ba33 | |||
| eb2b4fd9e0 | |||
| 42f439c4b7 | |||
| 294e51fca7 | |||
| 94166e0f95 | |||
| 1a1c3abc24 | |||
| 0f4f5d7046 | |||
| 8ec4afe721 | |||
| aa4536e1ef | |||
| 01a671918a | |||
| e09f28c62c | |||
| 82000949e3 | |||
| 4a154686e1 | |||
| 29dfe9d404 | |||
| 9a0c98397e | |||
| bc0795bb48 | |||
| d972183a79 | |||
| f70b4a79b2 | |||
| 7cac2e2bc3 | |||
| 2be1321aa9 | |||
| ba5bb09af7 | |||
| 5ab9b941e2 | |||
| d28f902ecc | |||
| fd862d16bb | |||
| a6e5534b64 | |||
| 225497337c | |||
| a5348e207b | |||
| c4c5256438 | |||
| b3b9899a23 | |||
| 7d1d385418 | |||
| 96cdf1b076 | |||
| 8688e9c9fa | |||
| 6a28828e08 | |||
| 8566662d56 | |||
| 298ae3e3ba | |||
| 4507b063f5 | |||
| 774e0c7faa | |||
| 8b54bb34e4 | |||
| e87b8e2682 | |||
| 2dc3ca52db | |||
| 514029a6bb | |||
| b29f398239 | |||
| e474b2a280 | |||
| d38b8a4867 | |||
| 1a5f48521d | |||
| ba427c64ba | |||
| 9d59b3def4 | |||
| a6f5bf72be | |||
| 6ff7f7aa53 | |||
| 1a2897c423 | |||
| 8b5b19ae2c | |||
| 6fa41a3b73 | |||
| 6496690123 | |||
| a11482ff23 | |||
| 4672e48fbd | |||
| 8f3cce6585 | |||
| 8d3a179ecc | |||
| 2cbcefd9a0 | |||
| ef06a0d0b6 | |||
| 1935ea60d0 | |||
| 8c7e1be344 | |||
| 9240497cbc | |||
| 0da4610249 | |||
| 26c7287997 | |||
| cece66adc6 | |||
| d29993fafa | |||
| 39c27c987d | |||
| 5470ec6293 | |||
| 1acdc6034b | |||
| e9fc80815a | |||
| a84536cd05 | |||
| 0a34809bb3 | |||
| 03847fb1ac | |||
| 8a27fce3a8 | |||
| 6a42639386 | |||
| b9214bfdee | |||
| 04fda24c8e | |||
| 446c5d90ec | |||
| 80f15ed04a | |||
| 51fb46556d | |||
| d73194c1f6 | |||
| ec1cf68ce2 | |||
| 39b39970f6 | |||
| 40edefa6f4 | |||
| 7154d5b841 | |||
| dfe43ce189 | |||
| 69d5fee471 | |||
| f1d9221b4c | |||
| fb2f901539 | |||
| 7c12c5d5ef | |||
| 7559732408 | |||
| fac0d795f2 | |||
| 3efd9c7f60 | |||
| bf8a0328b3 | |||
| 0ebb1cc54c | |||
| a111668888 | |||
| 0550fcfd3f | |||
| 293361a1f7 | |||
| 5d75b7b365 | |||
| 6400e2f8bc | |||
| 76b0183a0f | |||
| b3471c51df | |||
| b2c86f5571 | |||
| 264c6cb019 | |||
| 9bcb617f90 | |||
| f5d37a9959 | |||
| c44b82500d | |||
| 4f550fcbf3 | |||
| 1103d50733 | |||
| ddcb184183 | |||
| 90bcc5f03c | |||
| 27f8ae3999 | |||
| 80a891e541 | |||
| 776449aa3d | |||
| cef352f0ac | |||
| e8607a0c78 | |||
| 9c55cf9a8e | |||
| a9d1034298 | |||
| 8b83a13560 | |||
| 3c87480553 | |||
| 1a69218045 | |||
| e870ee5e0e | |||
| 908c6c18af | |||
| f591378ed3 | |||
| 0997a8a31e | |||
| 0bf6627fb0 | |||
| fb8539e679 | |||
| f8c2e85f3e | |||
| 110d2a0e10 | |||
| 8d9415191a | |||
| 7178a7e55d | |||
| 9e8d03d92d | |||
| f4a70eff43 | |||
| f9ec45c7ff | |||
| cf8bf9e4fc | |||
| 575237d764 | |||
| e12e8df3ef | |||
| 8d7b7d6cc4 | |||
| 6f79ea117c | |||
| 7b022502da | |||
| 4a376b7859 | |||
| 87cdf7feb1 | |||
| caf32290b8 | |||
| 7d495c56b3 | |||
| dc1c7bb284 | |||
| a6c85babfc | |||
| cbea7045fa | |||
| 099759c477 | |||
| 65197ac027 | |||
| e4bd6f5bd2 | |||
| acf5836253 | |||
| 17c8e8414c | |||
| 239033a269 | |||
| fa07064466 | |||
| 994ef712b2 | |||
| 33c30d3cbb | |||
| d9c8e80bca | |||
| 990729fe21 | |||
| aac0dd2993 | |||
| b17c24d2df | |||
| 32d606c667 | |||
| 6661672e2d | |||
| b5391b9110 | |||
| e306059f43 | |||
| a64e326c68 | |||
| 605b3d3a27 | |||
| 248e6d44db | |||
| 328a94e2d4 | |||
| 211196a722 | |||
| 0b283e60db | |||
| 90871cb3d9 | |||
| bf92845a4a | |||
| f8cbc2faed | |||
| 30fdb18945 | |||
| 062fb73f03 | |||
| 194c71727d | |||
| e1de3d2ae0 | |||
| 7f497f9d32 | |||
| 1cdb1816a2 | |||
| bc82b897c5 | |||
| beb4de0b45 | |||
| 785926a584 | |||
| 5c7972345a | |||
| 886f00ed50 | |||
| b983fac860 | |||
| 7b6decaef3 | |||
| 8d8301fbd7 | |||
| b4aa401210 | |||
| f1bfd6bc2a | |||
| 8c95323728 | |||
| 5874deeffc | |||
| 18cc648c8d | |||
| 9d515b20f2 | |||
| 17aaab1f9d | |||
| 6e26e8953c | |||
| e4138b871b | |||
| 4ac525afc2 | |||
| 05782433b8 | |||
| 9af7122b1d | |||
| 9e7a763482 | |||
| 1231d44b55 | |||
| 873f1f7f34 | |||
| d87db648c3 | |||
| 119c3d14b7 | |||
| 3cda32c213 | |||
| df3161455a | |||
| 4389f84ea5 | |||
| f9855fd097 | |||
| f912814e13 | |||
| 5738958a2a | |||
| d36d11653a | |||
| 7230714cbc | |||
| 6e5bf4b941 | |||
| fb66afd565 | |||
| ef5124d756 | |||
| 987de17e93 | |||
| 060be606e7 | |||
| 1c5f9f2e0f | |||
| 62253cc016 | |||
| 0b18671e91 | |||
| c98f3cfb4c | |||
| 624d11de4e | |||
| 5eb95a95d0 | |||
| da01156673 | |||
| 6a244f16e1 | |||
| 36d10462f7 | |||
| c30dbf6628 | |||
| 657cbbcabe | |||
| 81e7cf5a32 | |||
| edf298685e | |||
| efab0c4b6b | |||
| c838564023 | |||
| d197ee631e | |||
| 3dcddcba04 | |||
| 7823ff5336 | |||
| 11c335a015 | |||
| 07d96ad921 | |||
| 5d522b149b | |||
| 234bd89ed5 | |||
| af5cfb9bed | |||
| 426f9c337b | |||
| 5235dcee95 | |||
| 203ba2d340 | |||
| 9c67421ccc | |||
| 6669fc8214 | |||
| cef873f793 | |||
| 6a962f2591 | |||
| 91adf9c0eb | |||
| 9887580f9a | |||
| b7c62b5242 | |||
| 89a40272c6 | |||
| db369c98c8 | |||
| 10ba5d6046 | |||
| dd1a869531 | |||
| a9e23cf83a | |||
| 783c12590e | |||
| 6689b57a52 | |||
| 7029c699a0 | |||
| 3b9574af14 | |||
| 740f84dc22 | |||
| 55d45f9a98 | |||
| 61d1eeab6f | |||
| 133c1e866c | |||
| b730461894 | |||
| 8b08e22dbc | |||
| fc7c99fb0a | |||
| f1d267bb2d | |||
| 07664eedc0 | |||
| 64b8d7c874 | |||
| ccab07bd66 | |||
| 3a76d9a28e | |||
| 5720a5020d | |||
| b3e9e2099a | |||
| 93acf50bb4 | |||
| ff46a854f9 | |||
| 8c5f26ca5e | |||
| 5560b198ca | |||
| 9a413cf553 | |||
| bb5c491794 | |||
| 2f5d360e53 | |||
| 92e03dccb9 | |||
| 5ffe6284ca | |||
| fb98349bbd | |||
| 00a22ca12e | |||
| 3883adcefc | |||
| 0762ffa3dc | |||
| b70dc64d96 | |||
| 859751f74d | |||
| 91c451b6c5 | |||
| 30c7ed7e45 | |||
| 509b6f2056 | |||
| 558bebe710 | |||
| 08a85c5dae | |||
| d22f9ee294 | |||
| 0aeaf7c3b7 | |||
| c04bcef273 | |||
| 7fcea371c2 | |||
| dd765238f7 | |||
| 2c98a11696 | |||
| d4f14efaa0 | |||
| 27787c247b | |||
| ea9c07aa98 | |||
| 5cd9bfeb70 | |||
| b699196299 | |||
| e89c2aec4a | |||
| 456fb56e82 | |||
| 03ac828134 | |||
| 34b2264d5d | |||
| 933ede40f9 | |||
| 881dc33c9b | |||
| 3faa0d2603 | |||
| 1ce5087e2a | |||
| bf8d94eb35 | |||
| 9aac12f517 | |||
| 7b969173f4 | |||
| ca77d22035 | |||
| ad3bf35397 | |||
| 9b06221be0 | |||
| c0de178173 | |||
| 6a5face0aa | |||
| c15c54e920 | |||
| 24c079dca4 | |||
| 8eef7bb283 | |||
| 80493719f2 | |||
| df9d6bc506 | |||
| 71870cbd1c | |||
| f715ccd368 | |||
| 46edd56acc | |||
| 442850aebb | |||
| d4e752987e | |||
| 9c6a85ff16 | |||
| fa8d8eccc2 | |||
| 6e76f89ca2 | |||
| 9589bf6bf8 | |||
| ce5fa9502f | |||
| 7b1b05a35c | |||
| 38a86edc70 | |||
| 56b9b6f2c4 | |||
| 97dcba70cf | |||
| 6b93130c13 | |||
| 94c1a50cc8 | |||
| 31ab1d4287 | |||
| b6ba493450 | |||
| c613db2338 | |||
| 05ac8499df | |||
| 69244a094d | |||
| 1155673642 | |||
| 930079959c |
@@ -54,3 +54,5 @@ bin/
|
||||
/Win32
|
||||
/x64
|
||||
/client_files/**/CMakeFiles/
|
||||
|
||||
.idea
|
||||
|
||||
@@ -224,6 +224,9 @@ IF(OpenSSL_FOUND AND MBEDTLS_FOUND)
|
||||
SET(TLS_LIBRARY_LIBS ${OPENSSL_LIBRARIES})
|
||||
SET(TLS_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR})
|
||||
ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL)
|
||||
IF(${OPENSSL_VERSION} VERSION_GREATER_EQUAL "1.1.1")
|
||||
ADD_DEFINITIONS(-DCPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
ENDIF()
|
||||
ELSEIF(TLS_LIBRARY_SELECTION STREQUAL "mbedTLS")
|
||||
SET(TLS_LIBRARY_TYPE " mbedTLS")
|
||||
SET(TLS_LIBRARY_ENABLED ON)
|
||||
|
||||
@@ -18,16 +18,16 @@
|
||||
|**Install Count**|||
|
||||
### > Windows
|
||||
|
||||
* [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-windows)
|
||||
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-windows/)
|
||||
|
||||
### > Debian/Ubuntu/CentOS/Fedora
|
||||
|
||||
* [Install Guide](https://eqemu.gitbook.io/server/categories/installation/server-installation-linux)
|
||||
* [Install Guide](https://docs.eqemu.io/server/installation/server-installation-linux/)
|
||||
|
||||
* You can use curl or wget to kick off the installer (whichever your OS has)
|
||||
> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh
|
||||
|
||||
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
|
||||
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
|
||||
|
||||
## Supported Clients
|
||||
|
||||
@@ -56,7 +56,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://docs.eqemu.io/)
|
||||
|
||||
## Related Repositories
|
||||
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
############################################
|
||||
#
|
||||
# New changelog can be found here
|
||||
# https://eqemu.gitbook.io/changelog/
|
||||
# https://docs.eqemu.io/server/changelog/server
|
||||
#
|
||||
############################################
|
||||
# Deprecated
|
||||
|
||||
@@ -526,6 +526,7 @@ SET(common_headers
|
||||
guild_base.h
|
||||
guilds.h
|
||||
http/httplib.h
|
||||
http/uri.h
|
||||
inventory_profile.h
|
||||
inventory_slot.h
|
||||
ipc_mutex.h
|
||||
@@ -638,7 +639,8 @@ SET(common_headers
|
||||
StackWalker/StackWalker.h
|
||||
util/memory_stream.h
|
||||
util/directory.h
|
||||
util/uuid.h)
|
||||
util/uuid.h
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Event FILES
|
||||
event/event_loop.h
|
||||
|
||||
@@ -35,8 +35,12 @@ int WorldContentService::GetCurrentExpansion() const
|
||||
return current_expansion;
|
||||
}
|
||||
|
||||
void WorldContentService::SetExpansionContext()
|
||||
WorldContentService *WorldContentService::SetExpansionContext()
|
||||
{
|
||||
// do a rule manager reload until where we store expansion is changed to somewhere else
|
||||
RuleManager::Instance()->LoadRules(GetDatabase(), "default", true);
|
||||
|
||||
// pull expansion from rules
|
||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
||||
if (expansion >= Expansion::Classic && expansion <= Expansion::MaxId) {
|
||||
content_service.SetCurrentExpansion(expansion);
|
||||
@@ -47,6 +51,8 @@ void WorldContentService::SetExpansionContext()
|
||||
GetCurrentExpansion(),
|
||||
GetCurrentExpansionName()
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
std::string WorldContentService::GetCurrentExpansionName()
|
||||
@@ -73,15 +79,47 @@ void WorldContentService::SetCurrentExpansion(int current_expansion)
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
const std::vector<std::string> &WorldContentService::GetContentFlags() const
|
||||
const std::vector<ContentFlagsRepository::ContentFlags> &WorldContentService::GetContentFlags() const
|
||||
{
|
||||
return content_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::vector<std::string> WorldContentService::GetContentFlagsEnabled()
|
||||
{
|
||||
std::vector<std::string> enabled_flags;
|
||||
|
||||
for (auto &f: GetContentFlags()) {
|
||||
if (f.enabled) {
|
||||
enabled_flags.emplace_back(f.flag_name);
|
||||
}
|
||||
}
|
||||
|
||||
return enabled_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
|
||||
{
|
||||
std::vector<std::string> disabled_flags;
|
||||
|
||||
for (auto &f: GetContentFlags()) {
|
||||
if (!f.enabled) {
|
||||
disabled_flags.emplace_back(f.flag_name);
|
||||
}
|
||||
}
|
||||
|
||||
return disabled_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content_flags
|
||||
*/
|
||||
void WorldContentService::SetContentFlags(std::vector<std::string> content_flags)
|
||||
void WorldContentService::SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags)
|
||||
{
|
||||
WorldContentService::content_flags = content_flags;
|
||||
}
|
||||
@@ -90,10 +128,10 @@ void WorldContentService::SetContentFlags(std::vector<std::string> content_flags
|
||||
* @param content_flag
|
||||
* @return
|
||||
*/
|
||||
bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag)
|
||||
bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
|
||||
{
|
||||
for (auto &flag : GetContentFlags()) {
|
||||
if (flag == content_flag) {
|
||||
for (auto &f: GetContentFlags()) {
|
||||
if (f.flag_name == content_flag && f.enabled == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -101,20 +139,58 @@ bool WorldContentService::IsContentFlagEnabled(const std::string& content_flag)
|
||||
return false;
|
||||
}
|
||||
|
||||
void WorldContentService::ReloadContentFlags(Database &db)
|
||||
void WorldContentService::ReloadContentFlags()
|
||||
{
|
||||
std::vector<std::string> set_content_flags;
|
||||
auto content_flags = ContentFlagsRepository::GetWhere(db, "enabled = 1");
|
||||
std::vector<ContentFlagsRepository::ContentFlags> set_content_flags;
|
||||
auto flags = ContentFlagsRepository::All(*GetDatabase());
|
||||
|
||||
set_content_flags.reserve(content_flags.size());
|
||||
for (auto &flags: content_flags) {
|
||||
set_content_flags.push_back(flags.flag_name);
|
||||
set_content_flags.reserve(flags.size());
|
||||
for (auto &f: flags) {
|
||||
set_content_flags.push_back(f);
|
||||
|
||||
LogInfo(
|
||||
"Loaded content flag [{}] [{}]",
|
||||
f.flag_name,
|
||||
(f.enabled ? "Enabled" : "Disabled")
|
||||
);
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
"Enabled content flags [{}]",
|
||||
implode(", ", set_content_flags)
|
||||
);
|
||||
|
||||
SetContentFlags(set_content_flags);
|
||||
}
|
||||
|
||||
Database *WorldContentService::GetDatabase() const
|
||||
{
|
||||
return m_database;
|
||||
}
|
||||
|
||||
WorldContentService *WorldContentService::SetDatabase(Database *database)
|
||||
{
|
||||
WorldContentService::m_database = database;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
|
||||
{
|
||||
auto flags = ContentFlagsRepository::GetWhere(
|
||||
*GetDatabase(),
|
||||
fmt::format("flag_name = '{}'", content_flag_name)
|
||||
);
|
||||
|
||||
auto f = ContentFlagsRepository::NewEntity();
|
||||
if (!flags.empty()) {
|
||||
f = flags.front();
|
||||
}
|
||||
|
||||
f.enabled = enabled ? 1 : 0;
|
||||
f.flag_name = content_flag_name;
|
||||
|
||||
if (!flags.empty()) {
|
||||
ContentFlagsRepository::UpdateOne(*GetDatabase(), f);
|
||||
}
|
||||
else {
|
||||
ContentFlagsRepository::InsertOne(*GetDatabase(), f);
|
||||
}
|
||||
|
||||
ReloadContentFlags();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../repositories/content_flags_repository.h"
|
||||
|
||||
class Database;
|
||||
|
||||
@@ -160,15 +161,25 @@ public:
|
||||
bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; }
|
||||
bool IsCurrentExpansionTormentOfVelious() { return current_expansion == Expansion::ExpansionNumber::TormentOfVelious; }
|
||||
|
||||
const std::vector<ContentFlagsRepository::ContentFlags> &GetContentFlags() const;
|
||||
std::vector<std::string> GetContentFlagsEnabled();
|
||||
std::vector<std::string> GetContentFlagsDisabled();
|
||||
bool IsContentFlagEnabled(const std::string& content_flag);
|
||||
void SetContentFlags(std::vector<ContentFlagsRepository::ContentFlags> content_flags);
|
||||
void ReloadContentFlags();
|
||||
WorldContentService * SetExpansionContext();
|
||||
|
||||
WorldContentService * SetDatabase(Database *database);
|
||||
Database *GetDatabase() const;
|
||||
|
||||
void SetContentFlag(const std::string &content_flag_name, bool enabled);
|
||||
|
||||
private:
|
||||
int current_expansion{};
|
||||
std::vector<std::string> content_flags;
|
||||
public:
|
||||
const std::vector<std::string> &GetContentFlags() const;
|
||||
bool IsContentFlagEnabled(const std::string& content_flag);
|
||||
void SetContentFlags(std::vector<std::string> content_flags);
|
||||
void ReloadContentFlags(Database &db);
|
||||
void SetExpansionContext();
|
||||
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
|
||||
|
||||
// reference to database
|
||||
Database *m_database;
|
||||
};
|
||||
|
||||
extern WorldContentService content_service;
|
||||
|
||||
+126
-28
@@ -39,6 +39,7 @@
|
||||
#include "unix.h"
|
||||
#include <netinet/in.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "database.h"
|
||||
@@ -46,6 +47,8 @@
|
||||
#include "extprofile.h"
|
||||
#include "string_util.h"
|
||||
#include "database_schema.h"
|
||||
#include "http/httplib.h"
|
||||
#include "http/uri.h"
|
||||
|
||||
extern Client client;
|
||||
|
||||
@@ -713,7 +716,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
/* HoTT Ability */
|
||||
if(RuleB(Character, GrantHoTTOnCreate))
|
||||
{
|
||||
query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, rank) VALUES (%u, %i, %i)", character_id, 14, 1);
|
||||
query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)", character_id, 14, 1);
|
||||
results = QueryDatabase(query);
|
||||
}
|
||||
|
||||
@@ -2039,62 +2042,64 @@ void Database::ClearRaidLeader(uint32 gid, uint32 rid)
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win)
|
||||
void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win, bool remove)
|
||||
{
|
||||
|
||||
std::string field;
|
||||
|
||||
switch(theme)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
switch(theme) {
|
||||
case LDoNThemes::GUK: {
|
||||
field = "guk_";
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
case LDoNThemes::MIR: {
|
||||
field = "mir_";
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
case LDoNThemes::MMC: {
|
||||
field = "mmc_";
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
case LDoNThemes::RUJ: {
|
||||
field = "ruj_";
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
case LDoNThemes::TAK: {
|
||||
field = "tak_";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (win)
|
||||
field += "wins";
|
||||
else
|
||||
field += "losses";
|
||||
field += win ? "wins" : "losses";
|
||||
std::string field_operation = remove ? "-" : "+";
|
||||
|
||||
std::string query = StringFormat("UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u",field.c_str(), field.c_str(), char_id);
|
||||
std::string query = fmt::format(
|
||||
"UPDATE `adventure_stats` SET {} = {} {} 1 WHERE player_id = {}",
|
||||
field,
|
||||
field,
|
||||
field_operation,
|
||||
char_id
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (results.RowsAffected() != 0)
|
||||
if (results.RowsAffected() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
query = StringFormat("INSERT INTO `adventure_stats` SET %s=1, player_id=%u", field.c_str(), char_id);
|
||||
QueryDatabase(query);
|
||||
if (!remove) {
|
||||
query = fmt::format(
|
||||
"INSERT INTO `adventure_stats` SET {} = 1, player_id = {}",
|
||||
field,
|
||||
char_id
|
||||
);
|
||||
QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
std::string query = fmt::format(
|
||||
"SELECT "
|
||||
"`guk_wins`, "
|
||||
"`mir_wins`, "
|
||||
@@ -2109,7 +2114,7 @@ bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as)
|
||||
"FROM "
|
||||
"`adventure_stats` "
|
||||
"WHERE "
|
||||
"player_id = %u ",
|
||||
"player_id = {}",
|
||||
char_id
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
@@ -2268,6 +2273,35 @@ int Database::GetIPExemption(std::string account_ip) {
|
||||
return RuleI(World, MaxClientsPerIP);
|
||||
}
|
||||
|
||||
void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
|
||||
std::string query = fmt::format(
|
||||
"SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'",
|
||||
account_ip
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
uint32 exemption_id = 0;
|
||||
if (results.Success() && results.RowCount() > 0) {
|
||||
auto row = results.begin();
|
||||
exemption_id = atoi(row[0]);
|
||||
}
|
||||
|
||||
query = fmt::format(
|
||||
"INSERT INTO `ip_exemptions` (`exemption_ip`, `exemption_amount`) VALUES ('{}', {})",
|
||||
account_ip,
|
||||
exemption_amount
|
||||
);
|
||||
|
||||
if (exemption_id != 0) {
|
||||
query = fmt::format(
|
||||
"UPDATE `ip_exemptions` SET `exemption_amount` = {} WHERE `exemption_ip` = '{}'",
|
||||
exemption_amount,
|
||||
account_ip
|
||||
);
|
||||
}
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
|
||||
std::string query = StringFormat("SELECT instance_list.id FROM instance_list INNER JOIN instance_list_player ON instance_list.id = instance_list_player.id WHERE instance_list.zone = '%i' AND instance_list_player.charid = '%i'", zone_id, char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
@@ -2418,3 +2452,67 @@ bool Database::CopyCharacter(
|
||||
return true;
|
||||
}
|
||||
|
||||
void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string url)
|
||||
{
|
||||
try {
|
||||
uri request_uri(url);
|
||||
|
||||
LogHTTP(
|
||||
"[SourceDatabaseTableFromUrl] parsing url [{}] path [{}] host [{}] query_string [{}] protocol [{}] port [{}]",
|
||||
url,
|
||||
request_uri.get_path(),
|
||||
request_uri.get_host(),
|
||||
request_uri.get_query(),
|
||||
request_uri.get_scheme(),
|
||||
request_uri.get_port()
|
||||
);
|
||||
|
||||
if (!DoesTableExist(table_name)) {
|
||||
LogMySQLQuery("Table [{}] does not exist. Downloading from Github and installing...", table_name);
|
||||
|
||||
// http get request
|
||||
httplib::Client cli(
|
||||
fmt::format(
|
||||
"{}://{}",
|
||||
request_uri.get_scheme(),
|
||||
request_uri.get_host()
|
||||
).c_str()
|
||||
);
|
||||
|
||||
cli.set_connection_timeout(0, 60000000); // 60 sec
|
||||
cli.set_read_timeout(60, 0); // 60 seconds
|
||||
cli.set_write_timeout(60, 0); // 60 seconds
|
||||
|
||||
int sourced_queries = 0;
|
||||
|
||||
if (auto res = cli.Get(request_uri.get_path().c_str())) {
|
||||
if (res->status == 200) {
|
||||
for (auto &s: SplitString(res->body, ';')) {
|
||||
if (!trim(s).empty()) {
|
||||
auto results = QueryDatabase(s);
|
||||
if (!results.ErrorMessage().empty()) {
|
||||
LogError("Error sourcing SQL [{}]", results.ErrorMessage());
|
||||
return;
|
||||
}
|
||||
sourced_queries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogError("Error retrieving URL [{}]", url);
|
||||
}
|
||||
|
||||
LogMySQLQuery(
|
||||
"Table [{}] installed. Sourced [{}] queries",
|
||||
table_name,
|
||||
sourced_queries
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::invalid_argument iae) {
|
||||
LogError("[SourceDatabaseTableFromUrl] URI parser error [{}]", iae.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -176,7 +176,7 @@ public:
|
||||
|
||||
/* Adventure related. */
|
||||
|
||||
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win);
|
||||
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win = false, bool remove = false);
|
||||
bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
|
||||
|
||||
/* Account Related */
|
||||
@@ -198,7 +198,8 @@ public:
|
||||
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
||||
void SetAgreementFlag(uint32 acctid);
|
||||
|
||||
int GetIPExemption(std::string account_ip);
|
||||
int GetIPExemption(std::string account_ip);
|
||||
void SetIPExemption(std::string account_ip, int exemption_amount);
|
||||
|
||||
int GetInstanceID(uint32 char_id, uint32 zone_id);
|
||||
|
||||
@@ -269,6 +270,8 @@ public:
|
||||
int CountInvSnapshots();
|
||||
void ClearInvSnapshots(bool from_now = false);
|
||||
|
||||
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ bool Database::CheckDatabaseConversions() {
|
||||
CheckDatabaseConvertCorpseDeblob();
|
||||
|
||||
/* Run EQEmu Server script (Checks for database updates) */
|
||||
if(system("perl eqemu_server.pl ran_from_world"));
|
||||
system("perl eqemu_server.pl ran_from_world");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1452,7 +1452,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){
|
||||
if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){
|
||||
if (first_entry != 1){
|
||||
rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
|
||||
rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
|
||||
first_entry = 1;
|
||||
}
|
||||
rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace DatabaseSchema {
|
||||
{"player_titlesets", "char_id"},
|
||||
{"quest_globals", "charid"},
|
||||
{"timers", "char_id"},
|
||||
{"titles", "char_id"},
|
||||
{"trader", "char_id"},
|
||||
{"zone_flags", "charID"}
|
||||
};
|
||||
@@ -158,7 +157,6 @@ namespace DatabaseSchema {
|
||||
"spell_buckets",
|
||||
"spell_globals",
|
||||
"timers",
|
||||
"titles",
|
||||
"trader",
|
||||
"trader_audit",
|
||||
"zone_flags"
|
||||
@@ -270,6 +268,7 @@ namespace DatabaseSchema {
|
||||
"perl_event_export_settings",
|
||||
"profanity_list",
|
||||
"rule_sets",
|
||||
"titles",
|
||||
"rule_values",
|
||||
"variables",
|
||||
};
|
||||
|
||||
@@ -561,8 +561,9 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
|
||||
return "Mission";
|
||||
case DynamicZoneType::Quest:
|
||||
return "Quest";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
|
||||
|
||||
+231
-1
@@ -18,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "emu_constants.h"
|
||||
#include "languages.h"
|
||||
#include "data_verification.h"
|
||||
#include "bodytypes.h"
|
||||
|
||||
|
||||
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
|
||||
@@ -147,8 +150,235 @@ const char *EQ::constants::GetStanceName(StanceType stance_type) {
|
||||
}
|
||||
|
||||
int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
|
||||
if (stance_type >= EQ::constants::stancePassive && stance_type <= EQ::constants::stanceBurnAE)
|
||||
if (EQ::ValueWithin(stance_type, EQ::constants::stancePassive, EQ::constants::stanceBurnAE)) {
|
||||
return (stance_type - EQ::constants::stancePassive);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::map<int, std::string>& EQ::constants::GetLanguageMap()
|
||||
{
|
||||
static const std::map<int, std::string> language_map = {
|
||||
{ LANG_COMMON_TONGUE, "Common Tongue" },
|
||||
{ LANG_BARBARIAN, "Barbarian" },
|
||||
{ LANG_ERUDIAN, "Erudian" },
|
||||
{ LANG_ELVISH, "Elvish" },
|
||||
{ LANG_DARK_ELVISH, "Dark Elvish" },
|
||||
{ LANG_DWARVISH, "Dwarvish" },
|
||||
{ LANG_TROLL, "Troll" },
|
||||
{ LANG_OGRE, "Ogre" },
|
||||
{ LANG_GNOMISH, "Gnomish" },
|
||||
{ LANG_HALFLING, "Halfling" },
|
||||
{ LANG_THIEVES_CANT, "Thieves Cant" },
|
||||
{ LANG_OLD_ERUDIAN, "Old Erudian" },
|
||||
{ LANG_ELDER_ELVISH, "Elder Elvish" },
|
||||
{ LANG_FROGLOK, "Froglok" },
|
||||
{ LANG_GOBLIN, "Goblin" },
|
||||
{ LANG_GNOLL, "Gnoll" },
|
||||
{ LANG_COMBINE_TONGUE, "Combine Tongue" },
|
||||
{ LANG_ELDER_TEIRDAL, "Elder Teirdal" },
|
||||
{ LANG_LIZARDMAN, "Lizardman" },
|
||||
{ LANG_ORCISH, "Orcish" },
|
||||
{ LANG_FAERIE, "Faerie" },
|
||||
{ LANG_DRAGON, "Dragon" },
|
||||
{ LANG_ELDER_DRAGON, "Elder Dragon" },
|
||||
{ LANG_DARK_SPEECH, "Dark Speech" },
|
||||
{ LANG_VAH_SHIR, "Vah Shir" },
|
||||
{ LANG_ALARAN, "Alaran" },
|
||||
{ LANG_HADAL, "Hadal" },
|
||||
{ LANG_UNKNOWN, "Unknown" }
|
||||
};
|
||||
return language_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetLanguageName(int language_id)
|
||||
{
|
||||
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
||||
auto languages = EQ::constants::GetLanguageMap();
|
||||
return languages[language_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint32, std::string>& EQ::constants::GetLDoNThemeMap()
|
||||
{
|
||||
static const std::map<uint32, std::string> ldon_theme_map = {
|
||||
{ LDoNThemes::Unused, "Unused" },
|
||||
{ LDoNThemes::GUK, "Deepest Guk" },
|
||||
{ LDoNThemes::MIR, "Miragul's Menagerie" },
|
||||
{ LDoNThemes::MMC, "Mistmoore Catacombs" },
|
||||
{ LDoNThemes::RUJ, "Rujarkian Hills" },
|
||||
{ LDoNThemes::TAK, "Takish-Hiz" },
|
||||
};
|
||||
return ldon_theme_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetLDoNThemeName(uint32 theme_id)
|
||||
{
|
||||
if (EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) {
|
||||
auto ldon_themes = EQ::constants::GetLDoNThemeMap();
|
||||
return ldon_themes[theme_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetFlyModeMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> flymode_map = {
|
||||
{ GravityBehavior::Ground, "Ground" },
|
||||
{ GravityBehavior::Flying, "Flying" },
|
||||
{ GravityBehavior::Levitating, "Levitating" },
|
||||
{ GravityBehavior::Water, "Water" },
|
||||
{ GravityBehavior::Floating, "Floating" },
|
||||
{ GravityBehavior::LevitateWhileRunning, "Levitating While Running" },
|
||||
};
|
||||
return flymode_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetFlyModeName(uint8 flymode_id)
|
||||
{
|
||||
if (EQ::ValueWithin(flymode_id, GravityBehavior::Ground, GravityBehavior::LevitateWhileRunning)) {
|
||||
auto flymodes = EQ::constants::GetFlyModeMap();
|
||||
return flymodes[flymode_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
|
||||
{
|
||||
static const std::map<bodyType, std::string> bodytype_map = {
|
||||
{ BT_Humanoid, "Humanoid" },
|
||||
{ BT_Lycanthrope, "Lycanthrope" },
|
||||
{ BT_Undead, "Undead" },
|
||||
{ BT_Giant, "Giant" },
|
||||
{ BT_Construct, "Construct" },
|
||||
{ BT_Extraplanar, "Extraplanar" },
|
||||
{ BT_Magical, "Magical" },
|
||||
{ BT_SummonedUndead, "Summoned Undead" },
|
||||
{ BT_RaidGiant, "Raid Giant" },
|
||||
{ BT_RaidColdain, "Raid Coldain" },
|
||||
{ BT_NoTarget, "Untargetable" },
|
||||
{ BT_Vampire, "Vampire" },
|
||||
{ BT_Atenha_Ra, "Aten Ha Ra" },
|
||||
{ BT_Greater_Akheva, "Greater Akheva" },
|
||||
{ BT_Khati_Sha, "Khati Sha" },
|
||||
{ BT_Seru, "Seru" },
|
||||
{ BT_Grieg_Veneficus, "Grieg Veneficus" },
|
||||
{ BT_Draz_Nurakk, "Draz Nurakk" },
|
||||
{ BT_Zek, "Zek" },
|
||||
{ BT_Luggald, "Luggald" },
|
||||
{ BT_Animal, "Animal" },
|
||||
{ BT_Insect, "Insect" },
|
||||
{ BT_Monster, "Monster" },
|
||||
{ BT_Summoned, "Summoned" },
|
||||
{ BT_Plant, "Plant" },
|
||||
{ BT_Dragon, "Dragon" },
|
||||
{ BT_Summoned2, "Summoned 2" },
|
||||
{ BT_Summoned3, "Summoned 3" },
|
||||
{ BT_Dragon2, "Dragon 2" },
|
||||
{ BT_VeliousDragon, "Velious Dragon" },
|
||||
{ BT_Familiar, "Familiar" },
|
||||
{ BT_Dragon3, "Dragon 3" },
|
||||
{ BT_Boxes, "Boxes" },
|
||||
{ BT_Muramite, "Muramite" },
|
||||
{ BT_NoTarget2, "Untargetable 2" },
|
||||
{ BT_SwarmPet, "Swarm Pet" },
|
||||
{ BT_MonsterSummon, "Monster Summon" },
|
||||
{ BT_InvisMan, "Invisible Man" },
|
||||
{ BT_Special, "Special" },
|
||||
};
|
||||
return bodytype_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id)
|
||||
{
|
||||
auto bodytypes = EQ::constants::GetBodyTypeMap();
|
||||
if (!bodytypes[bodytype_id].empty()) {
|
||||
return bodytypes[bodytype_id];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetAccountStatusMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> account_status_map = {
|
||||
{ AccountStatus::Player, "Player" },
|
||||
{ AccountStatus::Steward, "Steward" },
|
||||
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
|
||||
{ AccountStatus::Guide, "Guide" },
|
||||
{ AccountStatus::QuestTroupe, "Quest Troupe" },
|
||||
{ AccountStatus::SeniorGuide, "Senior Guide" },
|
||||
{ AccountStatus::GMTester, "GM Tester" },
|
||||
{ AccountStatus::EQSupport, "EQ Support" },
|
||||
{ AccountStatus::GMStaff, "GM Staff" },
|
||||
{ AccountStatus::GMAdmin, "GM Admin" },
|
||||
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
|
||||
{ AccountStatus::QuestMaster, "Quest Master" },
|
||||
{ AccountStatus::GMAreas, "GM Areas" },
|
||||
{ AccountStatus::GMCoder, "GM Coder" },
|
||||
{ AccountStatus::GMMgmt, "GM Mgmt" },
|
||||
{ AccountStatus::GMImpossible, "GM Impossible" },
|
||||
{ AccountStatus::Max, "GM Max" }
|
||||
};
|
||||
return account_status_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetAccountStatusName(uint8 account_status)
|
||||
{
|
||||
auto account_statuses = EQ::constants::GetAccountStatusMap();
|
||||
std::string status_name;
|
||||
for (auto status_level = account_statuses.rbegin(); status_level != account_statuses.rend(); ++status_level) {
|
||||
if (account_status >= status_level->first) {
|
||||
status_name = status_level->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status_name;
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> consider_level_map = {
|
||||
{ ConsiderLevel::Ally, "Ally" },
|
||||
{ ConsiderLevel::Warmly, "Warmly" },
|
||||
{ ConsiderLevel::Kindly, "Kindly" },
|
||||
{ ConsiderLevel::Amiably, "Amiably" },
|
||||
{ ConsiderLevel::Indifferently, "Indifferently" },
|
||||
{ ConsiderLevel::Apprehensively, "Apprehensively" },
|
||||
{ ConsiderLevel::Dubiously, "Dubiously" },
|
||||
{ ConsiderLevel::Threateningly, "Threateningly" },
|
||||
{ ConsiderLevel::Scowls, "Scowls" }
|
||||
};
|
||||
return consider_level_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetConsiderLevelName(uint8 faction_consider_level)
|
||||
{
|
||||
auto consider_levels = EQ::constants::GetConsiderLevelMap();
|
||||
if (!consider_levels[faction_consider_level].empty()) {
|
||||
return consider_levels[faction_consider_level];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::map<uint8, std::string>& EQ::constants::GetEnvironmentalDamageMap()
|
||||
{
|
||||
static const std::map<uint8, std::string> damage_type_map = {
|
||||
{ EnvironmentalDamage::Lava, "Lava" },
|
||||
{ EnvironmentalDamage::Drowning, "Drowning" },
|
||||
{ EnvironmentalDamage::Falling, "Falling" },
|
||||
{ EnvironmentalDamage::Trap, "Trap" }
|
||||
};
|
||||
return damage_type_map;
|
||||
}
|
||||
|
||||
std::string EQ::constants::GetEnvironmentalDamageName(uint8 damage_type)
|
||||
{
|
||||
if (EQ::ValueWithin(damage_type, EnvironmentalDamage::Lava, EnvironmentalDamage::Trap)) {
|
||||
auto damage_types = EQ::constants::GetEnvironmentalDamageMap();
|
||||
return damage_types[damage_type];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
+89
-7
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "eq_limits.h"
|
||||
#include "emu_versions.h"
|
||||
#include "bodytypes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -220,9 +221,46 @@ namespace EQ
|
||||
stanceBurnAE
|
||||
};
|
||||
|
||||
enum GravityBehavior : uint8 {
|
||||
Ground,
|
||||
Flying,
|
||||
Levitating,
|
||||
Water,
|
||||
Floating,
|
||||
LevitateWhileRunning
|
||||
};
|
||||
|
||||
enum EnvironmentalDamage : uint8 {
|
||||
Lava = 250,
|
||||
Drowning,
|
||||
Falling,
|
||||
Trap
|
||||
};
|
||||
|
||||
const char *GetStanceName(StanceType stance_type);
|
||||
int ConvertStanceTypeToIndex(StanceType stance_type);
|
||||
|
||||
extern const std::map<int, std::string>& GetLanguageMap();
|
||||
std::string GetLanguageName(int language_id);
|
||||
|
||||
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
|
||||
std::string GetLDoNThemeName(uint32 theme_id);
|
||||
|
||||
extern const std::map<uint8, std::string>& GetFlyModeMap();
|
||||
std::string GetFlyModeName(uint8 flymode_id);
|
||||
|
||||
extern const std::map<bodyType, std::string>& GetBodyTypeMap();
|
||||
std::string GetBodyTypeName(bodyType bodytype_id);
|
||||
|
||||
extern const std::map<uint8, std::string>& GetAccountStatusMap();
|
||||
std::string GetAccountStatusName(uint8 account_status);
|
||||
|
||||
extern const std::map<uint8, std::string>& GetConsiderLevelMap();
|
||||
std::string GetConsiderLevelName(uint8 consider_level);
|
||||
|
||||
extern const std::map<uint8, std::string>& GetEnvironmentalDamageMap();
|
||||
std::string GetEnvironmentalDamageName(uint8 damage_type);
|
||||
|
||||
const int STANCE_TYPE_FIRST = stancePassive;
|
||||
const int STANCE_TYPE_LAST = stanceBurnAE;
|
||||
const int STANCE_TYPE_COUNT = stanceBurnAE;
|
||||
@@ -325,13 +363,57 @@ namespace EQ
|
||||
Guild
|
||||
};
|
||||
}; // namespace consent
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
enum ServerLockType : int {
|
||||
List,
|
||||
Lock,
|
||||
Unlock
|
||||
};
|
||||
|
||||
enum AccountStatus : uint8 {
|
||||
Player = 0,
|
||||
Steward = 10,
|
||||
ApprenticeGuide = 20,
|
||||
Guide = 50,
|
||||
QuestTroupe = 80,
|
||||
SeniorGuide = 81,
|
||||
GMTester = 85,
|
||||
EQSupport = 90,
|
||||
GMStaff = 95,
|
||||
GMAdmin = 100,
|
||||
GMLeadAdmin = 150,
|
||||
QuestMaster = 160,
|
||||
GMAreas = 170,
|
||||
GMCoder = 180,
|
||||
GMMgmt = 200,
|
||||
GMImpossible = 250,
|
||||
Max = 255
|
||||
};
|
||||
|
||||
enum Invisibility : uint8 {
|
||||
Visible,
|
||||
Invisible,
|
||||
Special = 255
|
||||
};
|
||||
|
||||
enum AugmentActions : int {
|
||||
Insert,
|
||||
Remove,
|
||||
Swap,
|
||||
Destroy
|
||||
};
|
||||
|
||||
enum ConsiderLevel : uint8 {
|
||||
Ally = 1,
|
||||
Warmly,
|
||||
Kindly,
|
||||
Amiably,
|
||||
Indifferently,
|
||||
Apprehensively,
|
||||
Dubiously,
|
||||
Threateningly,
|
||||
Scowls
|
||||
};
|
||||
|
||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||
|
||||
/* hack list to prevent circular references
|
||||
|
||||
eq_limits.h:EQ::inventory::LookupEntry::InventoryTypeSize[n];
|
||||
|
||||
*/
|
||||
|
||||
+2
-2
@@ -129,8 +129,8 @@ N(OP_DisciplineTimer),
|
||||
N(OP_DisciplineUpdate),
|
||||
N(OP_DiscordMerchantInventory),
|
||||
N(OP_DoGroupLeadershipAbility),
|
||||
N(OP_DuelResponse),
|
||||
N(OP_DuelResponse2),
|
||||
N(OP_DuelDecline),
|
||||
N(OP_DuelAccept),
|
||||
N(OP_DumpName),
|
||||
N(OP_Dye),
|
||||
N(OP_DynamicWall),
|
||||
|
||||
@@ -974,4 +974,39 @@ enum class DynamicZoneMemberStatus : uint8_t
|
||||
LinkDead
|
||||
};
|
||||
|
||||
enum LDoNThemes {
|
||||
Unused = 0,
|
||||
GUK,
|
||||
MIR,
|
||||
MMC,
|
||||
RUJ,
|
||||
TAK
|
||||
};
|
||||
|
||||
enum LDoNThemeBits {
|
||||
UnusedBit = 0,
|
||||
GUKBit = 1,
|
||||
MIRBit = 2,
|
||||
MMCBit = 4,
|
||||
RUJBit = 8,
|
||||
TAKBit = 16
|
||||
};
|
||||
|
||||
enum StartZoneIndex {
|
||||
Odus = 0,
|
||||
Qeynos,
|
||||
Halas,
|
||||
Rivervale,
|
||||
Freeport,
|
||||
Neriak,
|
||||
Grobb,
|
||||
Oggok,
|
||||
Kaladim,
|
||||
GreaterFaydark,
|
||||
Felwithe,
|
||||
Akanon,
|
||||
Cabilis,
|
||||
SharVahl
|
||||
};
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
@@ -384,7 +384,9 @@ struct NewZone_Struct {
|
||||
/*0716*/ uint32 FastRegenEndurance;
|
||||
/*0720*/ uint32 NPCAggroMaxDist;
|
||||
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
|
||||
/*0728*/
|
||||
/*0728*/ uint32 LavaDamage; // Seen 50
|
||||
/*0732*/ uint32 MinLavaDamage; // Seen 10
|
||||
/*0736*/
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -446,6 +448,7 @@ struct ManaChange_Struct
|
||||
/*08*/ uint32 spell_id;
|
||||
/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting?
|
||||
/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like
|
||||
/*16*/ int32 slot; // -1 normal, otherwise clear ETA and GCD
|
||||
};
|
||||
|
||||
struct SwapSpell_Struct
|
||||
@@ -2759,7 +2762,7 @@ struct EnvDamage2_Struct {
|
||||
/*0004*/ uint16 unknown4;
|
||||
/*0006*/ uint32 damage;
|
||||
/*0010*/ uint8 unknown10[12];
|
||||
/*0022*/ uint8 dmgtype; //FA = Lava; FC = Falling
|
||||
/*0022*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
|
||||
/*0023*/ uint8 unknown2[4];
|
||||
/*0027*/ uint16 constant; //Always FFFF
|
||||
/*0029*/ uint16 unknown29;
|
||||
@@ -4340,8 +4343,8 @@ struct AARankPrereq_Struct
|
||||
struct AARankEffect_Struct
|
||||
{
|
||||
int32 effect_id;
|
||||
int32 base1;
|
||||
int32 base2;
|
||||
int32 base_value;
|
||||
int32 limit_value;
|
||||
int32 slot;
|
||||
};
|
||||
|
||||
@@ -4349,8 +4352,8 @@ struct AARankEffect_Struct
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
/*08*/ uint32 base2;
|
||||
/*04*/ uint32 base_value;
|
||||
/*08*/ uint32 limit_value;
|
||||
/*12*/ uint32 slot;
|
||||
};
|
||||
|
||||
|
||||
+14
-1
@@ -44,6 +44,12 @@ void EQEmuConfig::parse_config()
|
||||
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
|
||||
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
||||
LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString();
|
||||
|
||||
// at least today, this is wrong a majority of the time
|
||||
// remove this if eqemulator ever upgrades its loginserver
|
||||
if (LoginHost.find("login.eqemulator.net") != std::string::npos) {
|
||||
LoginLegacy = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char str[32];
|
||||
@@ -62,12 +68,19 @@ void EQEmuConfig::parse_config()
|
||||
|
||||
loginconfig->LoginLegacy = false;
|
||||
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") { loginconfig->LoginLegacy = true; }
|
||||
|
||||
// at least today, this is wrong a majority of the time
|
||||
// remove this if eqemulator ever upgrades its loginserver
|
||||
if (loginconfig->LoginHost.find("login.eqemulator.net") != std::string::npos) {
|
||||
loginconfig->LoginLegacy = true;
|
||||
}
|
||||
|
||||
loginlist.Insert(loginconfig);
|
||||
} while (LoginCount < 100);
|
||||
}
|
||||
|
||||
|
||||
//<locked> from xml converts to json as locked: "", so i default to "false".
|
||||
//<locked> from xml converts to json as locked: "", so i default to "false".
|
||||
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
|
||||
Locked = false;
|
||||
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
|
||||
|
||||
@@ -130,6 +130,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::Loot].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Scheduler].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General);
|
||||
log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||
|
||||
/**
|
||||
* RFC 5424
|
||||
|
||||
@@ -125,6 +125,8 @@ namespace Logs {
|
||||
Cheat,
|
||||
ClientList,
|
||||
DiaWind,
|
||||
HTTP,
|
||||
Saylink,
|
||||
MaxCategoryID /* Don't Remove this */
|
||||
};
|
||||
|
||||
@@ -208,6 +210,8 @@ namespace Logs {
|
||||
"Cheat",
|
||||
"ClientList",
|
||||
"DialogueWindow",
|
||||
"HTTP",
|
||||
"Saylink",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -676,6 +676,26 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::DiaWind, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogHTTP(message, ...) do {\
|
||||
if (LogSys.log_settings[Logs::HTTP].is_category_enabled == 1)\
|
||||
OutF(LogSys, Logs::General, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogHTTPDetail(message, ...) do {\
|
||||
if (LogSys.log_settings[Logs::HTTP].is_category_enabled == 1)\
|
||||
OutF(LogSys, Logs::Detail, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogSaylink(message, ...) do {\
|
||||
if (LogSys.log_settings[Logs::Saylink].is_category_enabled == 1)\
|
||||
OutF(LogSys, Logs::General, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogSaylinkDetail(message, ...) do {\
|
||||
if (LogSys.log_settings[Logs::Saylink].is_category_enabled == 1)\
|
||||
OutF(LogSys, Logs::Detail, Logs::Saylink, __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__);\
|
||||
@@ -1066,6 +1086,12 @@
|
||||
#define LogDiaWindDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHTTP(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define LogHTTPDetail(message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
#define Log(debug_level, log_category, message, ...) do {\
|
||||
} while (0)
|
||||
|
||||
|
||||
+22
-22
@@ -20,31 +20,31 @@
|
||||
#include "races.h"
|
||||
#include "rulesys.h"
|
||||
|
||||
const char *FactionValueToString(FACTION_VALUE fv)
|
||||
const char *FactionValueToString(FACTION_VALUE faction_value)
|
||||
{
|
||||
switch (fv) {
|
||||
switch (faction_value) {
|
||||
case FACTION_ALLY:
|
||||
return ("Ally");
|
||||
return "Ally";
|
||||
case FACTION_WARMLY:
|
||||
return ("Warmly");
|
||||
return "Warmly";
|
||||
case FACTION_KINDLY:
|
||||
return ("Kindly");
|
||||
case FACTION_AMIABLE:
|
||||
return ("Amiable");
|
||||
case FACTION_INDIFFERENT:
|
||||
return ("Indifferent");
|
||||
case FACTION_APPREHENSIVE:
|
||||
return ("Apprehensive");
|
||||
case FACTION_DUBIOUS:
|
||||
return ("Dubious");
|
||||
case FACTION_THREATENLY:
|
||||
return ("Threatenly");
|
||||
return "Kindly";
|
||||
case FACTION_AMIABLY:
|
||||
return "Amiably";
|
||||
case FACTION_INDIFFERENTLY:
|
||||
return "Indifferently";
|
||||
case FACTION_APPREHENSIVELY:
|
||||
return "Apprehensively";
|
||||
case FACTION_DUBIOUSLY:
|
||||
return "Dubiously";
|
||||
case FACTION_THREATENINGLY:
|
||||
return "Threateningly";
|
||||
case FACTION_SCOWLS:
|
||||
return ("Scowls, ready to attack.");
|
||||
return "Scowls";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ("Unknown Faction Con");
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
||||
@@ -70,19 +70,19 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
|
||||
return FACTION_KINDLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) {
|
||||
return FACTION_AMIABLE;
|
||||
return FACTION_AMIABLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) {
|
||||
return FACTION_INDIFFERENT;
|
||||
return FACTION_INDIFFERENTLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) {
|
||||
return FACTION_APPREHENSIVE;
|
||||
return FACTION_APPREHENSIVELY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) {
|
||||
return FACTION_DUBIOUS;
|
||||
return FACTION_DUBIOUSLY;
|
||||
}
|
||||
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) {
|
||||
return FACTION_THREATENLY;
|
||||
return FACTION_THREATENINGLY;
|
||||
}
|
||||
return FACTION_SCOWLS;
|
||||
}
|
||||
|
||||
+6
-6
@@ -27,13 +27,13 @@ enum FACTION_VALUE {
|
||||
FACTION_ALLY = 1,
|
||||
FACTION_WARMLY = 2,
|
||||
FACTION_KINDLY = 3,
|
||||
FACTION_AMIABLE = 4,
|
||||
FACTION_AMIABLY = 4,
|
||||
|
||||
FACTION_INDIFFERENT = 5,
|
||||
FACTION_INDIFFERENTLY = 5,
|
||||
|
||||
FACTION_APPREHENSIVE = 6,
|
||||
FACTION_DUBIOUS = 7,
|
||||
FACTION_THREATENLY = 8,
|
||||
FACTION_APPREHENSIVELY = 6,
|
||||
FACTION_DUBIOUSLY = 7,
|
||||
FACTION_THREATENINGLY = 8,
|
||||
FACTION_SCOWLS = 9
|
||||
};
|
||||
|
||||
@@ -75,6 +75,6 @@ struct NPCFaction
|
||||
uint8 temp;
|
||||
};
|
||||
|
||||
const char *FactionValueToString(FACTION_VALUE fv);
|
||||
const char *FactionValueToString(FACTION_VALUE faction_value);
|
||||
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ enum { //some random constants
|
||||
#define MIN_LEVEL_ALCHEMY 25
|
||||
|
||||
//chance ratio that a
|
||||
#define THREATENLY_ARRGO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
|
||||
#define THREATENINGLY_AGGRO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
|
||||
|
||||
//max factions per npc faction list
|
||||
#define MAX_NPC_FACTIONS 20
|
||||
|
||||
@@ -64,4 +64,9 @@ void FileUtil::mkdir(const std::string& directory_name)
|
||||
}
|
||||
::mkdir(directory_name.c_str(), 0755);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool file_exists(const std::string& name) {
|
||||
std::ifstream f(name.c_str());
|
||||
return f.good();
|
||||
}
|
||||
|
||||
@@ -28,5 +28,6 @@ public:
|
||||
static void mkdir(const std::string& directory_name);
|
||||
};
|
||||
|
||||
bool file_exists(const std::string& name);
|
||||
|
||||
#endif //EQEMU_FILE_UTIL_H
|
||||
|
||||
+66
-6
@@ -63,7 +63,7 @@ bool BaseGuildManager::LoadGuilds() {
|
||||
for (auto row=results.begin();row!=results.end();++row)
|
||||
_CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]);
|
||||
|
||||
query = "SELECT guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
|
||||
query = "SELECT guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace FROM guild_ranks";
|
||||
results = m_db->QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
@@ -131,7 +131,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
||||
|
||||
info = _CreateGuild(guild_id, row[0], atoi(row[1]), atoi(row[2]), row[3], row[4], row[5], row[6]);
|
||||
|
||||
query = StringFormat("SELECT guild_id, rank, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
|
||||
query = StringFormat("SELECT guild_id, `rank`, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace "
|
||||
"FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id);
|
||||
results = m_db->QueryDatabase(query);
|
||||
|
||||
@@ -268,7 +268,7 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
|
||||
m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length());
|
||||
|
||||
query = StringFormat("INSERT INTO guild_ranks "
|
||||
"(guild_id,rank,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)"
|
||||
"(guild_id,`rank`,title,can_hear,can_speak,can_invite,can_remove,can_promote,can_demote,can_motd,can_warpeace)"
|
||||
" VALUES(%d,%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d)",
|
||||
guild_id, rank, title_esc,
|
||||
rankInfo.permissions[GUILD_HEAR],
|
||||
@@ -738,7 +738,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
||||
std::string query;
|
||||
|
||||
if(guild_id != GUILD_NONE) {
|
||||
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
|
||||
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,`rank`,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
@@ -758,7 +758,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
||||
}
|
||||
|
||||
bool BaseGuildManager::DBSetGuildRank(uint32 charid, uint8 rank) {
|
||||
std::string query = StringFormat("UPDATE guild_members SET rank=%d WHERE char_id=%d", rank, charid);
|
||||
std::string query = StringFormat("UPDATE guild_members SET `rank`=%d WHERE char_id=%d", rank, charid);
|
||||
return(QueryWithLogging(query, "setting a guild member's rank"));
|
||||
}
|
||||
|
||||
@@ -1208,7 +1208,7 @@ BaseGuildManager::RankInfo::RankInfo() {
|
||||
|
||||
BaseGuildManager::GuildInfo::GuildInfo() {
|
||||
leader_char_id = 0;
|
||||
minstatus = 0;
|
||||
minstatus = AccountStatus::Player;
|
||||
}
|
||||
|
||||
uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
|
||||
@@ -1225,6 +1225,66 @@ uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
|
||||
return results.RowCount();
|
||||
}
|
||||
|
||||
std::string BaseGuildManager::GetGuildNameByID(uint32 guild_id) const {
|
||||
if(guild_id == GUILD_NONE) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||
res = m_guilds.find(guild_id);
|
||||
if(res == m_guilds.end()) {
|
||||
return "Invalid Guild";
|
||||
}
|
||||
|
||||
return res->second->name;
|
||||
}
|
||||
|
||||
std::string BaseGuildManager::GetGuildRankName(uint32 guild_id, uint8 rank) const
|
||||
{
|
||||
if(rank > GUILD_MAX_RANK) {
|
||||
return "Invalid Rank";
|
||||
}
|
||||
|
||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||
res = m_guilds.find(guild_id);
|
||||
if(res == m_guilds.end()) {
|
||||
return "Invalid Guild Rank";
|
||||
}
|
||||
|
||||
return res->second->ranks[rank].name;
|
||||
}
|
||||
|
||||
uint32 BaseGuildManager::GetGuildIDByCharacterID(uint32 character_id)
|
||||
{
|
||||
if(!m_db) {
|
||||
return GUILD_NONE;
|
||||
}
|
||||
|
||||
std::string query = fmt::format(
|
||||
"SELECT `guild_id` FROM `guild_members` WHERE char_id = {} LIMIT 1",
|
||||
character_id
|
||||
);
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
if(!results.Success() || !results.RowCount()) {
|
||||
return GUILD_NONE;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
auto guild_id = std::stoul(row[0]);
|
||||
return guild_id;
|
||||
}
|
||||
|
||||
bool BaseGuildManager::IsCharacterInGuild(uint32 character_id, uint32 guild_id)
|
||||
{
|
||||
auto current_guild_id = GetGuildIDByCharacterID(character_id);
|
||||
|
||||
if (current_guild_id == GUILD_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (guild_id && current_guild_id != guild_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -76,8 +76,12 @@ class BaseGuildManager
|
||||
bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const;
|
||||
const char *GetRankName(uint32 guild_id, uint8 rank) const;
|
||||
const char *GetGuildName(uint32 guild_id) const;
|
||||
std::string GetGuildNameByID(uint32 guild_id) const;
|
||||
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
|
||||
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
|
||||
bool GetGuildNameByID(uint32 guild_id, std::string &into) const;
|
||||
uint32 GetGuildIDByName(const char *GuildName);
|
||||
uint32 GetGuildIDByCharacterID(uint32 character_id);
|
||||
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
|
||||
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
|
||||
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
|
||||
|
||||
@@ -0,0 +1,633 @@
|
||||
// Copyright (C) 2015 Ben Lewis <benjf5+github@gmail.com>
|
||||
// Licensed under the MIT license.
|
||||
// https://github.com/ben-zen/uri-library
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cctype>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
class uri {
|
||||
/* URIs are broadly divided into two categories: hierarchical and
|
||||
* non-hierarchical. Both hierarchical URIs and non-hierarchical URIs have a
|
||||
* few elements in common; all URIs have a scheme of one or more alphanumeric
|
||||
* characters followed by a colon, and they all may optionally have a query
|
||||
* component preceded by a question mark, and a fragment component preceded by
|
||||
* an octothorpe (hash mark: '#'). The query consists of stanzas separated by
|
||||
* either ampersands ('&') or semicolons (';') (but only one or the other),
|
||||
* and each stanza consists of a key and an optional value; if the value
|
||||
* exists, the key and value must be divided by an equals sign.
|
||||
*
|
||||
* The following is an example from Wikipedia of a hierarchical URI:
|
||||
* scheme:[//[user:password@]domain[:port]][/]path[?query][#fragment]
|
||||
*/
|
||||
|
||||
public:
|
||||
|
||||
enum class scheme_category {
|
||||
Hierarchical,
|
||||
NonHierarchical
|
||||
};
|
||||
|
||||
enum class component {
|
||||
Scheme,
|
||||
Content,
|
||||
Username,
|
||||
Password,
|
||||
Host,
|
||||
Port,
|
||||
Path,
|
||||
Query,
|
||||
Fragment
|
||||
};
|
||||
|
||||
enum class query_argument_separator {
|
||||
ampersand,
|
||||
semicolon
|
||||
};
|
||||
|
||||
uri(
|
||||
char const *uri_text, scheme_category category = scheme_category::Hierarchical,
|
||||
query_argument_separator separator = query_argument_separator::ampersand
|
||||
) :
|
||||
m_category(category),
|
||||
m_path_is_rooted(false),
|
||||
m_port(0),
|
||||
m_separator(separator)
|
||||
{
|
||||
setup(std::string(uri_text), category);
|
||||
};
|
||||
|
||||
uri(
|
||||
std::string const &uri_text, scheme_category category = scheme_category::Hierarchical,
|
||||
query_argument_separator separator = query_argument_separator::ampersand
|
||||
) :
|
||||
m_category(category),
|
||||
m_path_is_rooted(false),
|
||||
m_port(0),
|
||||
m_separator(separator)
|
||||
{
|
||||
setup(uri_text, category);
|
||||
};
|
||||
|
||||
uri(
|
||||
std::map<component, std::string> const &components,
|
||||
scheme_category category,
|
||||
bool rooted_path,
|
||||
query_argument_separator separator = query_argument_separator::ampersand
|
||||
) :
|
||||
m_category(category),
|
||||
m_path_is_rooted(rooted_path),
|
||||
m_separator(separator)
|
||||
{
|
||||
if (components.count(component::Scheme)) {
|
||||
if (components.at(component::Scheme).length() == 0) {
|
||||
throw std::invalid_argument("Scheme cannot be empty.");
|
||||
}
|
||||
m_scheme = components.at(component::Scheme);
|
||||
}
|
||||
else {
|
||||
throw std::invalid_argument("A URI must have a scheme.");
|
||||
}
|
||||
|
||||
if (category == scheme_category::Hierarchical) {
|
||||
if (components.count(component::Content)) {
|
||||
throw std::invalid_argument("The content component is only for use in non-hierarchical URIs.");
|
||||
}
|
||||
|
||||
bool has_username = components.count(component::Username);
|
||||
bool has_password = components.count(component::Password);
|
||||
if (has_username && has_password) {
|
||||
m_username = components.at(component::Username);
|
||||
m_password = components.at(component::Password);
|
||||
}
|
||||
else if ((has_username && !has_password) || (!has_username && has_password)) {
|
||||
throw std::invalid_argument("If a username or password is supplied, both must be provided.");
|
||||
}
|
||||
|
||||
if (components.count(component::Host)) {
|
||||
m_host = components.at(component::Host);
|
||||
}
|
||||
|
||||
if (components.count(component::Port)) {
|
||||
m_port = std::stoul(components.at(component::Port));
|
||||
}
|
||||
|
||||
if (components.count(component::Path)) {
|
||||
m_path = components.at(component::Path);
|
||||
}
|
||||
else {
|
||||
throw std::invalid_argument("A path is required on a hierarchical URI, even an empty path.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (components.count(component::Username)
|
||||
|| components.count(component::Password)
|
||||
|| components.count(component::Host)
|
||||
|| components.count(component::Port)
|
||||
|| components.count(component::Path)) {
|
||||
throw std::invalid_argument("None of the hierarchical components are allowed in a non-hierarchical URI.");
|
||||
}
|
||||
|
||||
if (components.count(component::Content)) {
|
||||
m_content = components.at(component::Content);
|
||||
}
|
||||
else {
|
||||
throw std::invalid_argument(
|
||||
"Content is a required component for a non-hierarchical URI, even an empty string."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (components.count(component::Query)) {
|
||||
m_query = components.at(component::Query);
|
||||
}
|
||||
|
||||
if (components.count(component::Fragment)) {
|
||||
m_fragment = components.at(component::Fragment);
|
||||
}
|
||||
}
|
||||
|
||||
uri(uri const &other, std::map<component, std::string> const &replacements) :
|
||||
m_category(other.m_category),
|
||||
m_path_is_rooted(other.m_path_is_rooted),
|
||||
m_separator(other.m_separator)
|
||||
{
|
||||
m_scheme = (replacements.count(component::Scheme))
|
||||
? replacements.at(component::Scheme) : other.m_scheme;
|
||||
|
||||
if (m_category == scheme_category::Hierarchical) {
|
||||
m_username = (replacements.count(component::Username))
|
||||
? replacements.at(component::Username) : other.m_username;
|
||||
|
||||
m_password = (replacements.count(component::Password))
|
||||
? replacements.at(component::Password) : other.m_password;
|
||||
|
||||
m_host = (replacements.count(component::Host))
|
||||
? replacements.at(component::Host) : other.m_host;
|
||||
|
||||
m_port = (replacements.count(component::Port))
|
||||
? std::stoul(replacements.at(component::Port)) : other.m_port;
|
||||
|
||||
m_path = (replacements.count(component::Path))
|
||||
? replacements.at(component::Path) : other.m_path;
|
||||
}
|
||||
else {
|
||||
m_content = (replacements.count(component::Content))
|
||||
? replacements.at(component::Content) : other.m_content;
|
||||
}
|
||||
|
||||
m_query = (replacements.count(component::Query))
|
||||
? replacements.at(component::Query) : other.m_query;
|
||||
|
||||
m_fragment = (replacements.count(component::Fragment))
|
||||
? replacements.at(component::Fragment) : other.m_fragment;
|
||||
}
|
||||
|
||||
// Copy constructor; just use the copy assignment operator internally.
|
||||
uri(uri const &other)
|
||||
{
|
||||
*this = other;
|
||||
};
|
||||
|
||||
// Copy assignment operator
|
||||
uri &operator=(uri const &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_scheme = other.m_scheme;
|
||||
m_content = other.m_content;
|
||||
m_username = other.m_username;
|
||||
m_password = other.m_password;
|
||||
m_host = other.m_host;
|
||||
m_path = other.m_path;
|
||||
m_query = other.m_query;
|
||||
m_fragment = other.m_fragment;
|
||||
m_query_dict = other.m_query_dict;
|
||||
m_category = other.m_category;
|
||||
m_port = other.m_port;
|
||||
m_path_is_rooted = other.m_path_is_rooted;
|
||||
m_separator = other.m_separator;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~uri() {};
|
||||
|
||||
std::string const &get_scheme() const
|
||||
{
|
||||
return m_scheme;
|
||||
};
|
||||
|
||||
scheme_category get_scheme_category() const
|
||||
{
|
||||
return m_category;
|
||||
};
|
||||
|
||||
std::string const &get_content() const
|
||||
{
|
||||
if (m_category != scheme_category::NonHierarchical) {
|
||||
throw std::domain_error("The content component is only valid for non-hierarchical URIs.");
|
||||
}
|
||||
return m_content;
|
||||
};
|
||||
|
||||
std::string const &get_username() const
|
||||
{
|
||||
if (m_category != scheme_category::Hierarchical) {
|
||||
throw std::domain_error("The username component is only valid for hierarchical URIs.");
|
||||
}
|
||||
return m_username;
|
||||
};
|
||||
|
||||
std::string const &get_password() const
|
||||
{
|
||||
if (m_category != scheme_category::Hierarchical) {
|
||||
throw std::domain_error("The password component is only valid for hierarchical URIs.");
|
||||
}
|
||||
return m_password;
|
||||
};
|
||||
|
||||
std::string const &get_host() const
|
||||
{
|
||||
if (m_category != scheme_category::Hierarchical) {
|
||||
throw std::domain_error("The host component is only valid for hierarchical URIs.");
|
||||
}
|
||||
return m_host;
|
||||
};
|
||||
|
||||
unsigned long get_port() const
|
||||
{
|
||||
if (m_category != scheme_category::Hierarchical) {
|
||||
throw std::domain_error("The port component is only valid for hierarchical URIs.");
|
||||
}
|
||||
return m_port;
|
||||
};
|
||||
|
||||
std::string const &get_path() const
|
||||
{
|
||||
if (m_category != scheme_category::Hierarchical) {
|
||||
throw std::domain_error("The path component is only valid for hierarchical URIs.");
|
||||
}
|
||||
return m_path;
|
||||
};
|
||||
|
||||
std::string const &get_query() const
|
||||
{
|
||||
return m_query;
|
||||
};
|
||||
|
||||
std::map<std::string, std::string> const &get_query_dictionary() const
|
||||
{
|
||||
return m_query_dict;
|
||||
};
|
||||
|
||||
std::string const &get_fragment() const
|
||||
{
|
||||
return m_fragment;
|
||||
};
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
std::string full_uri;
|
||||
full_uri.append(m_scheme);
|
||||
full_uri.append(":");
|
||||
|
||||
if (m_content.length() > m_path.length()) {
|
||||
full_uri.append("//");
|
||||
if (!(m_username.empty() || m_password.empty())) {
|
||||
full_uri.append(m_username);
|
||||
full_uri.append(":");
|
||||
full_uri.append(m_password);
|
||||
full_uri.append("@");
|
||||
}
|
||||
|
||||
full_uri.append(m_host);
|
||||
|
||||
if (m_port != 0) {
|
||||
full_uri.append(":");
|
||||
full_uri.append(std::to_string(m_port));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_path_is_rooted) {
|
||||
full_uri.append("/");
|
||||
}
|
||||
full_uri.append(m_path);
|
||||
|
||||
if (!m_query.empty()) {
|
||||
full_uri.append("?");
|
||||
full_uri.append(m_query);
|
||||
}
|
||||
|
||||
if (!m_fragment.empty()) {
|
||||
full_uri.append("#");
|
||||
full_uri.append(m_fragment);
|
||||
}
|
||||
|
||||
return full_uri;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
void setup(std::string const &uri_text, scheme_category category)
|
||||
{
|
||||
size_t const uri_length = uri_text.length();
|
||||
|
||||
if (uri_length == 0) {
|
||||
throw std::invalid_argument("URIs cannot be of zero length.");
|
||||
}
|
||||
|
||||
std::string::const_iterator cursor = parse_scheme(
|
||||
uri_text,
|
||||
uri_text.begin());
|
||||
// After calling parse_scheme, *cursor == ':'; none of the following parsers
|
||||
// expect a separator character, so we advance the cursor upon calling them.
|
||||
cursor = parse_content(uri_text, (cursor + 1));
|
||||
|
||||
if ((cursor != uri_text.end()) && (*cursor == '?')) {
|
||||
cursor = parse_query(uri_text, (cursor + 1));
|
||||
}
|
||||
|
||||
if ((cursor != uri_text.end()) && (*cursor == '#')) {
|
||||
cursor = parse_fragment(uri_text, (cursor + 1));
|
||||
}
|
||||
|
||||
init_query_dictionary(); // If the query string is empty, this will be empty too.
|
||||
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_scheme(
|
||||
std::string const &uri_text,
|
||||
std::string::const_iterator scheme_start
|
||||
)
|
||||
{
|
||||
std::string::const_iterator scheme_end = scheme_start;
|
||||
while ((scheme_end != uri_text.end()) && (*scheme_end != ':')) {
|
||||
if (!(std::isalnum(*scheme_end) || (*scheme_end == '-')
|
||||
|| (*scheme_end == '+') || (*scheme_end == '.'))) {
|
||||
throw std::invalid_argument(
|
||||
"Invalid character found in the scheme component. Supplied URI was: \""
|
||||
+ uri_text + "\"."
|
||||
);
|
||||
}
|
||||
++scheme_end;
|
||||
}
|
||||
|
||||
if (scheme_end == uri_text.end()) {
|
||||
throw std::invalid_argument(
|
||||
"End of URI found while parsing the scheme. Supplied URI was: \""
|
||||
+ uri_text + "\"."
|
||||
);
|
||||
}
|
||||
|
||||
if (scheme_start == scheme_end) {
|
||||
throw std::invalid_argument(
|
||||
"Scheme component cannot be zero-length. Supplied URI was: \""
|
||||
+ uri_text + "\"."
|
||||
);
|
||||
}
|
||||
|
||||
m_scheme = std::move(std::string(scheme_start, scheme_end));
|
||||
return scheme_end;
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_content(
|
||||
std::string const &uri_text,
|
||||
std::string::const_iterator content_start
|
||||
)
|
||||
{
|
||||
std::string::const_iterator content_end = content_start;
|
||||
while ((content_end != uri_text.end()) && (*content_end != '?') && (*content_end != '#')) {
|
||||
++content_end;
|
||||
}
|
||||
|
||||
m_content = std::move(std::string(content_start, content_end));
|
||||
|
||||
if ((m_category == scheme_category::Hierarchical) && (m_content.length() > 0)) {
|
||||
// If it's a hierarchical URI, the content should be parsed for the hierarchical components.
|
||||
std::string::const_iterator path_start = m_content.begin();
|
||||
std::string::const_iterator path_end = m_content.end();
|
||||
if (!m_content.compare(0, 2, "//")) {
|
||||
// In this case an authority component is present.
|
||||
std::string::const_iterator authority_cursor = (m_content.begin() + 2);
|
||||
if (m_content.find_first_of('@') != std::string::npos) {
|
||||
std::string::const_iterator userpass_divider = parse_username(
|
||||
uri_text,
|
||||
m_content,
|
||||
authority_cursor
|
||||
);
|
||||
authority_cursor = parse_password(uri_text, m_content, (userpass_divider + 1));
|
||||
// After this call, *authority_cursor == '@', so we skip over it.
|
||||
++authority_cursor;
|
||||
}
|
||||
|
||||
authority_cursor = parse_host(uri_text, m_content, authority_cursor);
|
||||
|
||||
if ((authority_cursor != m_content.end()) && (*authority_cursor == ':')) {
|
||||
authority_cursor = parse_port(uri_text, m_content, (authority_cursor + 1));
|
||||
}
|
||||
|
||||
if ((authority_cursor != m_content.end()) && (*authority_cursor == '/')) {
|
||||
// Then the path is rooted, and we should note this.
|
||||
m_path_is_rooted = true;
|
||||
path_start = authority_cursor + 1;
|
||||
}
|
||||
|
||||
// If we've reached the end and no path is present then set path_start
|
||||
// to the end.
|
||||
if (authority_cursor == m_content.end()) {
|
||||
path_start = m_content.end();
|
||||
}
|
||||
}
|
||||
else if (!m_content.compare(0, 1, "/")) {
|
||||
m_path_is_rooted = true;
|
||||
++path_start;
|
||||
}
|
||||
|
||||
// We can now build the path based on what remains in the content string,
|
||||
// since that's all that exists after the host and optional port component.
|
||||
m_path = std::move(std::string(path_start, path_end));
|
||||
}
|
||||
return content_end;
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_username(
|
||||
std::string const &uri_text,
|
||||
std::string const &content,
|
||||
std::string::const_iterator username_start
|
||||
)
|
||||
{
|
||||
std::string::const_iterator username_end = username_start;
|
||||
// Since this is only reachable when '@' was in the content string, we can
|
||||
// ignore the end-of-string case.
|
||||
while (*username_end != ':') {
|
||||
if (*username_end == '@') {
|
||||
throw std::invalid_argument(
|
||||
"Username must be followed by a password. Supplied URI was: \""
|
||||
+ uri_text + "\"."
|
||||
);
|
||||
}
|
||||
++username_end;
|
||||
}
|
||||
m_username = std::move(std::string(username_start, username_end));
|
||||
return username_end;
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_password(
|
||||
std::string const &uri_text,
|
||||
std::string const &content,
|
||||
std::string::const_iterator password_start
|
||||
)
|
||||
{
|
||||
std::string::const_iterator password_end = password_start;
|
||||
while (*password_end != '@') {
|
||||
++password_end;
|
||||
}
|
||||
|
||||
m_password = std::move(std::string(password_start, password_end));
|
||||
return password_end;
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_host(
|
||||
std::string const &uri_text,
|
||||
std::string const &content,
|
||||
std::string::const_iterator host_start
|
||||
)
|
||||
{
|
||||
std::string::const_iterator host_end = host_start;
|
||||
// So, the host can contain a few things. It can be a domain, it can be an
|
||||
// IPv4 address, it can be an IPv6 address, or an IPvFuture literal. In the
|
||||
// case of those last two, it's of the form [...] where what's between the
|
||||
// brackets is a matter of which IPv?? version it is.
|
||||
while (host_end != content.end()) {
|
||||
if (*host_end == '[') {
|
||||
// We're parsing an IPv6 or IPvFuture address, so we should handle that
|
||||
// instead of the normal procedure.
|
||||
while ((host_end != content.end()) && (*host_end != ']')) {
|
||||
++host_end;
|
||||
}
|
||||
|
||||
if (host_end == content.end()) {
|
||||
throw std::invalid_argument(
|
||||
"End of content component encountered "
|
||||
"while parsing the host component. "
|
||||
"Supplied URI was: \""
|
||||
+ uri_text + "\"."
|
||||
);
|
||||
}
|
||||
|
||||
++host_end;
|
||||
break;
|
||||
// We can stop looping, we found the end of the IP literal, which is the
|
||||
// whole of the host component when one's in use.
|
||||
}
|
||||
else if ((*host_end == ':') || (*host_end == '/')) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
++host_end;
|
||||
}
|
||||
}
|
||||
|
||||
m_host = std::move(std::string(host_start, host_end));
|
||||
return host_end;
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_port(
|
||||
std::string const &uri_text,
|
||||
std::string const &content,
|
||||
std::string::const_iterator port_start
|
||||
)
|
||||
{
|
||||
std::string::const_iterator port_end = port_start;
|
||||
while ((port_end != content.end()) && (*port_end != '/')) {
|
||||
if (!std::isdigit(*port_end)) {
|
||||
throw std::invalid_argument(
|
||||
"Invalid character while parsing the port. "
|
||||
"Supplied URI was: \"" + uri_text + "\"."
|
||||
);
|
||||
}
|
||||
|
||||
++port_end;
|
||||
}
|
||||
|
||||
m_port = std::stoul(std::string(port_start, port_end));
|
||||
return port_end;
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_query(
|
||||
std::string const &uri_text,
|
||||
std::string::const_iterator query_start
|
||||
)
|
||||
{
|
||||
std::string::const_iterator query_end = query_start;
|
||||
while ((query_end != uri_text.end()) && (*query_end != '#')) {
|
||||
// Queries can contain almost any character except hash, which is reserved
|
||||
// for the start of the fragment.
|
||||
++query_end;
|
||||
}
|
||||
m_query = std::move(std::string(query_start, query_end));
|
||||
return query_end;
|
||||
};
|
||||
|
||||
std::string::const_iterator parse_fragment(
|
||||
std::string const &uri_text,
|
||||
std::string::const_iterator fragment_start
|
||||
)
|
||||
{
|
||||
m_fragment = std::move(std::string(fragment_start, uri_text.end()));
|
||||
return uri_text.end();
|
||||
};
|
||||
|
||||
void init_query_dictionary()
|
||||
{
|
||||
if (!m_query.empty()) {
|
||||
// Loop over the query string looking for '&'s, then check each one for
|
||||
// an '=' to find keys and values; if there's not an '=' then the key
|
||||
// will have an empty value in the map.
|
||||
char separator = (m_separator == query_argument_separator::ampersand) ? '&' : ';';
|
||||
size_t carat = 0;
|
||||
size_t stanza_end = m_query.find_first_of(separator);
|
||||
do {
|
||||
std::string stanza = m_query.substr(
|
||||
carat,
|
||||
((stanza_end != std::string::npos) ? (stanza_end - carat) : std::string::npos));
|
||||
size_t key_value_divider = stanza.find_first_of('=');
|
||||
std::string key = stanza.substr(0, key_value_divider);
|
||||
std::string value;
|
||||
if (key_value_divider != std::string::npos) {
|
||||
value = stanza.substr((key_value_divider + 1));
|
||||
}
|
||||
|
||||
if (m_query_dict.count(key) != 0) {
|
||||
throw std::invalid_argument("Bad key in the query string!");
|
||||
}
|
||||
|
||||
m_query_dict.emplace(key, value);
|
||||
carat = ((stanza_end != std::string::npos) ? (stanza_end + 1)
|
||||
: std::string::npos);
|
||||
stanza_end = m_query.find_first_of(separator, carat);
|
||||
} while ((stanza_end != std::string::npos)
|
||||
|| (carat != std::string::npos));
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_scheme;
|
||||
std::string m_content;
|
||||
std::string m_username;
|
||||
std::string m_password;
|
||||
std::string m_host;
|
||||
std::string m_path;
|
||||
std::string m_query;
|
||||
std::string m_fragment;
|
||||
|
||||
std::map<std::string, std::string> m_query_dict;
|
||||
|
||||
scheme_category m_category;
|
||||
unsigned long m_port;
|
||||
bool m_path_is_rooted;
|
||||
query_argument_separator m_separator;
|
||||
};
|
||||
@@ -224,7 +224,7 @@ EQ::ItemInstance* EQ::InventoryProfile::GetItem(int16 slot_id, uint8 bagidx) con
|
||||
return GetItem(InventoryProfile::CalcSlotId(slot_id, bagidx));
|
||||
}
|
||||
|
||||
// Put an item snto specified slot
|
||||
// Put an item into specified slot
|
||||
int16 EQ::InventoryProfile::PutItem(int16 slot_id, const ItemInstance& inst)
|
||||
{
|
||||
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) {
|
||||
@@ -399,7 +399,7 @@ bool EQ::InventoryProfile::SwapItem(
|
||||
}
|
||||
|
||||
// Remove item from inventory (with memory delete)
|
||||
bool EQ::InventoryProfile::DeleteItem(int16 slot_id, uint8 quantity) {
|
||||
bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
|
||||
// Pop item out of inventory map (or queue)
|
||||
ItemInstance *item_to_delete = PopItem(slot_id);
|
||||
|
||||
@@ -590,6 +590,68 @@ bool EQ::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quan
|
||||
// Checks that user has at least 'quantity' number of items in a given inventory slot
|
||||
// Returns first slot it was found in, or SLOT_INVALID if not found
|
||||
|
||||
bool EQ::InventoryProfile::HasAugmentEquippedByID(uint32 item_id)
|
||||
{
|
||||
bool has_equipped = false;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->ContainsAugmentByID(item_id)) {
|
||||
has_equipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return has_equipped;
|
||||
}
|
||||
|
||||
int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id)
|
||||
{
|
||||
int quantity = 0;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->ContainsAugmentByID(item_id)) {
|
||||
quantity += item->CountAugmentByID(item_id);
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
bool EQ::InventoryProfile::HasItemEquippedByID(uint32 item_id)
|
||||
{
|
||||
bool has_equipped = false;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->GetID() == item_id) {
|
||||
has_equipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return has_equipped;
|
||||
}
|
||||
|
||||
int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id)
|
||||
{
|
||||
int quantity = 0;
|
||||
ItemInstance* item = nullptr;
|
||||
|
||||
for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||
item = GetItem(slot_id);
|
||||
if (item && item->GetID() == item_id) {
|
||||
quantity += item->IsStackable() ? item->GetCharges() : 1;
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
//This function has a flaw in that it only returns the last stack that it looked at
|
||||
//when quantity is greater than 1 and not all of quantity can be found in 1 stack.
|
||||
int16 EQ::InventoryProfile::HasItem(uint32 item_id, uint8 quantity, uint8 where)
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace EQ
|
||||
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0);
|
||||
|
||||
// Remove item from inventory
|
||||
bool DeleteItem(int16 slot_id, uint8 quantity = 0);
|
||||
bool DeleteItem(int16 slot_id, int16 quantity = 0);
|
||||
|
||||
// Checks All items in a bag for No Drop
|
||||
bool CheckNoDrop(int16 slot_id, bool recurse = true);
|
||||
@@ -140,6 +140,18 @@ namespace EQ
|
||||
// Remove item from inventory (and take control of memory)
|
||||
ItemInstance* PopItem(int16 slot_id);
|
||||
|
||||
// Check if player has a specific item equipped by Item ID
|
||||
bool HasItemEquippedByID(uint32 item_id);
|
||||
|
||||
// Check how many of a specific item the player has equipped by Item ID
|
||||
int CountItemEquippedByID(uint32 item_id);
|
||||
|
||||
// Check if player has a specific augment equipped by Item ID
|
||||
bool HasAugmentEquippedByID(uint32 item_id);
|
||||
|
||||
// Check how many of a specific augment the player has equipped by Item ID
|
||||
int CountAugmentEquippedByID(uint32 item_id);
|
||||
|
||||
// Check whether there is space for the specified number of the specified item.
|
||||
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
|
||||
|
||||
|
||||
+1
-1
@@ -482,7 +482,7 @@ namespace EQ
|
||||
uint32 Haste;
|
||||
uint32 DamageShield;
|
||||
uint32 RecastDelay;
|
||||
uint32 RecastType;
|
||||
int RecastType;
|
||||
uint32 AugDistiller;
|
||||
bool Attuneable;
|
||||
bool NoPet;
|
||||
|
||||
@@ -689,6 +689,45 @@ bool EQ::ItemInstance::IsAugmented()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::ContainsAugmentByID(uint32 item_id)
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!item_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
|
||||
if (GetAugmentItemID(augment_slot) == item_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int EQ::ItemInstance::CountAugmentByID(uint32 item_id)
|
||||
{
|
||||
int quantity = 0;
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
if (!item_id) {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
for (uint8 augment_slot = invaug::SOCKET_BEGIN; augment_slot <= invaug::SOCKET_END; ++augment_slot) {
|
||||
if (GetAugmentItemID(augment_slot) == item_id) {
|
||||
quantity++;
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
// Has attack/delay?
|
||||
bool EQ::ItemInstance::IsWeapon() const
|
||||
{
|
||||
@@ -1706,4 +1745,4 @@ EvolveInfo::EvolveInfo(uint32 first, uint8 max, bool allkills, uint32 L2, uint32
|
||||
|
||||
EvolveInfo::~EvolveInfo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,8 @@ namespace EQ
|
||||
void DeleteAugment(uint8 slot);
|
||||
ItemInstance* RemoveAugment(uint8 index);
|
||||
bool IsAugmented();
|
||||
bool ContainsAugmentByID(uint32 item_id);
|
||||
int CountAugmentByID(uint32 item_id);
|
||||
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
|
||||
bool UpdateOrnamentationInfo();
|
||||
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
||||
|
||||
+1
-1
@@ -194,7 +194,7 @@ void MD5::Final(uint8 digest[16], MD5Context *ctx) {
|
||||
|
||||
/* The heart of the MD5 algorithm. */
|
||||
void MD5::Transform(uint32 hash[4], const uint32 input[16]) {
|
||||
register uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
|
||||
uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, input[ 0]+0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, input[ 1]+0xe8c7b756, 12);
|
||||
|
||||
@@ -15,7 +15,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
|
||||
memset(m_line, 0, MaxConsoleLineLength);
|
||||
m_accept_messages = false;
|
||||
m_user_id = 0;
|
||||
m_admin = 0;
|
||||
m_admin = AccountStatus::Player;
|
||||
|
||||
m_connection->OnRead(std::bind(&ConsoleServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
|
||||
@@ -29,7 +29,7 @@ EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent,
|
||||
if (addr.find("127.0.0.1") != std::string::npos || addr.find("::0") != std::string::npos) {
|
||||
SendLine("Connection established from localhost, assuming admin");
|
||||
m_status = ConsoleStatusLoggedIn;
|
||||
m_admin = 255;
|
||||
m_admin = AccountStatus::Max;
|
||||
SendPrompt();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -11,6 +11,7 @@ EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr<
|
||||
m_connection->OnRead(std::bind(&ServertalkServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_connection->OnDisconnect(std::bind(&ServertalkServerConnection::OnDisconnect, this, std::placeholders::_1));
|
||||
m_connection->Start();
|
||||
m_legacy_mode = false;
|
||||
}
|
||||
|
||||
EQ::Net::ServertalkServerConnection::~ServertalkServerConnection()
|
||||
@@ -19,17 +20,73 @@ EQ::Net::ServertalkServerConnection::~ServertalkServerConnection()
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet & p)
|
||||
{
|
||||
// pad zero size packets
|
||||
if (p.Length() == 0) {
|
||||
p.PutUInt8(0, 0);
|
||||
if (m_legacy_mode) {
|
||||
if (!m_connection)
|
||||
return;
|
||||
|
||||
if (opcode == ServerOP_UsertoWorldReq) {
|
||||
auto req_in = (UsertoWorldRequest_Struct*)p.Data();
|
||||
|
||||
EQ::Net::DynamicPacket req;
|
||||
size_t i = 0;
|
||||
req.PutUInt32(i, req_in->lsaccountid); i += 4;
|
||||
req.PutUInt32(i, req_in->worldid); i += 4;
|
||||
req.PutUInt32(i, req_in->FromID); i += 4;
|
||||
req.PutUInt32(i, req_in->ToID); i += 4;
|
||||
req.PutData(i, req_in->IPAddr, 64); i += 64;
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt16(0, ServerOP_UsertoWorldReqLeg);
|
||||
out.PutUInt16(2, req.Length() + 4);
|
||||
out.PutPacket(4, req);
|
||||
|
||||
m_connection->Write((const char*)out.Data(), out.Length());
|
||||
return;
|
||||
}
|
||||
|
||||
if (opcode == ServerOP_LSClientAuth) {
|
||||
auto req_in = (ClientAuth_Struct*)p.Data();
|
||||
|
||||
EQ::Net::DynamicPacket req;
|
||||
size_t i = 0;
|
||||
req.PutUInt32(i, req_in->loginserver_account_id); i += 4;
|
||||
req.PutData(i, req_in->account_name, 30); i += 30;
|
||||
req.PutData(i, req_in->key, 30); i += 30;
|
||||
req.PutUInt8(i, req_in->lsadmin); i += 1;
|
||||
req.PutUInt16(i, req_in->is_world_admin); i += 2;
|
||||
req.PutUInt32(i, req_in->ip); i += 4;
|
||||
req.PutUInt8(i, req_in->is_client_from_local_network); i += 1;
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt16(0, ServerOP_LSClientAuthLeg);
|
||||
out.PutUInt16(2, req.Length() + 4);
|
||||
out.PutPacket(4, req);
|
||||
|
||||
m_connection->Write((const char*)out.Data(), out.Length());
|
||||
return;
|
||||
}
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt16(0, opcode);
|
||||
out.PutUInt16(2, p.Length() + 4);
|
||||
out.PutPacket(4, p);
|
||||
|
||||
m_connection->Write((const char*)out.Data(), out.Length());
|
||||
} else {
|
||||
// pad zero size packets
|
||||
// pad packets that would cause a collision with legacy identification code
|
||||
// It's unlikely we'd send a 4MB msg for any reason but just incase.
|
||||
if (p.Length() == 0 || p.Length() == 43061256) {
|
||||
p.PutUInt8(0, 0);
|
||||
}
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt32(0, p.Length());
|
||||
out.PutUInt16(4, opcode);
|
||||
out.PutPacket(6, p);
|
||||
|
||||
InternalSend(ServertalkMessage, out);
|
||||
}
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt32(0, p.Length());
|
||||
out.PutUInt16(4, opcode);
|
||||
out.PutPacket(6, p);
|
||||
|
||||
InternalSend(ServertalkMessage, out);
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::SendPacket(ServerPacket *p)
|
||||
@@ -54,17 +111,41 @@ void EQ::Net::ServertalkServerConnection::OnMessage(std::function<void(uint16_t,
|
||||
void EQ::Net::ServertalkServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz)
|
||||
{
|
||||
m_buffer.insert(m_buffer.end(), (const char*)data, (const char*)data + sz);
|
||||
ProcessReadBuffer();
|
||||
|
||||
if (m_legacy_mode) {
|
||||
ProcessOldReadBuffer();
|
||||
} else {
|
||||
ProcessReadBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
|
||||
{
|
||||
size_t current = 0;
|
||||
size_t total = m_buffer.size();
|
||||
constexpr size_t ls_info_size = sizeof(ServerNewLSInfo_Struct);
|
||||
|
||||
while (current < total) {
|
||||
auto left = total - current;
|
||||
|
||||
if (left < 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto leg_opcode = *(uint16_t*)&m_buffer[current];
|
||||
auto leg_size = *(uint16_t*)&m_buffer[current + 2] - 4;
|
||||
|
||||
//this creates a small edge case where the exact size of a
|
||||
//packet from the modern protocol can't be "43061256"
|
||||
//so in send we pad it one byte if that's the case
|
||||
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) {
|
||||
m_legacy_mode = true;
|
||||
m_identifier = "World";
|
||||
m_parent->ConnectionIdentified(this);
|
||||
ProcessOldReadBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
//header:
|
||||
//uint32 length;
|
||||
@@ -129,6 +210,57 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::ProcessOldReadBuffer()
|
||||
{
|
||||
size_t current = 0;
|
||||
size_t total = m_buffer.size();
|
||||
|
||||
while (current < total) {
|
||||
auto left = total - current;
|
||||
|
||||
/*
|
||||
//header:
|
||||
//uint32 length;
|
||||
//uint8 type;
|
||||
*/
|
||||
uint16_t length = 0;
|
||||
uint16_t opcode = 0;
|
||||
if (left < 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
opcode = *(uint16_t*)&m_buffer[current];
|
||||
length = *(uint16_t*)&m_buffer[current + 2];
|
||||
if (length < 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
length -= 4;
|
||||
|
||||
if (current + 4 + length > total) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
EQ::Net::DynamicPacket p;
|
||||
ProcessMessageOld(opcode, p);
|
||||
}
|
||||
else {
|
||||
EQ::Net::StaticPacket p(&m_buffer[current + 4], length);
|
||||
ProcessMessageOld(opcode, p);
|
||||
}
|
||||
|
||||
current += length + 4;
|
||||
}
|
||||
|
||||
if (current == total) {
|
||||
m_buffer.clear();
|
||||
}
|
||||
else {
|
||||
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + current);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::OnDisconnect(TCPConnection *c)
|
||||
{
|
||||
m_parent->ConnectionDisconnected(this);
|
||||
@@ -144,7 +276,7 @@ void EQ::Net::ServertalkServerConnection::SendHello()
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::InternalSend(ServertalkPacketType type, EQ::Net::Packet &p)
|
||||
{
|
||||
if (!m_connection)
|
||||
if (!m_connection || m_legacy_mode)
|
||||
return;
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
@@ -201,3 +333,20 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
|
||||
LogError("Error parsing message from client: {0}", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::ProcessMessageOld(uint16_t opcode, EQ::Net::Packet &p)
|
||||
{
|
||||
try {
|
||||
auto cb = m_message_callbacks.find(opcode);
|
||||
if (cb != m_message_callbacks.end()) {
|
||||
cb->second(opcode, p);
|
||||
}
|
||||
|
||||
if (m_message_callback) {
|
||||
m_message_callback(opcode, p);
|
||||
}
|
||||
}
|
||||
catch (std::exception &ex) {
|
||||
LogError("Error parsing legacy message from client: {0}", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ namespace EQ
|
||||
private:
|
||||
void OnRead(TCPConnection* c, const unsigned char* data, size_t sz);
|
||||
void ProcessReadBuffer();
|
||||
void ProcessOldReadBuffer();
|
||||
void OnDisconnect(TCPConnection* c);
|
||||
void SendHello();
|
||||
void InternalSend(ServertalkPacketType type, EQ::Net::Packet &p);
|
||||
void ProcessHandshake(EQ::Net::Packet &p);
|
||||
void ProcessMessage(EQ::Net::Packet &p);
|
||||
void ProcessMessageOld(uint16_t opcode, EQ::Net::Packet &p);
|
||||
|
||||
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
|
||||
ServertalkServer *m_parent;
|
||||
@@ -41,6 +43,7 @@ namespace EQ
|
||||
std::function<void(uint16_t, EQ::Net::Packet&)> m_message_callback;
|
||||
std::string m_identifier;
|
||||
std::string m_uuid;
|
||||
bool m_legacy_mode;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
#include "../emu_constants.h"
|
||||
|
||||
struct MethodHandlerEntry
|
||||
{
|
||||
@@ -174,13 +175,13 @@ Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connectio
|
||||
auto r = _impl->login_handler(connection, user, pass);
|
||||
|
||||
if (r.logged_in) {
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max);
|
||||
ret["status"] = "Ok";
|
||||
}
|
||||
else if (user == "admin" && (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::")) {
|
||||
r.logged_in = true;
|
||||
r.account_id = 0;
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
|
||||
connection->SetAuthorized(true, r.account_name, r.account_id, AccountStatus::Max);
|
||||
ret["status"] = "Ok";
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -115,8 +115,8 @@ IN(OP_GMTraining, GMTrainee_Struct);
|
||||
IN(OP_GMEndTraining, GMTrainEnd_Struct);
|
||||
IN(OP_GMTrainSkill, GMSkillChange_Struct);
|
||||
IN(OP_RequestDuel, Duel_Struct);
|
||||
IN(OP_DuelResponse, DuelResponse_Struct);
|
||||
IN(OP_DuelResponse2, Duel_Struct);
|
||||
IN(OP_DuelDecline, DuelResponse_Struct);
|
||||
IN(OP_DuelAccept, Duel_Struct);
|
||||
IN(OP_SpawnAppearance, SpawnAppearance_Struct);
|
||||
IN(OP_BazaarInspect, BazaarInspect_Struct);
|
||||
IN(OP_Death, Death_Struct);
|
||||
|
||||
@@ -240,8 +240,8 @@ void load_opcode_names()
|
||||
opcode_map[0x00a1] = "LiveOP_SaveOnZoneReq";
|
||||
opcode_map[0x0185] = "LiveOP_Logout";
|
||||
opcode_map[0x0298] = "LiveOP_RequestDuel";
|
||||
opcode_map[0x0a5d] = "LiveOP_DuelResponse";
|
||||
opcode_map[0x016e] = "LiveOP_DuelResponse2";
|
||||
opcode_map[0x0a5d] = "LiveOP_DuelDecline";
|
||||
opcode_map[0x016e] = "LiveOP_DuelAccept";
|
||||
opcode_map[0x007c] = "LiveOP_InstillDoubt";
|
||||
opcode_map[0x00ac] = "LiveOP_SafeFallSuccess";
|
||||
opcode_map[0x02fb] = "LiveOP_DisciplineUpdate";
|
||||
|
||||
+2
-16
@@ -1634,20 +1634,6 @@ namespace RoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
@@ -1863,8 +1849,8 @@ namespace RoF
|
||||
/*fill in some unknowns with observed values, hopefully it will help */
|
||||
eq->unknown800 = -1;
|
||||
eq->unknown844 = 600;
|
||||
eq->unknown880 = 50;
|
||||
eq->unknown884 = 10;
|
||||
OUT(LavaDamage);
|
||||
OUT(MinLavaDamage);
|
||||
eq->unknown888 = 1;
|
||||
eq->unknown889 = 0;
|
||||
eq->unknown890 = 1;
|
||||
|
||||
+2
-16
@@ -1683,20 +1683,6 @@ namespace RoF2
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
@@ -1919,8 +1905,8 @@ namespace RoF2
|
||||
eq->SkyRelated2 = -1;
|
||||
eq->NPCAggroMaxDist = 600;
|
||||
eq->FilterID = 2008; // Guild Lobby observed value
|
||||
eq->LavaDamage = 50;
|
||||
eq->MinLavaDamage = 10;
|
||||
OUT(LavaDamage);
|
||||
OUT(MinLavaDamage);
|
||||
eq->bDisallowManaStone = 1;
|
||||
eq->bNoBind = 0;
|
||||
eq->bNoAttack = 0;
|
||||
|
||||
@@ -93,7 +93,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -3061,7 +3061,7 @@ struct EnvDamage2_Struct {
|
||||
/*0006*/ uint32 damage;
|
||||
/*0010*/ float unknown10; // New to Underfoot - Seen 1
|
||||
/*0014*/ uint8 unknown14[12];
|
||||
/*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling
|
||||
/*0026*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
|
||||
/*0027*/ uint8 unknown27[4];
|
||||
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
|
||||
/*0033*/ uint16 constant; // Always FFFF
|
||||
@@ -4361,8 +4361,8 @@ struct UseAA_Struct {
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
/*08*/ uint32 base2;
|
||||
/*04*/ uint32 base_value;
|
||||
/*08*/ uint32 limit_value;
|
||||
/*12*/ uint32 slot;
|
||||
/*16*/
|
||||
};
|
||||
|
||||
@@ -79,7 +79,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -581,8 +581,8 @@ struct NewZone_Struct {
|
||||
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||
/*0872*/ uint32 scriptIDSomething3;
|
||||
/*0876*/ uint32 SuspendBuffs;
|
||||
/*0880*/ uint32 unknown880; // Seen 50
|
||||
/*0884*/ uint32 unknown884; // Seen 10
|
||||
/*0880*/ uint32 LavaDamage; // Seen 50
|
||||
/*0884*/ uint32 MinLavaDamage; // Seen 10
|
||||
/*0888*/ uint8 unknown888; // Seen 1
|
||||
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
|
||||
/*0890*/ uint8 unknown890; // Seen 1
|
||||
@@ -3032,7 +3032,7 @@ struct EnvDamage2_Struct {
|
||||
/*0006*/ uint32 damage;
|
||||
/*0010*/ float unknown10; // New to Underfoot - Seen 1
|
||||
/*0014*/ uint8 unknown14[12];
|
||||
/*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling
|
||||
/*0026*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
|
||||
/*0027*/ uint8 unknown27[4];
|
||||
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
|
||||
/*0033*/ uint16 constant; // Always FFFF
|
||||
@@ -4305,8 +4305,8 @@ struct UseAA_Struct {
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
/*08*/ uint32 base2;
|
||||
/*04*/ uint32 base_value;
|
||||
/*08*/ uint32 limit_value;
|
||||
/*12*/ uint32 slot;
|
||||
/*16*/
|
||||
};
|
||||
|
||||
+4
-18
@@ -1170,20 +1170,6 @@ namespace SoD
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
@@ -1388,8 +1374,8 @@ namespace SoD
|
||||
/*fill in some unknowns with observed values, hopefully it will help */
|
||||
eq->unknown800 = -1;
|
||||
eq->unknown844 = 600;
|
||||
eq->unknown880 = 50;
|
||||
eq->unknown884 = 10;
|
||||
OUT(LavaDamage);
|
||||
OUT(MinLavaDamage);
|
||||
eq->unknown888 = 1;
|
||||
eq->unknown889 = 0;
|
||||
eq->unknown890 = 1;
|
||||
@@ -1874,8 +1860,8 @@ namespace SoD
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].limit_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -450,8 +450,8 @@ struct NewZone_Struct {
|
||||
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||
/*0872*/ uint32 scriptIDSomething3;
|
||||
/*0876*/ uint32 SuspendBuffs;
|
||||
/*0880*/ uint32 unknown880; //seen 50
|
||||
/*0884*/ uint32 unknown884; //seen 10
|
||||
/*0880*/ uint32 LavaDamage; //seen 50
|
||||
/*0884*/ uint32 MinLavaDamage; //seen 10
|
||||
/*0888*/ uint8 unknown888; //seen 1
|
||||
/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj)
|
||||
/*0890*/ uint8 unknown890; //seen 1
|
||||
@@ -2539,7 +2539,7 @@ struct EnvDamage2_Struct {
|
||||
/*0004*/ uint16 unknown4;
|
||||
/*0006*/ uint32 damage;
|
||||
/*0010*/ uint8 unknown10[12];
|
||||
/*0022*/ uint8 dmgtype; //FA = Lava; FC = Falling
|
||||
/*0022*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
|
||||
/*0023*/ uint8 unknown2[4];
|
||||
/*0027*/ uint16 constant; //Always FFFF
|
||||
/*0029*/ uint16 unknown29;
|
||||
@@ -3748,8 +3748,8 @@ struct UseAA_Struct {
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
/*08*/ uint32 base2;
|
||||
/*04*/ uint32 base_value;
|
||||
/*08*/ uint32 limit_value;
|
||||
/*12*/ uint32 slot;
|
||||
/*16*/
|
||||
};
|
||||
|
||||
+4
-18
@@ -966,20 +966,6 @@ namespace SoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MemorizeSpell)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MemorizeSpell_Struct);
|
||||
@@ -1066,8 +1052,8 @@ namespace SoF
|
||||
/*fill in some unknowns with observed values, hopefully it will help */
|
||||
eq->unknown796 = -1;
|
||||
eq->unknown840 = 600;
|
||||
eq->unknown876 = 50;
|
||||
eq->unknown880 = 10;
|
||||
OUT(LavaDamage);
|
||||
OUT(MinLavaDamage);
|
||||
eq->unknown884 = 1;
|
||||
eq->unknown885 = 0;
|
||||
eq->unknown886 = 1;
|
||||
@@ -1545,8 +1531,8 @@ namespace SoF
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].limit_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MemorizeSpell)
|
||||
E(OP_MoveItem)
|
||||
E(OP_NewSpawn)
|
||||
|
||||
@@ -454,8 +454,8 @@ struct NewZone_Struct {
|
||||
/*0864*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||
/*0868*/ uint32 scriptIDSomething3;
|
||||
/*0872*/ uint32 SuspendBuffs;
|
||||
/*0876*/ uint32 unknown876; //seen 50
|
||||
/*0880*/ uint32 unknown880; //seen 10
|
||||
/*0876*/ uint32 LavaDamage; //seen 50
|
||||
/*0880*/ uint32 MinLavaDamage; //seen 10
|
||||
/*0884*/ uint8 unknown884; //seen 1
|
||||
/*0885*/ uint8 unknown885; //seen 0 (POK) or 1 (rujj)
|
||||
/*0886*/ uint8 unknown886; //seen 1
|
||||
@@ -2509,7 +2509,7 @@ struct EnvDamage2_Struct {
|
||||
/*0004*/ uint16 unknown4;
|
||||
/*0006*/ uint32 damage;
|
||||
/*0010*/ uint8 unknown10[12];
|
||||
/*0022*/ uint8 dmgtype; //FA = Lava; FC = Falling
|
||||
/*0022*/ uint8 dmgtype; // FA = Lava, FB = Drowning, FC = Falling, FD = Trap
|
||||
/*0023*/ uint8 unknown2[4];
|
||||
/*0027*/ uint16 constant; //Always FFFF
|
||||
/*0029*/ uint16 unknown29;
|
||||
@@ -3673,8 +3673,8 @@ struct UseAA_Struct {
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
/*08*/ uint32 base2;
|
||||
/*04*/ uint32 base_value;
|
||||
/*08*/ uint32 limit_value;
|
||||
/*12*/ uint32 slot;
|
||||
/*16*/
|
||||
};
|
||||
|
||||
@@ -932,6 +932,19 @@ namespace Titanium
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MemorizeSpell)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MemorizeSpell_Struct);
|
||||
@@ -1338,8 +1351,8 @@ namespace Titanium
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].limit_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ E(OP_ItemPacket)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LFGuild)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MemorizeSpell)
|
||||
E(OP_MoveItem)
|
||||
E(OP_OnLevelMessage)
|
||||
|
||||
@@ -3180,8 +3180,8 @@ struct UseAA_Struct {
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
/*08*/ uint32 base2;
|
||||
/*04*/ uint32 base_value;
|
||||
/*08*/ uint32 limit_value;
|
||||
/*12*/ uint32 slot;
|
||||
};
|
||||
|
||||
|
||||
+4
-18
@@ -1390,20 +1390,6 @@ namespace UF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ManaChange)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ManaChange_Struct);
|
||||
SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct);
|
||||
|
||||
OUT(new_mana);
|
||||
OUT(stamina);
|
||||
OUT(spell_id);
|
||||
OUT(keepcasting);
|
||||
eq->slot = -1; // this is spell gem slot. It's -1 in normal operation
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_MercenaryDataResponse)
|
||||
{
|
||||
//consume the packet
|
||||
@@ -1614,8 +1600,8 @@ namespace UF
|
||||
/*fill in some unknowns with observed values, hopefully it will help */
|
||||
eq->unknown800 = -1;
|
||||
eq->unknown844 = 600;
|
||||
eq->unknown880 = 50;
|
||||
eq->unknown884 = 10;
|
||||
OUT(LavaDamage);
|
||||
OUT(MinLavaDamage);
|
||||
eq->unknown888 = 1;
|
||||
eq->unknown889 = 0;
|
||||
eq->unknown890 = 1;
|
||||
@@ -2139,8 +2125,8 @@ namespace UF
|
||||
|
||||
for(auto i = 0; i < eq->total_abilities; ++i) {
|
||||
eq->abilities[i].skill_id = inapp->ReadUInt32();
|
||||
eq->abilities[i].base1 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base2 = inapp->ReadUInt32();
|
||||
eq->abilities[i].base_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].limit_value = inapp->ReadUInt32();
|
||||
eq->abilities[i].slot = inapp->ReadUInt32();
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
|
||||
@@ -450,8 +450,8 @@ struct NewZone_Struct {
|
||||
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||
/*0872*/ uint32 scriptIDSomething3;
|
||||
/*0876*/ uint32 SuspendBuffs;
|
||||
/*0880*/ uint32 unknown880; //seen 50
|
||||
/*0884*/ uint32 unknown884; //seen 10
|
||||
/*0880*/ uint32 LavaDamage; //seen 50
|
||||
/*0884*/ uint32 MinLavaDamage; //seen 10
|
||||
/*0888*/ uint8 unknown888; //seen 1
|
||||
/*0889*/ uint8 unknown889; //seen 0 (POK) or 1 (rujj)
|
||||
/*0890*/ uint8 unknown890; //seen 1
|
||||
@@ -3803,8 +3803,8 @@ struct UseAA_Struct {
|
||||
|
||||
struct AA_Ability {
|
||||
/*00*/ uint32 skill_id;
|
||||
/*04*/ uint32 base1;
|
||||
/*08*/ uint32 base2;
|
||||
/*04*/ uint32 base_value;
|
||||
/*08*/ uint32 limit_value;
|
||||
/*12*/ uint32 slot;
|
||||
/*16*/
|
||||
};
|
||||
|
||||
@@ -221,9 +221,6 @@ XS(XS_EQDB_escape_string)
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
XS(boot_EQDB); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(boot_EQDB)
|
||||
{
|
||||
|
||||
@@ -260,9 +260,6 @@ XS(XS_EQDBRes_fetch_lengths)
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
XS(boot_EQDBRes); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(boot_EQDBRes)
|
||||
{
|
||||
|
||||
@@ -2232,3 +2232,15 @@ bool PlayerAppearance::IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_v
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* GetGenderName(uint32 gender_id) {
|
||||
const char* gender_name = "Unknown";
|
||||
if (gender_id == MALE) {
|
||||
gender_name = "Male";
|
||||
} else if (gender_id == FEMALE) {
|
||||
gender_name = "Female";
|
||||
} else if (gender_id == NEUTER) {
|
||||
gender_name = "Neuter";
|
||||
}
|
||||
return gender_name;
|
||||
}
|
||||
@@ -851,6 +851,7 @@
|
||||
|
||||
const char* GetRaceIDName(uint16 race_id);
|
||||
const char* GetPlayerRaceName(uint32 player_race_value);
|
||||
const char* GetGenderName(uint32 gender_id);
|
||||
|
||||
uint32 GetPlayerRaceValue(uint16 race_id);
|
||||
uint32 GetPlayerRaceBit(uint16 race_id);
|
||||
@@ -1602,6 +1603,14 @@ namespace PlayerAppearance
|
||||
#define RACE_FALLEN_KNIGHT_722 722
|
||||
#define RACE_SERVANT_OF_SHADOW_723 723
|
||||
#define RACE_LUCLIN_724 724
|
||||
#define RACE_XARIC_725 725
|
||||
#define RACE_DERVISH_726 726
|
||||
#define RACE_DERVISH_727 727
|
||||
#define RACE_LUCLIN_728 728
|
||||
#define RACE_LUCLIN_729 729
|
||||
#define RACE_ORB_730 730
|
||||
#define RACE_LUCLIN_731 731
|
||||
#define RACE_PEGASUS_732 732
|
||||
#define RACE_INTERACTIVE_OBJECT_2250 2250
|
||||
|
||||
#endif
|
||||
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
entry.zone_in_time = 1800;
|
||||
entry.win_points = 0;
|
||||
entry.lose_points = 0;
|
||||
entry.theme = 1;
|
||||
entry.theme = LDoNThemes::GUK;
|
||||
entry.zone_in_zone_id = 0;
|
||||
entry.zone_in_x = 0;
|
||||
entry.zone_in_y = 0;
|
||||
|
||||
@@ -717,7 +717,7 @@ public:
|
||||
entry.itemclass = 0;
|
||||
entry.itemtype = 0;
|
||||
entry.ldonprice = 0;
|
||||
entry.ldontheme = 0;
|
||||
entry.ldontheme = LDoNThemes::Unused;
|
||||
entry.ldonsold = 0;
|
||||
entry.light = 0;
|
||||
entry.lore = "";
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_TOOL_GAME_OBJECTS_REPOSITORY_H
|
||||
#define EQEMU_BASE_TOOL_GAME_OBJECTS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../string_util.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseToolGameObjectsRepository {
|
||||
public:
|
||||
struct ToolGameObjects {
|
||||
int id;
|
||||
int zoneid;
|
||||
std::string zonesn;
|
||||
std::string object_name;
|
||||
std::string file_from;
|
||||
int is_global;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"zoneid",
|
||||
"zonesn",
|
||||
"object_name",
|
||||
"file_from",
|
||||
"is_global",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"zoneid",
|
||||
"zonesn",
|
||||
"object_name",
|
||||
"file_from",
|
||||
"is_global",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("tool_game_objects");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static ToolGameObjects NewEntity()
|
||||
{
|
||||
ToolGameObjects entry{};
|
||||
|
||||
entry.id = 0;
|
||||
entry.zoneid = 0;
|
||||
entry.zonesn = "";
|
||||
entry.object_name = "";
|
||||
entry.file_from = "";
|
||||
entry.is_global = 0;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static ToolGameObjects GetToolGameObjectsEntry(
|
||||
const std::vector<ToolGameObjects> &tool_game_objectss,
|
||||
int tool_game_objects_id
|
||||
)
|
||||
{
|
||||
for (auto &tool_game_objects : tool_game_objectss) {
|
||||
if (tool_game_objects.id == tool_game_objects_id) {
|
||||
return tool_game_objects;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static ToolGameObjects FindOne(
|
||||
Database& db,
|
||||
int tool_game_objects_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
tool_game_objects_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
ToolGameObjects entry{};
|
||||
|
||||
entry.id = atoi(row[0]);
|
||||
entry.zoneid = atoi(row[1]);
|
||||
entry.zonesn = row[2] ? row[2] : "";
|
||||
entry.object_name = row[3] ? row[3] : "";
|
||||
entry.file_from = row[4] ? row[4] : "";
|
||||
entry.is_global = atoi(row[5]);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int tool_game_objects_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
tool_game_objects_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
ToolGameObjects tool_game_objects_entry
|
||||
)
|
||||
{
|
||||
std::vector<std::string> update_values;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
update_values.push_back(columns[1] + " = " + std::to_string(tool_game_objects_entry.zoneid));
|
||||
update_values.push_back(columns[2] + " = '" + EscapeString(tool_game_objects_entry.zonesn) + "'");
|
||||
update_values.push_back(columns[3] + " = '" + EscapeString(tool_game_objects_entry.object_name) + "'");
|
||||
update_values.push_back(columns[4] + " = '" + EscapeString(tool_game_objects_entry.file_from) + "'");
|
||||
update_values.push_back(columns[5] + " = " + std::to_string(tool_game_objects_entry.is_global));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
implode(", ", update_values),
|
||||
PrimaryKey(),
|
||||
tool_game_objects_entry.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static ToolGameObjects InsertOne(
|
||||
Database& db,
|
||||
ToolGameObjects tool_game_objects_entry
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(tool_game_objects_entry.id));
|
||||
insert_values.push_back(std::to_string(tool_game_objects_entry.zoneid));
|
||||
insert_values.push_back("'" + EscapeString(tool_game_objects_entry.zonesn) + "'");
|
||||
insert_values.push_back("'" + EscapeString(tool_game_objects_entry.object_name) + "'");
|
||||
insert_values.push_back("'" + EscapeString(tool_game_objects_entry.file_from) + "'");
|
||||
insert_values.push_back(std::to_string(tool_game_objects_entry.is_global));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
implode(",", insert_values)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
tool_game_objects_entry.id = results.LastInsertedID();
|
||||
return tool_game_objects_entry;
|
||||
}
|
||||
|
||||
tool_game_objects_entry = NewEntity();
|
||||
|
||||
return tool_game_objects_entry;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
std::vector<ToolGameObjects> tool_game_objects_entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &tool_game_objects_entry: tool_game_objects_entries) {
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(tool_game_objects_entry.id));
|
||||
insert_values.push_back(std::to_string(tool_game_objects_entry.zoneid));
|
||||
insert_values.push_back("'" + EscapeString(tool_game_objects_entry.zonesn) + "'");
|
||||
insert_values.push_back("'" + EscapeString(tool_game_objects_entry.object_name) + "'");
|
||||
insert_values.push_back("'" + EscapeString(tool_game_objects_entry.file_from) + "'");
|
||||
insert_values.push_back(std::to_string(tool_game_objects_entry.is_global));
|
||||
|
||||
insert_chunks.push_back("(" + implode(",", insert_values) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<ToolGameObjects> All(Database& db)
|
||||
{
|
||||
std::vector<ToolGameObjects> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
ToolGameObjects entry{};
|
||||
|
||||
entry.id = atoi(row[0]);
|
||||
entry.zoneid = atoi(row[1]);
|
||||
entry.zonesn = row[2] ? row[2] : "";
|
||||
entry.object_name = row[3] ? row[3] : "";
|
||||
entry.file_from = row[4] ? row[4] : "";
|
||||
entry.is_global = atoi(row[5]);
|
||||
|
||||
all_entries.push_back(entry);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<ToolGameObjects> GetWhere(Database& db, std::string where_filter)
|
||||
{
|
||||
std::vector<ToolGameObjects> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
ToolGameObjects entry{};
|
||||
|
||||
entry.id = atoi(row[0]);
|
||||
entry.zoneid = atoi(row[1]);
|
||||
entry.zonesn = row[2] ? row[2] : "";
|
||||
entry.object_name = row[3] ? row[3] : "";
|
||||
entry.file_from = row[4] ? row[4] : "";
|
||||
entry.is_global = atoi(row[5]);
|
||||
|
||||
all_entries.push_back(entry);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, std::string where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_TOOL_GAME_OBJECTS_REPOSITORY_H
|
||||
@@ -110,6 +110,8 @@ public:
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
int underworld_teleport_index;
|
||||
int lava_damage;
|
||||
int min_lava_damage;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -212,6 +214,8 @@ public:
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
"underworld_teleport_index",
|
||||
"lava_damage",
|
||||
"min_lava_damage",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -339,6 +343,8 @@ public:
|
||||
entry.content_flags = "";
|
||||
entry.content_flags_disabled = "";
|
||||
entry.underworld_teleport_index = 0;
|
||||
entry.lava_damage = 50;
|
||||
entry.min_lava_damage = 10;
|
||||
|
||||
return entry;
|
||||
}
|
||||
@@ -466,6 +472,8 @@ public:
|
||||
entry.content_flags = row[89] ? row[89] : "";
|
||||
entry.content_flags_disabled = row[90] ? row[90] : "";
|
||||
entry.underworld_teleport_index = atoi(row[91]);
|
||||
entry.lava_damage = atoi(row[92]);
|
||||
entry.min_lava_damage = atoi(row[93]);
|
||||
|
||||
return entry;
|
||||
}
|
||||
@@ -590,6 +598,8 @@ public:
|
||||
update_values.push_back(columns[89] + " = '" + EscapeString(zone_entry.content_flags) + "'");
|
||||
update_values.push_back(columns[90] + " = '" + EscapeString(zone_entry.content_flags_disabled) + "'");
|
||||
update_values.push_back(columns[91] + " = " + std::to_string(zone_entry.underworld_teleport_index));
|
||||
update_values.push_back(columns[92] + " = " + std::to_string(zone_entry.lava_damage));
|
||||
update_values.push_back(columns[93] + " = " + std::to_string(zone_entry.min_lava_damage));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -703,6 +713,8 @@ public:
|
||||
insert_values.push_back("'" + EscapeString(zone_entry.content_flags) + "'");
|
||||
insert_values.push_back("'" + EscapeString(zone_entry.content_flags_disabled) + "'");
|
||||
insert_values.push_back(std::to_string(zone_entry.underworld_teleport_index));
|
||||
insert_values.push_back(std::to_string(zone_entry.lava_damage));
|
||||
insert_values.push_back(std::to_string(zone_entry.min_lava_damage));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -824,6 +836,8 @@ public:
|
||||
insert_values.push_back("'" + EscapeString(zone_entry.content_flags) + "'");
|
||||
insert_values.push_back("'" + EscapeString(zone_entry.content_flags_disabled) + "'");
|
||||
insert_values.push_back(std::to_string(zone_entry.underworld_teleport_index));
|
||||
insert_values.push_back(std::to_string(zone_entry.lava_damage));
|
||||
insert_values.push_back(std::to_string(zone_entry.min_lava_damage));
|
||||
|
||||
insert_chunks.push_back("(" + implode(",", insert_values) + ")");
|
||||
}
|
||||
@@ -949,6 +963,8 @@ public:
|
||||
entry.content_flags = row[89] ? row[89] : "";
|
||||
entry.content_flags_disabled = row[90] ? row[90] : "";
|
||||
entry.underworld_teleport_index = atoi(row[91]);
|
||||
entry.lava_damage = atoi(row[92]);
|
||||
entry.min_lava_damage = atoi(row[93]);
|
||||
|
||||
all_entries.push_back(entry);
|
||||
}
|
||||
@@ -1065,6 +1081,8 @@ public:
|
||||
entry.content_flags = row[89] ? row[89] : "";
|
||||
entry.content_flags_disabled = row[90] ? row[90] : "";
|
||||
entry.underworld_teleport_index = atoi(row[91]);
|
||||
entry.lava_damage = atoi(row[92]);
|
||||
entry.min_lava_damage = atoi(row[93]);
|
||||
|
||||
all_entries.push_back(entry);
|
||||
}
|
||||
|
||||
@@ -40,43 +40,48 @@ namespace ContentFilterCriteria {
|
||||
}
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}min_expansion <= {} OR {}min_expansion = 0)",
|
||||
" AND ({}min_expansion <= {} OR {}min_expansion = -1)",
|
||||
table_prefix,
|
||||
current_expansion_filter_criteria,
|
||||
table_prefix
|
||||
);
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}max_expansion >= {} OR {}max_expansion = 0)",
|
||||
" AND ({}max_expansion >= {} OR {}max_expansion = -1)",
|
||||
table_prefix,
|
||||
current_expansion_filter_criteria,
|
||||
table_prefix
|
||||
);
|
||||
|
||||
std::vector<std::string> flags = content_service.GetContentFlags();
|
||||
std::vector<std::string> flags_disabled = content_service.GetContentFlagsDisabled();
|
||||
std::vector<std::string> flags_enabled = content_service.GetContentFlagsEnabled();
|
||||
std::string flags_in_filter_enabled;
|
||||
std::string flags_in_filter_disabled;
|
||||
if (!flags.empty()) {
|
||||
if (!flags_enabled.empty()) {
|
||||
flags_in_filter_enabled = fmt::format(
|
||||
" OR CONCAT(',', {}content_flags, ',') REGEXP ',({}),' ",
|
||||
table_prefix,
|
||||
implode("|", flags)
|
||||
implode("|", flags_enabled)
|
||||
);
|
||||
}
|
||||
if (!flags_disabled.empty()) {
|
||||
flags_in_filter_disabled = fmt::format(
|
||||
" OR CONCAT(',', {}content_flags_disabled, ',') NOT REGEXP ',({}),' ",
|
||||
" OR CONCAT(',', {}content_flags_disabled, ',') REGEXP ',({}),' ",
|
||||
table_prefix,
|
||||
implode("|", flags)
|
||||
implode("|", flags_disabled)
|
||||
);
|
||||
}
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}content_flags IS NULL{}) ",
|
||||
" AND (({}content_flags IS NULL OR {}content_flags = ''){}) ",
|
||||
table_prefix,
|
||||
table_prefix,
|
||||
flags_in_filter_enabled
|
||||
);
|
||||
|
||||
criteria += fmt::format(
|
||||
" AND ({}content_flags_disabled IS NULL{}) ",
|
||||
" AND (({}content_flags_disabled IS NULL OR {}content_flags_disabled = ''){}) ",
|
||||
table_prefix,
|
||||
table_prefix,
|
||||
flags_in_filter_disabled
|
||||
);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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_TOOL_GAME_OBJECTS_REPOSITORY_H
|
||||
#define EQEMU_TOOL_GAME_OBJECTS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../string_util.h"
|
||||
#include "base/base_tool_game_objects_repository.h"
|
||||
|
||||
class ToolGameObjectsRepository: public BaseToolGameObjectsRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* ToolGameObjectsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* ToolGameObjectsRepository::GetWhereNeverExpires()
|
||||
* ToolGameObjectsRepository::GetWhereXAndY()
|
||||
* ToolGameObjectsRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_TOOL_GAME_OBJECTS_REPOSITORY_H
|
||||
+58
-3
@@ -139,6 +139,7 @@ RULE_INT(Character, TradeskillUpMakePoison, 2, "Make Poison skillup rate adjustm
|
||||
RULE_INT(Character, TradeskillUpPottery, 4, "Pottery skillup rate adjustment. Lower is faster")
|
||||
RULE_INT(Character, TradeskillUpResearch, 1, "Research skillup rate adjustment. Lower is faster")
|
||||
RULE_INT(Character, TradeskillUpTinkering, 2, "Tinkering skillup rate adjustment. Lower is faster")
|
||||
RULE_INT(Character, TradeskillUpTailoring, 2, "Tailoring skillup rate adjustment. Lower is faster")
|
||||
RULE_BOOL(Character, MarqueeHPUpdates, false, "Will show health percentage in center of screen if health lesser than 100%")
|
||||
RULE_INT(Character, IksarCommonTongue, 95, "Starting value for Common Tongue for Iksars")
|
||||
RULE_INT(Character, OgreCommonTongue, 95, "Starting value for Common Tongue for Ogres")
|
||||
@@ -167,6 +168,31 @@ RULE_BOOL(Character, EnableCharacterEXPMods, false, "Enables character zone-base
|
||||
RULE_BOOL(Character, PVPEnableGuardFactionAssist, true, "Enables faction based assisting against the aggresor in pvp.")
|
||||
RULE_BOOL(Character, SkillUpFromItems, true, "Allow Skill ups from clickable items")
|
||||
RULE_BOOL(Character, EnableTestBuff, false, "Allow the use of /testbuff")
|
||||
RULE_BOOL(Character, UseResurrectionSickness, true, "Use Resurrection Sickness based on Resurrection spell cast, set to false to disable Resurrection Sickness.")
|
||||
RULE_INT(Character, OldResurrectionSicknessSpellID, 757, "757 is Default Old Resurrection Sickness Spell ID")
|
||||
RULE_INT(Character, ResurrectionSicknessSpellID, 756, "756 is Default Resurrection Sickness Spell ID")
|
||||
RULE_BOOL(Character, EnableBardMelody, true, "Enable Bard /melody by default, to disable change to false for a classic experience.")
|
||||
RULE_BOOL(Character, EnableRangerAutoFire, true, "Enable Ranger /autofire by default, to disable change to false for a classic experience.")
|
||||
RULE_BOOL(Character, EnableTGB, true, "Enable /tgb (Target Group Buff) by default, to disable change to false for a classic experience.")
|
||||
RULE_INT(Character, SkillUpMaximumChancePercentage, 25, "Maximum chance to improve a combat skill, before skill-specific modifiers. This should be greater than SkillUpMinimumChancePercentage.")
|
||||
RULE_INT(Character, SkillUpMinimumChancePercentage, 2, "Minimum chance to improve a combat skill, after skill-specific modifiers. This should be lesser than SkillUpMaximumChancePercentage.")
|
||||
RULE_INT(Character, WarriorTrackingDistanceMultiplier, 0, "If you want warriors to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, ClericTrackingDistanceMultiplier, 0, "If you want clerics to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, PaladinTrackingDistanceMultiplier, 0, "If you want paladins to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, RangerTrackingDistanceMultiplier, 12, "If you want rangers to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, ShadowKnightTrackingDistanceMultiplier, 0, "If you want shadow knights to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, DruidTrackingDistanceMultiplier, 10, "If you want druids to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, MonkTrackingDistanceMultiplier, 0, "If you want monks to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, BardTrackingDistanceMultiplier, 7, "If you want bards to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, RogueTrackingDistanceMultiplier, 0, "If you want rogues to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, ShamanTrackingDistanceMultiplier, 0, "If you want shaman to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, NecromancerTrackingDistanceMultiplier, 0, "If you want necromancers to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, WizardTrackingDistanceMultiplier, 0, "If you want wizards to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, MagicianTrackingDistanceMultiplier, 0, "If you want magicians to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, EnchanterTrackingDistanceMultiplier, 0, "If you want enchanters to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, BeastlordTrackingDistanceMultiplier, 0, "If you want beastlords to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_INT(Character, BerserkerTrackingDistanceMultiplier, 0, "If you want berserkers to be able to track, increase this above 0. 0 disables tracking packets.")
|
||||
RULE_BOOL(Character, OnInviteReceiveAlreadyinGroupMessage, true, "If you want clients to receive a message when trying to invite a player into a group that is currently in another group.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Mercs)
|
||||
@@ -256,10 +282,11 @@ RULE_INT(Zone, ClientLinkdeadMS, 90000, "The time a client remains link dead on
|
||||
RULE_INT(Zone, GraveyardTimeMS, 1200000, "Time until a player corpse is moved to a zone's graveyard, if one is specified for the zone (milliseconds)")
|
||||
RULE_BOOL(Zone, EnableShadowrest, 1, "Enables or disables the Shadowrest zone feature for player corpses. Default is turned on")
|
||||
RULE_INT(Zone, AutoShutdownDelay, 5000, "How long a dynamic zone stays loaded while empty (milliseconds)")
|
||||
RULE_INT(Zone, PEQZoneReuseTime, 900, "Time between two uses of the #peqzone command (seconds)")
|
||||
RULE_INT(Zone, PEQZoneReuseTime, 900, "Seconds between two uses of the #peqzone command (Set to 0 to disable)")
|
||||
RULE_INT(Zone, PEQZoneDebuff1, 4454, "First debuff casted by #peqzone Default is Cursed Keeper's Blight")
|
||||
RULE_INT(Zone, PEQZoneDebuff2, 2209, "Second debuff casted by #peqzone Default is Tendrils of Apathy")
|
||||
RULE_BOOL(Zone, UsePEQZoneDebuffs, true, "Setting if the command #peqzone applies the defined debuffs")
|
||||
RULE_INT(Zone, PEQZoneHPRatio, 75, "Required HP Ratio to use #peqzone")
|
||||
RULE_REAL(Zone, HotZoneBonus, 0.75, "Value which is added to the experience multiplier. This also applies to AA experience.")
|
||||
RULE_INT(Zone, EbonCrystalItemID, 40902, "Item ID for Ebon Crystal")
|
||||
RULE_INT(Zone, RadiantCrystalItemID, 40903, "Item ID for Radiant Crystal")
|
||||
@@ -319,7 +346,7 @@ RULE_INT(Spells, MaxDiscSlotsNPC, 0, "Maximum number of NPC disc slots. NPC don'
|
||||
RULE_INT(Spells, MaxTotalSlotsNPC, 60, "Maximum total of NPC slots. The default value is the limit of the Titanium client")
|
||||
RULE_INT(Spells, MaxTotalSlotsPET, 30, "Maximum total of pet slots. The default value is the limit of the Titanium client")
|
||||
RULE_BOOL (Spells, EnableBlockedBuffs, true, "Allow blocked spells")
|
||||
RULE_INT(Spells, ReflectType, 3, "Reflect type. 0=disabled, 1=single target player spells only, 2=all player spells, 3=all single target spells, 4=all spells")
|
||||
RULE_INT(Spells, ReflectType, 4, "Reflect type. 0=disabled, 1=single target player spells only, 2=all player spells, 3=all single target spells, 4=all spells")
|
||||
RULE_BOOL(Spells, ReflectMessagesClose, true, "True (Live functionality) is for Reflect messages to show to players within close proximity. False shows just player reflecting")
|
||||
RULE_INT(Spells, VirusSpreadDistance, 30, "The distance a viral spell will jump to its next victim")
|
||||
RULE_BOOL(Spells, LiveLikeFocusEffects, true, "Determines whether specific healing, dmg and mana reduction focuses are randomized")
|
||||
@@ -380,6 +407,11 @@ RULE_BOOL(Spells, PreventFactionWarOnCharmBreak, false, "Enable spell interupts
|
||||
RULE_BOOL(Spells, AllowDoubleInvis, false, "Allows you to cast invisibility spells on a player that is already invisible")
|
||||
RULE_BOOL(Spells, AllowSpellMemorizeFromItem, false, "Allows players to memorize spells by right-clicking spell scrolls")
|
||||
RULE_BOOL(Spells, InvisRequiresGroup, false, "Invis requires the the target to be in group.")
|
||||
RULE_INT(Spells, ClericInnateHealFocus, 5, "Clerics on live get a 5 pct innate heal focus")
|
||||
RULE_BOOL(Spells, DOTsScaleWithSpellDmg, false, "Allow SpellDmg stat to affect DoT spells")
|
||||
RULE_BOOL(Spells, HOTsScaleWithHealAmt, false, "Allow HealAmt stat to affect HoT spells")
|
||||
RULE_BOOL(Spells, CompoundLifetapHeals, true, "True: Lifetap heals calculate damage bonuses and then heal bonuses. False: Lifetaps heal using the amount damaged to mob.")
|
||||
RULE_BOOL(Spells, UseFadingMemoriesMaxLevel, false, "Enables to limit field in spell data to set the max level that over which an NPC will ignore fading memories effect and not lose aggro.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Combat)
|
||||
@@ -391,7 +423,8 @@ RULE_INT(Combat, ArcheryCritDifficulty, 3400, "Value against which is rolled to
|
||||
RULE_INT(Combat, ThrowingCritDifficulty, 1100, "Value against which is rolled to check if a throwing crit is triggered. Lower is easier")
|
||||
RULE_BOOL(Combat, NPCCanCrit, false, "Setting whether an NPC can land critical hits")
|
||||
RULE_BOOL(Combat, UseIntervalAC, true, "Switch whether bonuses, armour class, multipliers, classes and caps should be considered in the calculation of damage values")
|
||||
RULE_INT(Combat, PetAttackMagicLevel, 30, "Level at which pets can cause magic damage")
|
||||
RULE_INT(Combat, PetAttackMagicLevel, 10, "Level at which pets can cause magic damage, no longer used")
|
||||
RULE_INT(Combat, NPCAttackMagicLevel, 10, "Level at which NPC and pets can cause magic damage")
|
||||
RULE_BOOL(Combat, EnableFearPathing, true, "Setting whether to use pathing during fear")
|
||||
RULE_BOOL(Combat, FleeGray, true, "If true FleeGrayHPRatio will be used")
|
||||
RULE_INT(Combat, FleeGrayHPRatio, 50, "HP percentage when a Gray NPC begins to flee")
|
||||
@@ -477,6 +510,9 @@ RULE_BOOL(Combat, UseExtendedPoisonProcs, false, "Allow old school poisons to la
|
||||
RULE_BOOL(Combat, EnableSneakPull, false, "Enable implementation of Sneak Pull")
|
||||
RULE_INT(Combat, SneakPullAssistRange, 400, "Modified range of assist for sneak pull")
|
||||
RULE_BOOL(Combat, Classic2HBAnimation, false, "2HB will use the 2 hand piercing animation instead of the overhead slashing animation")
|
||||
RULE_BOOL(Combat, ArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption")
|
||||
RULE_BOOL(Combat, ThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption")
|
||||
RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SE_RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(NPC)
|
||||
@@ -508,6 +544,7 @@ 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_BOOL(NPC, AnimalsOpenDoors, true, "Determines or not whether animals open doors or not when they approach them")
|
||||
RULE_INT(NPC, MaxRaceID, 732, "Maximum Race ID, RoF2 by default supports up to 732")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Aggro)
|
||||
@@ -580,6 +617,10 @@ RULE_REAL(Bots, LeashDistance, 562500.0f, "Distance a bot is allowed to travel f
|
||||
RULE_BOOL(Bots, AllowApplyPoisonCommand, true, "Allows the use of the bot command 'applypoison'")
|
||||
RULE_BOOL(Bots, AllowApplyPotionCommand, true, "Allows the use of the bot command 'applypotion'")
|
||||
RULE_BOOL(Bots, RestrictApplyPotionToRogue, true, "Restricts the bot command 'applypotion' to rogue-usable potions (i.e., poisons)")
|
||||
RULE_BOOL(Bots, OldRaceRezEffects, false, "Older clients had ID 757 for races with high starting STR, but it doesn't seem used anymore")
|
||||
RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on Resurrection spell cast, set to false to disable Resurrection Sickness.")
|
||||
RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell")
|
||||
RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell")
|
||||
RULE_CATEGORY_END()
|
||||
#endif
|
||||
|
||||
@@ -598,6 +639,10 @@ RULE_INT(Chat, IntervalDurationMS, 60000, "Interval length in milliseconds")
|
||||
RULE_INT(Chat, KarmaUpdateIntervalMS, 1200000, "Karma update interval in milliseconds")
|
||||
RULE_INT(Chat, KarmaGlobalChatLimit, 72, "Amount of karma you need to be able to talk in ooc/auction/chat below the level limit")
|
||||
RULE_INT(Chat, GlobalChatLevelLimit, 8, "Level limit you need to of reached to talk in ooc/auction/chat if your karma is too low")
|
||||
RULE_BOOL(Chat, AutoInjectSaylinksToSay, true, "Automatically injects saylinks into dialogue that has [brackets in them]")
|
||||
RULE_BOOL(Chat, AutoInjectSaylinksToClientMessage, true, "Automatically injects saylinks into dialogue that has [brackets in them]")
|
||||
RULE_BOOL(Chat, QuestDialogueUsesDialogueWindow, false, "Pipes all quest dialogue to dialogue window")
|
||||
RULE_BOOL(Chat, DialogueWindowAnimatesNPCsIfNoneSet, true, "If there is no animation specified in the dialogue window markdown then it will choose a random greet animation such as wave or salute")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Merchant)
|
||||
@@ -703,6 +748,7 @@ RULE_BOOL(Inventory, EnforceAugmentWear, true, "Forces augment wear slot validat
|
||||
RULE_BOOL(Inventory, DeleteTransformationMold, true, "False if you want mold to last forever")
|
||||
RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false, "Weapons can use any weapon transformation")
|
||||
RULE_BOOL(Inventory, TransformSummonedBags, false, "Transforms summoned bags into disenchanted ones instead of deleting")
|
||||
RULE_BOOL(Inventory, AllowMultipleOfSameAugment, false, "Allows multiple of the same augment to be placed in an item via #augmentitem or MQ2, set to true to allow")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Client)
|
||||
@@ -741,6 +787,7 @@ RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Expansion)
|
||||
RULE_INT(Expansion, CurrentExpansion, -1, "The current expansion enabled for the server [-1 = ALL, 0 = Classic, 1 = Kunark etc.]")
|
||||
RULE_BOOL(Expansion, UseCurrentExpansionAAOnly, false, "When true will only load AA ranks that match CurrentExpansion rule")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Instances)
|
||||
@@ -779,6 +826,14 @@ RULE_BOOL(Cheat, EnableMQFastMemDetector, true, "Enable the MQFastMem Detector.
|
||||
RULE_BOOL(Cheat, MarkMQWarpLT, false, "Mark clients makeing smaller warps")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Command)
|
||||
RULE_BOOL(Command, DyeCommandRequiresDyes, false, "Enable this to require a Prismatic Dye (32557) each time someone uses #dye.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Doors)
|
||||
RULE_BOOL(Doors, RequireKeyOnCursor, false, "Enable this to require pre-keyring keys to be on player cursor to open doors.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
#undef RULE_CATEGORY
|
||||
#undef RULE_INT
|
||||
#undef RULE_REAL
|
||||
|
||||
+205
-37
@@ -1,5 +1,5 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
|
||||
|
||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -11,7 +11,7 @@
|
||||
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
|
||||
@@ -24,7 +24,10 @@
|
||||
#include "item_instance.h"
|
||||
#include "item_data.h"
|
||||
#include "../zone/zonedb.h"
|
||||
#include <algorithm>
|
||||
|
||||
// static bucket global
|
||||
std::vector<SaylinkRepository::Saylink> g_cached_saylinks = {};
|
||||
|
||||
bool EQ::saylink::DegenerateLinkBody(SayLinkBody_Struct &say_link_body_struct, const std::string &say_link_body)
|
||||
{
|
||||
@@ -102,13 +105,13 @@ const std::string &EQ::SayLinkEngine::GenerateLink()
|
||||
m_Link = "<LINKER ERROR>";
|
||||
LogError("SayLinkEngine::GenerateLink() failed to generate a useable say link");
|
||||
LogError(">> LinkType: {}, Lengths: [link: {}({}), body: {}({}), text: {}({})]",
|
||||
m_LinkType,
|
||||
m_Link.length(),
|
||||
EQ::constants::SAY_LINK_MAXIMUM_SIZE,
|
||||
m_LinkBody.length(),
|
||||
EQ::constants::SAY_LINK_BODY_SIZE,
|
||||
m_LinkText.length(),
|
||||
EQ::constants::SAY_LINK_TEXT_SIZE
|
||||
m_LinkType,
|
||||
m_Link.length(),
|
||||
EQ::constants::SAY_LINK_MAXIMUM_SIZE,
|
||||
m_LinkBody.length(),
|
||||
EQ::constants::SAY_LINK_BODY_SIZE,
|
||||
m_LinkText.length(),
|
||||
EQ::constants::SAY_LINK_TEXT_SIZE
|
||||
);
|
||||
LogError(">> LinkBody: {}", m_LinkBody.c_str());
|
||||
LogError(">> LinkText: {}", m_LinkText.c_str());
|
||||
@@ -295,33 +298,9 @@ std::string EQ::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bo
|
||||
{
|
||||
uint32 saylink_id = 0;
|
||||
|
||||
/**
|
||||
* Query for an existing phrase and id in the saylink table
|
||||
*/
|
||||
std::string query = StringFormat(
|
||||
"SELECT `id` FROM `saylink` WHERE `phrase` = '%s' LIMIT 1",
|
||||
EscapeString(saylink_text).c_str());
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
|
||||
if (results.Success()) {
|
||||
if (results.RowCount() >= 1) {
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
saylink_id = static_cast<uint32>(atoi(row[0]));
|
||||
}
|
||||
else {
|
||||
std::string insert_query = StringFormat(
|
||||
"INSERT INTO `saylink` (`phrase`) VALUES ('%s')",
|
||||
EscapeString(saylink_text).c_str());
|
||||
|
||||
results = database.QueryDatabase(insert_query);
|
||||
if (!results.Success()) {
|
||||
LogError("Error in saylink phrase queries {}", results.ErrorMessage().c_str());
|
||||
}
|
||||
else {
|
||||
saylink_id = results.LastInsertedID();
|
||||
}
|
||||
}
|
||||
SaylinkRepository::Saylink saylink = GetOrSaveSaylink(saylink_text);
|
||||
if (saylink.id > 0) {
|
||||
saylink_id = saylink.id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,4 +318,193 @@ std::string EQ::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bo
|
||||
linker.SetProxyText(link_name.c_str());
|
||||
|
||||
return linker.GenerateLink();
|
||||
}
|
||||
}
|
||||
|
||||
std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
|
||||
{
|
||||
std::string new_message = message;
|
||||
int link_index = 0;
|
||||
int saylink_index = 0;
|
||||
std::vector<std::string> links = {};
|
||||
std::vector<std::string> saylinks = {};
|
||||
int saylink_length = 50;
|
||||
std::string saylink_separator = "\u0012";
|
||||
std::string saylink_partial = "00000";
|
||||
|
||||
LogSaylinkDetail("new_message pre pass 1 [{}]", new_message);
|
||||
|
||||
// first pass - strip existing saylinks by putting placeholder anchors on them
|
||||
for (auto &saylink: split_string(new_message, saylink_separator)) {
|
||||
if (!saylink.empty() && saylink.length() > saylink_length &&
|
||||
saylink.find(saylink_partial) != std::string::npos) {
|
||||
saylinks.emplace_back(saylink);
|
||||
|
||||
LogSaylinkDetail("Found saylink [{}]", saylink);
|
||||
|
||||
// replace with anchor
|
||||
find_replace(
|
||||
new_message,
|
||||
fmt::format("{}", saylink),
|
||||
fmt::format("<saylink:{}>", saylink_index)
|
||||
);
|
||||
|
||||
saylink_index++;
|
||||
}
|
||||
}
|
||||
|
||||
LogSaylinkDetail("new_message post pass 1 [{}]", new_message);
|
||||
|
||||
LogSaylinkDetail("saylink separator count [{}]", std::count(new_message.begin(), new_message.end(), '\u0012'));
|
||||
|
||||
// loop through brackets until none exist
|
||||
if (new_message.find('[') != std::string::npos) {
|
||||
for (auto &b: split_string(new_message, "[")) {
|
||||
if (!b.empty() && b.find(']') != std::string::npos) {
|
||||
std::vector<std::string> right_split = split_string(b, "]");
|
||||
if (!right_split.empty()) {
|
||||
std::string bracket_message = trim(right_split[0]);
|
||||
|
||||
// we shouldn't see a saylink fragment here, ignore this bracket
|
||||
if (bracket_message.find(saylink_partial) != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip where multiple saylinks are within brackets
|
||||
if (bracket_message.find(saylink_separator) != std::string::npos &&
|
||||
std::count(bracket_message.begin(), bracket_message.end(), '\u0012') > 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if non empty bracket contents
|
||||
if (!bracket_message.empty()) {
|
||||
LogSaylinkDetail("Found bracket_message [{}]", bracket_message);
|
||||
|
||||
// already a saylink
|
||||
// todo: improve this later
|
||||
if (!bracket_message.empty() &&
|
||||
(bracket_message.length() > saylink_length ||
|
||||
bracket_message.find(saylink_separator) != std::string::npos)) {
|
||||
links.emplace_back(bracket_message);
|
||||
}
|
||||
else {
|
||||
links.emplace_back(
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
bracket_message,
|
||||
false,
|
||||
bracket_message
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// replace with anchor
|
||||
find_replace(
|
||||
new_message,
|
||||
fmt::format("[{}]", bracket_message),
|
||||
fmt::format("<prelink:{}>", link_index)
|
||||
);
|
||||
|
||||
link_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogSaylinkDetail("new_message post pass 2 (post brackets) [{}]", new_message);
|
||||
|
||||
// strip any current delimiters of saylinks
|
||||
find_replace(new_message, saylink_separator, "");
|
||||
|
||||
// pop links onto anchors
|
||||
link_index = 0;
|
||||
for (auto &link: links) {
|
||||
|
||||
// strip any current delimiters of saylinks
|
||||
find_replace(link, saylink_separator, "");
|
||||
|
||||
find_replace(
|
||||
new_message,
|
||||
fmt::format("<prelink:{}>", link_index),
|
||||
fmt::format("[\u0012{}\u0012]", link)
|
||||
);
|
||||
link_index++;
|
||||
}
|
||||
|
||||
LogSaylinkDetail("new_message post pass 3 (post prelink anchor pop) [{}]", new_message);
|
||||
|
||||
// pop links onto anchors
|
||||
saylink_index = 0;
|
||||
for (auto &link: saylinks) {
|
||||
// strip any current delimiters of saylinks
|
||||
find_replace(link, saylink_separator, "");
|
||||
|
||||
// check to see if we did a double anchor pass (existing saylink that was also inside brackets)
|
||||
// this means we found a saylink and we're checking to see if we're already encoded before double encoding
|
||||
if (new_message.find(fmt::format("\u0012<saylink:{}>\u0012", saylink_index)) != std::string::npos) {
|
||||
LogSaylinkDetail("Found encoded saylink at index [{}]", saylink_index);
|
||||
|
||||
find_replace(
|
||||
new_message,
|
||||
fmt::format("\u0012<saylink:{}>\u0012", saylink_index),
|
||||
fmt::format("\u0012{}\u0012", link)
|
||||
);
|
||||
saylink_index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
find_replace(
|
||||
new_message,
|
||||
fmt::format("<saylink:{}>", saylink_index),
|
||||
fmt::format("\u0012{}\u0012", link)
|
||||
);
|
||||
saylink_index++;
|
||||
}
|
||||
|
||||
LogSaylinkDetail("new_message post pass 4 (post saylink anchor pop) [{}]", new_message);
|
||||
|
||||
return new_message;
|
||||
}
|
||||
|
||||
void EQ::SayLinkEngine::LoadCachedSaylinks()
|
||||
{
|
||||
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not like '%#%'");
|
||||
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
|
||||
g_cached_saylinks = saylinks;
|
||||
}
|
||||
|
||||
SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string saylink_text)
|
||||
{
|
||||
// return cached saylink if exist
|
||||
if (!g_cached_saylinks.empty()) {
|
||||
for (auto &s: g_cached_saylinks) {
|
||||
if (s.phrase == saylink_text) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto saylinks = SaylinkRepository::GetWhere(
|
||||
database,
|
||||
fmt::format("phrase = '{}'", EscapeString(saylink_text))
|
||||
);
|
||||
|
||||
// return if found from the database
|
||||
if (!saylinks.empty()) {
|
||||
return saylinks[0];
|
||||
}
|
||||
|
||||
// if not found in database - save
|
||||
if (saylinks.empty()) {
|
||||
auto new_saylink = SaylinkRepository::NewEntity();
|
||||
new_saylink.phrase = saylink_text;
|
||||
|
||||
// persist to database
|
||||
auto link = SaylinkRepository::InsertOne(database, new_saylink);
|
||||
if (link.id > 0) {
|
||||
g_cached_saylinks.emplace_back(link);
|
||||
return link;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
+7
-4
@@ -1,17 +1,17 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
|
||||
|
||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
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
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "types.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "repositories/saylink_repository.h"
|
||||
|
||||
struct ServerLootItem_Struct;
|
||||
|
||||
@@ -105,6 +105,8 @@ namespace EQ
|
||||
|
||||
void Reset();
|
||||
|
||||
static std::string InjectSaylinksIfNotExist(const char *message);
|
||||
static void LoadCachedSaylinks();
|
||||
private:
|
||||
void generate_body();
|
||||
void generate_text();
|
||||
@@ -120,6 +122,7 @@ namespace EQ
|
||||
std::string m_LinkBody;
|
||||
std::string m_LinkText;
|
||||
bool m_Error;
|
||||
static SaylinkRepository::Saylink GetOrSaveSaylink(std::string saylink_text);
|
||||
};
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
+189
-594
@@ -226,91 +226,28 @@
|
||||
#define ServerOP_UCSServerStatusReply 0x4010
|
||||
#define ServerOP_HotReloadQuests 0x4011
|
||||
#define ServerOP_UpdateSchedulerEvents 0x4012
|
||||
#define ServerOP_ReloadContentFlags 0x4013
|
||||
|
||||
#define ServerOP_CZCastSpellPlayer 0x4500
|
||||
#define ServerOP_CZCastSpellGroup 0x4501
|
||||
#define ServerOP_CZCastSpellRaid 0x4502
|
||||
#define ServerOP_CZCastSpellGuild 0x4503
|
||||
#define ServerOP_CZMarqueePlayer 0x4504
|
||||
#define ServerOP_CZMarqueeGroup 0x4505
|
||||
#define ServerOP_CZMarqueeRaid 0x4506
|
||||
#define ServerOP_CZMarqueeGuild 0x4507
|
||||
#define ServerOP_CZMessagePlayer 0x4508
|
||||
#define ServerOP_CZMessageGroup 0x4509
|
||||
#define ServerOP_CZMessageRaid 0x4510
|
||||
#define ServerOP_CZMessageGuild 0x4511
|
||||
#define ServerOP_CZMovePlayer 0x4512
|
||||
#define ServerOP_CZMoveGroup 0x4513
|
||||
#define ServerOP_CZMoveRaid 0x4514
|
||||
#define ServerOP_CZMoveGuild 0x4515
|
||||
#define ServerOP_CZMoveInstancePlayer 0x4516
|
||||
#define ServerOP_CZMoveInstanceGroup 0x4517
|
||||
#define ServerOP_CZMoveInstanceRaid 0x4518
|
||||
#define ServerOP_CZMoveInstanceGuild 0x4519
|
||||
#define ServerOP_CZRemoveSpellPlayer 0x4520
|
||||
#define ServerOP_CZRemoveSpellGroup 0x4521
|
||||
#define ServerOP_CZRemoveSpellRaid 0x4522
|
||||
#define ServerOP_CZRemoveSpellGuild 0x4523
|
||||
#define ServerOP_CZSetEntityVariableByClientName 0x4524
|
||||
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x4525
|
||||
#define ServerOP_CZSetEntityVariableByGroupID 0x4526
|
||||
#define ServerOP_CZSetEntityVariableByRaidID 0x4527
|
||||
#define ServerOP_CZSetEntityVariableByGuildID 0x4528
|
||||
#define ServerOP_CZSignalClient 0x4529
|
||||
#define ServerOP_CZSignalClientByName 0x4530
|
||||
#define ServerOP_CZSignalNPC 0x4531
|
||||
#define ServerOP_CZSignalGroup 0x4532
|
||||
#define ServerOP_CZSignalRaid 0x4533
|
||||
#define ServerOP_CZSignalGuild 0x4534
|
||||
#define ServerOP_CZTaskActivityResetPlayer 0x4535
|
||||
#define ServerOP_CZTaskActivityResetGroup 0x4536
|
||||
#define ServerOP_CZTaskActivityResetRaid 0x4537
|
||||
#define ServerOP_CZTaskActivityResetGuild 0x4538
|
||||
#define ServerOP_CZTaskActivityUpdatePlayer 0x4539
|
||||
#define ServerOP_CZTaskActivityUpdateGroup 0x4540
|
||||
#define ServerOP_CZTaskActivityUpdateRaid 0x4541
|
||||
#define ServerOP_CZTaskActivityUpdateGuild 0x4542
|
||||
#define ServerOP_CZTaskAssignPlayer 0x4543
|
||||
#define ServerOP_CZTaskAssignGroup 0x4544
|
||||
#define ServerOP_CZTaskAssignRaid 0x4545
|
||||
#define ServerOP_CZTaskAssignGuild 0x4546
|
||||
#define ServerOP_CZTaskDisablePlayer 0x4547
|
||||
#define ServerOP_CZTaskDisableGroup 0x4548
|
||||
#define ServerOP_CZTaskDisableRaid 0x4549
|
||||
#define ServerOP_CZTaskDisableGuild 0x4550
|
||||
#define ServerOP_CZTaskEnablePlayer 0x4551
|
||||
#define ServerOP_CZTaskEnableGroup 0x4552
|
||||
#define ServerOP_CZTaskEnableRaid 0x4553
|
||||
#define ServerOP_CZTaskEnableGuild 0x4554
|
||||
#define ServerOP_CZTaskFailPlayer 0x4555
|
||||
#define ServerOP_CZTaskFailGroup 0x4556
|
||||
#define ServerOP_CZTaskFailRaid 0x4557
|
||||
#define ServerOP_CZTaskFailGuild 0x4558
|
||||
#define ServerOP_CZTaskRemovePlayer 0x4559
|
||||
#define ServerOP_CZTaskRemoveGroup 0x4560
|
||||
#define ServerOP_CZTaskRemoveRaid 0x4561
|
||||
#define ServerOP_CZTaskRemoveGuild 0x4562
|
||||
#define ServerOP_CZClientMessageString 0x4563
|
||||
#define ServerOP_CZLDoNUpdate 0x4564
|
||||
#define ServerOP_CZDialogueWindow 0x4500
|
||||
#define ServerOP_CZLDoNUpdate 0x4501
|
||||
#define ServerOP_CZMarquee 0x4502
|
||||
#define ServerOP_CZMessage 0x4503
|
||||
#define ServerOP_CZMove 0x4504
|
||||
#define ServerOP_CZSetEntityVariable 0x4505
|
||||
#define ServerOP_CZSignal 0x4506
|
||||
#define ServerOP_CZSpell 0x4507
|
||||
#define ServerOP_CZTaskUpdate 0x4508
|
||||
#define ServerOP_CZClientMessageString 0x4509
|
||||
|
||||
#define ServerOP_WWAssignTask 0x4750
|
||||
#define ServerOP_WWCastSpell 0x4751
|
||||
#define ServerOP_WWCompleteActivity 0x4752
|
||||
#define ServerOP_WWDisableTask 0x4753
|
||||
#define ServerOP_WWEnableTask 0x4754
|
||||
#define ServerOP_WWFailTask 0x4755
|
||||
#define ServerOP_WWMarquee 0x4756
|
||||
#define ServerOP_WWMessage 0x4757
|
||||
#define ServerOP_WWMove 0x4758
|
||||
#define ServerOP_WWMoveInstance 0x4759
|
||||
#define ServerOP_WWRemoveSpell 0x4760
|
||||
#define ServerOP_WWRemoveTask 0x4761
|
||||
#define ServerOP_WWResetActivity 0x4762
|
||||
#define ServerOP_WWSetEntityVariableClient 0x4763
|
||||
#define ServerOP_WWSetEntityVariableNPC 0x4764
|
||||
#define ServerOP_WWSignalClient 0x4765
|
||||
#define ServerOP_WWSignalNPC 0x4766
|
||||
#define ServerOP_WWUpdateActivity 0x4767
|
||||
#define ServerOP_WWDialogueWindow 0x4750
|
||||
#define ServerOP_WWLDoNUpdate 0x4751
|
||||
#define ServerOP_WWMarquee 0x4752
|
||||
#define ServerOP_WWMessage 0x4753
|
||||
#define ServerOP_WWMove 0x4754
|
||||
#define ServerOP_WWSetEntityVariable 0x4755
|
||||
#define ServerOP_WWSignal 0x4756
|
||||
#define ServerOP_WWSpell 0x4757
|
||||
#define ServerOP_WWTaskUpdate 0x4758
|
||||
|
||||
/**
|
||||
* QueryServer
|
||||
@@ -325,17 +262,79 @@
|
||||
#define ServerOP_QSPlayerDropItem 0x5007
|
||||
|
||||
enum {
|
||||
CZLDoNUpdateType_Character = 0,
|
||||
CZLDoNUpdateType_Group,
|
||||
CZLDoNUpdateType_Raid,
|
||||
CZLDoNUpdateType_Guild,
|
||||
CZLDoNUpdateType_Expedition
|
||||
CZUpdateType_Character,
|
||||
CZUpdateType_Group,
|
||||
CZUpdateType_Raid,
|
||||
CZUpdateType_Guild,
|
||||
CZUpdateType_Expedition,
|
||||
CZUpdateType_ClientName,
|
||||
CZUpdateType_NPC
|
||||
};
|
||||
|
||||
enum {
|
||||
CZLDoNUpdateSubtype_Win = 0,
|
||||
CZLDoNUpdateSubtype_Loss,
|
||||
CZLDoNUpdateSubtype_Points
|
||||
CZLDoNUpdateSubtype_AddLoss,
|
||||
CZLDoNUpdateSubtype_AddPoints,
|
||||
CZLDoNUpdateSubtype_AddWin,
|
||||
CZLDoNUpdateSubtype_RemoveLoss,
|
||||
CZLDoNUpdateSubtype_RemoveWin,
|
||||
};
|
||||
|
||||
enum {
|
||||
CZMoveUpdateSubtype_MoveZone,
|
||||
CZMoveUpdateSubtype_MoveZoneInstance
|
||||
};
|
||||
|
||||
enum {
|
||||
CZSpellUpdateSubtype_Cast,
|
||||
CZSpellUpdateSubtype_Remove
|
||||
};
|
||||
|
||||
enum {
|
||||
CZTaskUpdateSubtype_ActivityReset,
|
||||
CZTaskUpdateSubtype_ActivityUpdate,
|
||||
CZTaskUpdateSubtype_AssignTask,
|
||||
CZTaskUpdateSubtype_DisableTask,
|
||||
CZTaskUpdateSubtype_EnableTask,
|
||||
CZTaskUpdateSubtype_FailTask,
|
||||
CZTaskUpdateSubtype_RemoveTask
|
||||
};
|
||||
|
||||
enum {
|
||||
WWLDoNUpdateType_AddLoss,
|
||||
WWLDoNUpdateType_AddPoints,
|
||||
WWLDoNUpdateType_AddWin,
|
||||
WWLDoNUpdateType_RemoveLoss,
|
||||
WWLDoNUpdateType_RemoveWin
|
||||
};
|
||||
|
||||
enum {
|
||||
WWMoveUpdateType_MoveZone,
|
||||
WWMoveUpdateType_MoveZoneInstance
|
||||
};
|
||||
|
||||
enum {
|
||||
WWSetEntityVariableUpdateType_Character,
|
||||
WWSetEntityVariableUpdateType_NPC
|
||||
};
|
||||
|
||||
enum {
|
||||
WWSignalUpdateType_Character,
|
||||
WWSignalUpdateType_NPC
|
||||
};
|
||||
|
||||
enum {
|
||||
WWSpellUpdateType_Cast,
|
||||
WWSpellUpdateType_Remove
|
||||
};
|
||||
|
||||
enum {
|
||||
WWTaskUpdateType_ActivityReset,
|
||||
WWTaskUpdateType_ActivityUpdate,
|
||||
WWTaskUpdateType_AssignTask,
|
||||
WWTaskUpdateType_DisableTask,
|
||||
WWTaskUpdateType_EnableTask,
|
||||
WWTaskUpdateType_FailTask,
|
||||
WWTaskUpdateType_RemoveTask
|
||||
};
|
||||
|
||||
/* Query Serv Generic Packet Flag/Type Enumeration */
|
||||
@@ -1440,489 +1439,107 @@ struct QSGeneralQuery_Struct {
|
||||
char QueryString[0];
|
||||
};
|
||||
|
||||
struct CZCastSpellPlayer_Struct {
|
||||
int character_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZCastSpellGroup_Struct {
|
||||
int group_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZCastSpellRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZCastSpellGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZClientSignal_Struct {
|
||||
int character_id;
|
||||
uint32 signal;
|
||||
};
|
||||
|
||||
struct CZGroupSignal_Struct {
|
||||
int group_id;
|
||||
uint32 signal;
|
||||
};
|
||||
|
||||
struct CZRaidSignal_Struct {
|
||||
int raid_id;
|
||||
uint32 signal;
|
||||
};
|
||||
|
||||
struct CZGuildSignal_Struct {
|
||||
int guild_id;
|
||||
uint32 signal;
|
||||
};
|
||||
|
||||
struct CZNPCSignal_Struct {
|
||||
uint32 npctype_id;
|
||||
uint32 signal;
|
||||
};
|
||||
|
||||
struct CZClientMessageString_Struct {
|
||||
uint32 string_id;
|
||||
uint16 chat_type;
|
||||
char character_name[64];
|
||||
char client_name[64];
|
||||
uint32 args_size;
|
||||
char args[1]; // null delimited
|
||||
};
|
||||
|
||||
struct CZClientSignalByName_Struct {
|
||||
char character_name[64];
|
||||
uint32 signal;
|
||||
};
|
||||
|
||||
struct CZCompleteActivityPlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZCompleteActivityGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZCompleteActivityRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZCompleteActivityGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZMovePlayer_Struct {
|
||||
int character_id;
|
||||
char zone_short_name[32];
|
||||
};
|
||||
|
||||
struct CZMarqueePlayer_Struct {
|
||||
int character_id;
|
||||
uint32 type;
|
||||
uint32 priority;
|
||||
uint32 fade_in;
|
||||
uint32 fade_out;
|
||||
uint32 duration;
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMarqueeGroup_Struct {
|
||||
int group_id;
|
||||
uint32 type;
|
||||
uint32 priority;
|
||||
uint32 fade_in;
|
||||
uint32 fade_out;
|
||||
uint32 duration;
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMarqueeRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 type;
|
||||
uint32 priority;
|
||||
uint32 fade_in;
|
||||
uint32 fade_out;
|
||||
uint32 duration;
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMarqueeGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 type;
|
||||
uint32 priority;
|
||||
uint32 fade_in;
|
||||
uint32 fade_out;
|
||||
uint32 duration;
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMessagePlayer_Struct {
|
||||
uint32 type;
|
||||
char character_name[64];
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMessageGroup_Struct {
|
||||
uint32 type;
|
||||
int group_id;
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMessageRaid_Struct {
|
||||
uint32 type;
|
||||
int raid_id;
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMessageGuild_Struct {
|
||||
uint32 type;
|
||||
int guild_id;
|
||||
char message[512];
|
||||
};
|
||||
|
||||
struct CZMoveGroup_Struct {
|
||||
int group_id;
|
||||
char zone_short_name[32];
|
||||
};
|
||||
|
||||
struct CZMoveRaid_Struct {
|
||||
int raid_id;
|
||||
char zone_short_name[32];
|
||||
};
|
||||
|
||||
struct CZMoveGuild_Struct {
|
||||
int guild_id;
|
||||
char zone_short_name[32];
|
||||
};
|
||||
|
||||
struct CZMoveInstancePlayer_Struct {
|
||||
int character_id;
|
||||
uint16 instance_id;
|
||||
};
|
||||
|
||||
struct CZMoveInstanceGroup_Struct {
|
||||
int group_id;
|
||||
uint16 instance_id;
|
||||
};
|
||||
|
||||
struct CZMoveInstanceRaid_Struct {
|
||||
int raid_id;
|
||||
uint16 instance_id;
|
||||
};
|
||||
|
||||
struct CZMoveInstanceGuild_Struct {
|
||||
int guild_id;
|
||||
uint16 instance_id;
|
||||
};
|
||||
|
||||
struct CZRemoveSpellPlayer_Struct {
|
||||
int character_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZRemoveSpellGroup_Struct {
|
||||
int group_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZRemoveSpellRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZRemoveSpellGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct CZRemoveTaskPlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZRemoveTaskGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZRemoveTaskRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZRemoveTaskGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZResetActivityPlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZResetActivityGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZResetActivityRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZResetActivityGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZSetEntVarByNPCTypeID_Struct {
|
||||
uint32 npctype_id;
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
};
|
||||
|
||||
struct CZSetEntVarByClientName_Struct {
|
||||
char character_name[64];
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
};
|
||||
|
||||
struct CZSetEntVarByGroupID_Struct {
|
||||
int group_id;
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
};
|
||||
|
||||
struct CZSetEntVarByRaidID_Struct {
|
||||
int raid_id;
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
};
|
||||
|
||||
struct CZSetEntVarByGuildID_Struct {
|
||||
int guild_id;
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
};
|
||||
|
||||
struct CZTaskActivityResetPlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZTaskActivityResetGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZTaskActivityResetRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZTaskActivityResetGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
};
|
||||
|
||||
struct CZTaskActivityUpdatePlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
int activity_count;
|
||||
};
|
||||
|
||||
struct CZTaskActivityUpdateGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
int activity_count;
|
||||
};
|
||||
|
||||
struct CZTaskActivityUpdateRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
int activity_count;
|
||||
};
|
||||
|
||||
struct CZTaskActivityUpdateGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
int activity_count;
|
||||
};
|
||||
|
||||
struct CZTaskAssignPlayer_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
bool enforce_level_requirement;
|
||||
};
|
||||
|
||||
struct CZTaskAssignGroup_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
bool enforce_level_requirement;
|
||||
};
|
||||
|
||||
struct CZTaskAssignRaid_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
bool enforce_level_requirement;
|
||||
};
|
||||
|
||||
struct CZTaskAssignGuild_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
bool enforce_level_requirement;
|
||||
};
|
||||
|
||||
struct CZTaskDisablePlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskDisableGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskDisableRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskDisableGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskEnablePlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskEnableGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskEnableRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskEnableGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskFailPlayer_Struct {
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskFailGroup_Struct {
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskFailRaid_Struct {
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskFailGuild_Struct {
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskRemovePlayer_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int character_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskRemoveGroup_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int group_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskRemoveRaid_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int raid_id;
|
||||
uint32 task_id;
|
||||
};
|
||||
|
||||
struct CZTaskRemoveGuild_Struct {
|
||||
uint16 npc_entity_id;
|
||||
int guild_id;
|
||||
uint32 task_id;
|
||||
struct CZDialogueWindow_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
char message[4096];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZLDoNUpdate_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition
|
||||
uint8 update_subtype; // 0 - Win, 1 - Loss, 2 - Points
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Loss, 1 - Points, 2 - Win
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 theme_id;
|
||||
int points; // Always 1, except for when Points are used
|
||||
int points; // Only used in Points Subtype, else 1
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct WWAssignTask_Struct {
|
||||
uint16 npc_entity_id;
|
||||
uint32 task_id;
|
||||
bool enforce_level_requirement;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
struct CZMarquee_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 type;
|
||||
uint32 priority;
|
||||
uint32 fade_in;
|
||||
uint32 fade_out;
|
||||
uint32 duration;
|
||||
char message[512];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct WWCastSpell_Struct {
|
||||
struct CZMessage_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
int update_identifier; // Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 type;
|
||||
char message[512];
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZMove_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Move Zone, 1 - Move Zone Instance
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint16 instance_id; // Only used by Move Zone Instance, else 0
|
||||
char zone_short_name[32]; // Only by with Move Zone, else empty
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZSetEntityVariable_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name, 6 - NPC
|
||||
int update_identifier; // Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
char client_name[64]; // Only used by Character Type, else empty
|
||||
};
|
||||
|
||||
struct CZSignal_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name, 6 - NPC
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, Expedition ID, or NPC ID based on update type, 0 for Character Name
|
||||
uint32 signal;
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZSpell_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Cast Spell, 1 - Remove Spell
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 spell_id;
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct CZTaskUpdate_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - Group, 2 - Raid, 3 - Guild, 4 - Expedition, 5 - Character Name
|
||||
uint8 update_subtype; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
|
||||
int update_identifier; // Character ID, Group ID, Raid ID, Guild ID, or Expedition ID based on update type, 0 for Character Name
|
||||
uint32 task_identifier;
|
||||
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
|
||||
int update_count; // Only used by Activity Update, else 1
|
||||
bool enforce_level_requirement; // Only used by Assign Task
|
||||
char client_name[64]; // Only used by Character Name Type, else empty
|
||||
};
|
||||
|
||||
struct WWDialogueWindow_Struct {
|
||||
char message[4096];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWDisableTask_Struct {
|
||||
uint32 task_id;
|
||||
struct WWLDoNUpdate_Struct {
|
||||
uint8 update_type; // 0 - Loss, 1 - Points, 2 - Win
|
||||
uint32 theme_id;
|
||||
int points; // Only used in Points Subtype, else 1
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWEnableTask_Struct {
|
||||
uint32 task_id;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWFailTask_Struct {
|
||||
uint32 task_id;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
struct WWMarquee_Struct {
|
||||
uint32 type;
|
||||
uint32 priority;
|
||||
@@ -1942,63 +1559,41 @@ struct WWMessage_Struct {
|
||||
};
|
||||
|
||||
struct WWMove_Struct {
|
||||
char zone_short_name[32];
|
||||
uint8 update_type; // 0 - Move Zone, 1 - Move Zone Instance
|
||||
char zone_short_name[32]; // Used with Move Zone
|
||||
uint16 instance_id; // Used with Move Zone Instance
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWMoveInstance_Struct {
|
||||
uint16 instance_id;
|
||||
struct WWSetEntityVariable_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - NPC
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWRemoveSpell_Struct {
|
||||
struct WWSignal_Struct {
|
||||
uint8 update_type; // 0 - Character, 1 - NPC
|
||||
uint32 signal;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWSpell_Struct {
|
||||
uint8 update_type; // 0 - Cast Spell, 1 - Remove Spell
|
||||
uint32 spell_id;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWRemoveTask_Struct {
|
||||
uint32 task_id;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
|
||||
};
|
||||
|
||||
struct WWResetActivity_Struct {
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWSetEntVarClient_Struct {
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWSetEntVarNPC_Struct {
|
||||
char variable_name[256];
|
||||
char variable_value[256];
|
||||
};
|
||||
|
||||
struct WWSignalClient_Struct {
|
||||
uint32 signal;
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
struct WWSignalNPC_Struct {
|
||||
uint32 signal;
|
||||
};
|
||||
|
||||
struct WWUpdateActivity_Struct {
|
||||
uint32 task_id;
|
||||
int activity_id;
|
||||
int activity_count;
|
||||
struct WWTaskUpdate_Struct {
|
||||
uint8 update_type; // 0 - Activity Reset, 1 - Activity Update, 2 - Assign Task, 3 - Disable Task, 4 - Enable Task, 5 - Fail Task, 6 - Remove Task
|
||||
uint32 task_identifier;
|
||||
int task_subidentifier; // Activity ID for Activity Reset and Activity Update, NPC Entity ID for Assign Task, else -1
|
||||
int update_count; // Update Count for Activity Update, else 1
|
||||
bool enforce_level_requirement; // Only used by Assign Task, else false
|
||||
uint8 min_status;
|
||||
uint8 max_status;
|
||||
};
|
||||
|
||||
+59
-58
@@ -1118,7 +1118,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
||||
item.Haste = (uint32)atoul(row[ItemField::haste]);
|
||||
item.DamageShield = (uint32)atoul(row[ItemField::damageshield]);
|
||||
item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]);
|
||||
item.RecastType = (uint32)atoul(row[ItemField::recasttype]);
|
||||
item.RecastType = (int)atoi(row[ItemField::recasttype]);
|
||||
item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]);
|
||||
item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]);
|
||||
item.Attuneable = (atoi(row[ItemField::attuneable]) == 0) ? false : true;
|
||||
@@ -1682,7 +1682,7 @@ void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpe
|
||||
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]);
|
||||
sp[spellID].damage_shield_type = atoi(row[1]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1762,48 +1762,48 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades));
|
||||
|
||||
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].aoe_range=static_cast<float>(atof(row[10]));
|
||||
sp[tempid].push_back=static_cast<float>(atof(row[11]));
|
||||
sp[tempid].push_up=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].buff_duration_formula=atoi(row[16]);
|
||||
sp[tempid].buff_duration=atoi(row[17]);
|
||||
sp[tempid].aoe_duration=atoi(row[18]);
|
||||
sp[tempid].mana=atoi(row[19]);
|
||||
|
||||
int y=0;
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].base[y]=atoi(row[20+y]); // effect_base_value
|
||||
sp[tempid].base_value[y]=atoi(row[20+y]); // effect_base_value
|
||||
|
||||
for(y=0; y < EFFECT_COUNT; y++)
|
||||
sp[tempid].base2[y]=atoi(row[32+y]); // effect_limit_value
|
||||
sp[tempid].limit_value[y]=atoi(row[32+y]); // effect_limit_value
|
||||
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].max[y]=atoi(row[44+y]);
|
||||
sp[tempid].max_value[y]=atoi(row[44+y]);
|
||||
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].components[y]=atoi(row[58+y]);
|
||||
sp[tempid].component[y]=atoi(row[58+y]);
|
||||
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].component_counts[y]=atoi(row[62+y]);
|
||||
sp[tempid].component_count[y]=atoi(row[62+y]);
|
||||
|
||||
for(y=0; y< 4;y++)
|
||||
sp[tempid].NoexpendReagent[y]=atoi(row[66+y]);
|
||||
sp[tempid].no_expend_reagent[y]=atoi(row[66+y]);
|
||||
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].formula[y]=atoi(row[70+y]);
|
||||
|
||||
sp[tempid].goodEffect=atoi(row[83]);
|
||||
sp[tempid].Activated=atoi(row[84]);
|
||||
sp[tempid].resisttype=atoi(row[85]);
|
||||
sp[tempid].good_effect=atoi(row[83]);
|
||||
sp[tempid].activated=atoi(row[84]);
|
||||
sp[tempid].resist_type=atoi(row[85]);
|
||||
|
||||
for(y=0; y< EFFECT_COUNT;y++)
|
||||
sp[tempid].effectid[y]=atoi(row[86+y]);
|
||||
sp[tempid].effect_id[y]=atoi(row[86+y]);
|
||||
|
||||
sp[tempid].targettype = (SpellTargetType) atoi(row[98]);
|
||||
sp[tempid].basediff=atoi(row[99]);
|
||||
sp[tempid].target_type = (SpellTargetType) atoi(row[98]);
|
||||
sp[tempid].base_difficulty=atoi(row[99]);
|
||||
|
||||
int tmp_skill = atoi(row[100]);;
|
||||
|
||||
@@ -1812,15 +1812,15 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
else
|
||||
sp[tempid].skill = (EQ::skills::SkillType) tmp_skill;
|
||||
|
||||
sp[tempid].zonetype=atoi(row[101]);
|
||||
sp[tempid].EnvironmentType=atoi(row[102]);
|
||||
sp[tempid].TimeOfDay=atoi(row[103]);
|
||||
sp[tempid].zone_type=atoi(row[101]);
|
||||
sp[tempid].environment_type=atoi(row[102]);
|
||||
sp[tempid].time_of_day=atoi(row[103]);
|
||||
|
||||
for(y=0; y < PLAYER_CLASS_COUNT;y++)
|
||||
sp[tempid].classes[y]=atoi(row[104+y]);
|
||||
|
||||
sp[tempid].CastingAnim=atoi(row[120]);
|
||||
sp[tempid].SpellAffectIndex=atoi(row[123]);
|
||||
sp[tempid].casting_animation=atoi(row[120]);
|
||||
sp[tempid].spell_affect_index=atoi(row[123]);
|
||||
sp[tempid].disallow_sit=atoi(row[124]);
|
||||
sp[tempid].deity_agnostic=atoi(row[125]);
|
||||
|
||||
@@ -1829,31 +1829,32 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
|
||||
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].resist_difficulty=atoi(row[147]);
|
||||
sp[tempid].unstackable_dot = atoi(row[148]) != 0;
|
||||
sp[tempid].recourse_link = atoi(row[150]);
|
||||
sp[tempid].no_partial_resist = atoi(row[151]) != 0;
|
||||
|
||||
sp[tempid].short_buff_box = atoi(row[154]);
|
||||
sp[tempid].descnum = atoi(row[155]);
|
||||
sp[tempid].typedescnum = atoi(row[156]);
|
||||
sp[tempid].effectdescnum = atoi(row[157]);
|
||||
sp[tempid].description_id = atoi(row[155]);
|
||||
sp[tempid].type_description_id = atoi(row[156]);
|
||||
sp[tempid].effect_description_id = atoi(row[157]);
|
||||
|
||||
sp[tempid].npc_no_los = atoi(row[159]) != 0;
|
||||
sp[tempid].feedbackable = atoi(row[160]) != 0;
|
||||
sp[tempid].reflectable = atoi(row[161]) != 0;
|
||||
sp[tempid].bonushate=atoi(row[162]);
|
||||
sp[tempid].bonus_hate=atoi(row[162]);
|
||||
|
||||
sp[tempid].ldon_trap = atoi(row[165]) != 0;
|
||||
sp[tempid].EndurCost=atoi(row[166]);
|
||||
sp[tempid].EndurTimerIndex=atoi(row[167]);
|
||||
sp[tempid].IsDisciplineBuff = atoi(row[168]) != 0;
|
||||
sp[tempid].HateAdded=atoi(row[173]);
|
||||
sp[tempid].EndurUpkeep=atoi(row[174]);
|
||||
sp[tempid].numhitstype = atoi(row[175]);
|
||||
sp[tempid].numhits = atoi(row[176]);
|
||||
sp[tempid].pvpresistbase=atoi(row[177]);
|
||||
sp[tempid].pvpresistcalc=atoi(row[178]);
|
||||
sp[tempid].pvpresistcap=atoi(row[179]);
|
||||
sp[tempid].endurance_cost=atoi(row[166]);
|
||||
sp[tempid].timer_id=atoi(row[167]);
|
||||
sp[tempid].is_discipline = atoi(row[168]) != 0;
|
||||
sp[tempid].hate_added=atoi(row[173]);
|
||||
sp[tempid].endurance_upkeep=atoi(row[174]);
|
||||
sp[tempid].hit_number_type = atoi(row[175]);
|
||||
sp[tempid].hit_number = atoi(row[176]);
|
||||
sp[tempid].pvp_resist_base=atoi(row[177]);
|
||||
sp[tempid].pvp_resist_per_level=atoi(row[178]);
|
||||
sp[tempid].pvp_resist_cap=atoi(row[179]);
|
||||
sp[tempid].spell_category=atoi(row[180]);
|
||||
sp[tempid].pvp_duration = atoi(row[181]);
|
||||
sp[tempid].pvp_duration_cap = atoi(row[182]);
|
||||
@@ -1861,11 +1862,11 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
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].min_resist = atoi(row[189]);
|
||||
sp[tempid].max_resist = 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].nimbus_effect = 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;
|
||||
@@ -1873,29 +1874,29 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
||||
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].song_cap = atoi(row[202]);
|
||||
sp[tempid].no_block = atoi(row[205]);
|
||||
sp[tempid].spellgroup=atoi(row[207]);
|
||||
sp[tempid].spell_group=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].cast_restriction = atoi(row[211]);
|
||||
sp[tempid].allow_rest = atoi(row[212]) != 0;
|
||||
sp[tempid].can_cast_in_combat = atoi(row[213]) != 0;
|
||||
sp[tempid].can_cast_out_of_combat = atoi(row[214]) != 0;
|
||||
sp[tempid].override_crit_chance = atoi(row[217]);
|
||||
sp[tempid].aemaxtargets = atoi(row[218]);
|
||||
sp[tempid].aoe_max_targets = atoi(row[218]);
|
||||
sp[tempid].no_heal_damage_item_mod = atoi(row[219]);
|
||||
sp[tempid].caster_requirement_id = atoi(row[220]);
|
||||
sp[tempid].spell_class = atoi(row[221]);
|
||||
sp[tempid].spell_subclass = atoi(row[222]);
|
||||
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].persist_death = atoi(row[224]) != 0;
|
||||
sp[tempid].min_distance = atof(row[227]);
|
||||
sp[tempid].min_distance_mod = atof(row[228]);
|
||||
sp[tempid].max_distance = atof(row[229]);
|
||||
sp[tempid].max_distance_mod = atof(row[230]);
|
||||
sp[tempid].min_range = static_cast<float>(atoi(row[231]));
|
||||
sp[tempid].no_remove = atoi(row[232]) != 0;
|
||||
sp[tempid].DamageShieldType = 0;
|
||||
sp[tempid].damage_shield_type = 0;
|
||||
}
|
||||
|
||||
LoadDamageShieldTypes(sp, max_spells);
|
||||
|
||||
+10
-96
@@ -177,8 +177,7 @@ bool EQ::skills::IsMeleeDmg(SkillType skill)
|
||||
|
||||
const std::map<EQ::skills::SkillType, std::string>& EQ::skills::GetSkillTypeMap()
|
||||
{
|
||||
/* VS2013 code
|
||||
static const std::map<SkillUseTypes, std::string> skill_use_types_map = {
|
||||
static const std::map<SkillType, std::string> skill_type_map = {
|
||||
{ Skill1HBlunt, "1H Blunt" },
|
||||
{ Skill1HSlashing, "1H Slashing" },
|
||||
{ Skill2HBlunt, "2H Blunt" },
|
||||
@@ -258,103 +257,18 @@ const std::map<EQ::skills::SkillType, std::string>& EQ::skills::GetSkillTypeMap(
|
||||
{ SkillTripleAttack, "Triple Attack" },
|
||||
{ Skill2HPiercing, "2H Piercing" }
|
||||
};
|
||||
*/
|
||||
|
||||
/* VS2012 code - begin */
|
||||
|
||||
static const char* skill_use_names[SkillCount] = {
|
||||
"1H Blunt",
|
||||
"1H Slashing",
|
||||
"2H Blunt",
|
||||
"2H Slashing",
|
||||
"Abjuration",
|
||||
"Alteration",
|
||||
"Apply Poison",
|
||||
"Archery",
|
||||
"Backstab",
|
||||
"Bind Wound",
|
||||
"Bash",
|
||||
"Block",
|
||||
"Brass Instruments",
|
||||
"Channeling",
|
||||
"Conjuration",
|
||||
"Defense",
|
||||
"Disarm",
|
||||
"Disarm Traps",
|
||||
"Divination",
|
||||
"Dodge",
|
||||
"Double Attack",
|
||||
"Dragon Punch",
|
||||
"Dual Wield",
|
||||
"Eagle Strike",
|
||||
"Evocation",
|
||||
"Feign Death",
|
||||
"Flying Kick",
|
||||
"Forage",
|
||||
"Hand to Hand",
|
||||
"Hide",
|
||||
"Kick",
|
||||
"Meditate",
|
||||
"Mend",
|
||||
"Offense",
|
||||
"Parry",
|
||||
"Pick Lock",
|
||||
"1H Piercing",
|
||||
"Riposte",
|
||||
"Round Kick",
|
||||
"Safe Fall",
|
||||
"Sense Heading",
|
||||
"Singing",
|
||||
"Sneak",
|
||||
"Specialize Abjuration",
|
||||
"Specialize Alteration",
|
||||
"Specialize Conjuration",
|
||||
"Specialize Divination",
|
||||
"Specialize Evocation",
|
||||
"Pick Pockets",
|
||||
"Stringed Instruments",
|
||||
"Swimming",
|
||||
"Throwing",
|
||||
"Tiger Claw",
|
||||
"Tracking",
|
||||
"Wind Instruments",
|
||||
"Fishing",
|
||||
"Make Poison",
|
||||
"Tinkering",
|
||||
"Research",
|
||||
"Alchemy",
|
||||
"Baking",
|
||||
"Tailoring",
|
||||
"Sense Traps",
|
||||
"Blacksmithing",
|
||||
"Fletching",
|
||||
"Brewing",
|
||||
"Alcohol Tolerance",
|
||||
"Begging",
|
||||
"Jewelry Making",
|
||||
"Pottery",
|
||||
"Percussion Instruments",
|
||||
"Intimidation",
|
||||
"Berserking",
|
||||
"Taunt",
|
||||
"Frenzy",
|
||||
"Remove Traps",
|
||||
"Triple Attack",
|
||||
"2H Piercing"
|
||||
};
|
||||
|
||||
static std::map<SkillType, std::string> skill_type_map;
|
||||
|
||||
skill_type_map.clear();
|
||||
|
||||
for (int i = Skill1HBlunt; i < SkillCount; ++i)
|
||||
skill_type_map[(SkillType)i] = skill_use_names[i];
|
||||
|
||||
/* VS2012 code - end */
|
||||
|
||||
return skill_type_map;
|
||||
}
|
||||
|
||||
std::string EQ::skills::GetSkillName(SkillType skill)
|
||||
{
|
||||
if (skill >= Skill1HBlunt && skill <= Skill2HPiercing) {
|
||||
auto skills = GetSkillTypeMap();
|
||||
return skills[skill];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
EQ::SkillProfile::SkillProfile()
|
||||
{
|
||||
memset(&Skill, 0, (sizeof(uint32) * PACKET_SKILL_ARRAY_SIZE));
|
||||
|
||||
@@ -171,6 +171,7 @@ namespace EQ
|
||||
|
||||
extern const std::map<SkillType, std::string>& GetSkillTypeMap();
|
||||
|
||||
std::string GetSkillName(SkillType skill);
|
||||
} /*skills*/
|
||||
|
||||
struct SkillProfile { // prototype - not implemented
|
||||
|
||||
+395
-165
File diff suppressed because it is too large
Load Diff
+413
-364
File diff suppressed because it is too large
Load Diff
+801
-146
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,11 @@ std::vector<std::string> wrap(std::vector<std::string> &src, std::string charact
|
||||
std::string implode(std::string glue, std::vector<std::string> src);
|
||||
std::string convert2digit(int n, std::string suffix);
|
||||
std::string numberToWords(unsigned long long int n);
|
||||
std::string ConvertMoneyToString(uint32 platinum, uint32 gold = 0, uint32 silver = 0, uint32 copper = 0);
|
||||
std::string ConvertSecondsToTime(int duration, bool is_milliseconds = false);
|
||||
inline std::string ConvertMillisecondsToTime(int duration) {
|
||||
return ConvertSecondsToTime(duration, true);
|
||||
}
|
||||
|
||||
// For converstion of numerics into English
|
||||
// Used for grid nodes, as NPC names remove numerals.
|
||||
@@ -208,6 +213,11 @@ void RemoveApostrophes(std::string &s);
|
||||
std::string convert2digit(int n, std::string suffix);
|
||||
std::string numberToWords(unsigned long long int n);
|
||||
std::string FormatName(const std::string& char_name);
|
||||
bool IsAllowedWorldServerCharacterList(char c);
|
||||
void SanitizeWorldServerName(char *name);
|
||||
std::string SanitizeWorldServerName(std::string server_long_name);
|
||||
std::string repeat(std::string s, int n);
|
||||
std::vector<std::string> GetBadWords();
|
||||
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result)
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9172
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9175
|
||||
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9028
|
||||
|
||||
@@ -22,7 +22,7 @@ SET(eqlogin_headers
|
||||
loginserver_command_handler.h
|
||||
loginserver_webserver.h
|
||||
login_server.h
|
||||
login_structures.h
|
||||
login_types.h
|
||||
options.h
|
||||
server_manager.h
|
||||
world_server.h
|
||||
|
||||
@@ -1,28 +1,9 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "account_management.h"
|
||||
#include "login_server.h"
|
||||
#include "../common/event/task_scheduler.h"
|
||||
#include "../common/event/event_loop.h"
|
||||
#include "../common/net/dns.h"
|
||||
#include "../common/string_util.h"
|
||||
|
||||
extern LoginServer server;
|
||||
EQ::Event::TaskScheduler task_runner;
|
||||
@@ -300,6 +281,8 @@ bool AccountManagement::UpdateLoginserverWorldAdminAccountPasswordById(
|
||||
return updated_account;
|
||||
}
|
||||
|
||||
constexpr int REQUEST_TIMEOUT_MS = 1500;
|
||||
|
||||
/**
|
||||
* @param in_account_username
|
||||
* @param in_account_password
|
||||
@@ -395,19 +378,33 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
||||
}
|
||||
);
|
||||
|
||||
EQ::Net::DNSLookup(
|
||||
"login.eqemulator.net", 5999, false, [&](const std::string &addr) {
|
||||
if (addr.empty()) {
|
||||
ret = 0;
|
||||
running = false;
|
||||
}
|
||||
auto s = SplitString(server.options.GetEQEmuLoginServerAddress(), ':');
|
||||
if (s.size() == 2) {
|
||||
auto address = s[0];
|
||||
auto port = std::stoi(s[1]);
|
||||
|
||||
mgr.Connect(addr, 5999);
|
||||
}
|
||||
);
|
||||
EQ::Net::DNSLookup(
|
||||
address, port, false, [&](const std::string &addr) {
|
||||
if (addr.empty()) {
|
||||
ret = 0;
|
||||
running = false;
|
||||
}
|
||||
|
||||
mgr.Connect(addr, port);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
|
||||
|
||||
auto &loop = EQ::EventLoop::Get();
|
||||
while (running) {
|
||||
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() > REQUEST_TIMEOUT_MS) {
|
||||
LogInfo("[CheckExternalLoginserverUserCredentials] Deadline exceeded [{}]", REQUEST_TIMEOUT_MS);
|
||||
running = false;
|
||||
}
|
||||
|
||||
loop.Process();
|
||||
}
|
||||
|
||||
@@ -416,4 +413,115 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
||||
);
|
||||
|
||||
return res.get();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 AccountManagement::HealthCheckUserLogin()
|
||||
{
|
||||
std::string in_account_username = "healthcheckuser";
|
||||
std::string in_account_password = "healthcheckpassword";
|
||||
|
||||
auto res = task_runner.Enqueue(
|
||||
[&]() -> uint32 {
|
||||
bool running = true;
|
||||
uint32 ret = 0;
|
||||
|
||||
EQ::Net::DaybreakConnectionManager mgr;
|
||||
std::shared_ptr<EQ::Net::DaybreakConnection> c;
|
||||
|
||||
mgr.OnNewConnection(
|
||||
[&](std::shared_ptr<EQ::Net::DaybreakConnection> connection) {
|
||||
c = connection;
|
||||
}
|
||||
);
|
||||
|
||||
mgr.OnConnectionStateChange(
|
||||
[&](
|
||||
std::shared_ptr<EQ::Net::DaybreakConnection> conn,
|
||||
EQ::Net::DbProtocolStatus from,
|
||||
EQ::Net::DbProtocolStatus to
|
||||
) {
|
||||
if (EQ::Net::StatusConnected == to) {
|
||||
EQ::Net::DynamicPacket p;
|
||||
p.PutUInt16(0, 1); //OP_SessionReady
|
||||
p.PutUInt32(2, 2);
|
||||
c->QueuePacket(p);
|
||||
}
|
||||
else if (EQ::Net::StatusDisconnected == to) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
mgr.OnPacketRecv(
|
||||
[&](std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p) {
|
||||
auto opcode = p.GetUInt16(0);
|
||||
switch (opcode) {
|
||||
case 0x0017: //OP_ChatMessage
|
||||
{
|
||||
size_t buffer_len =
|
||||
in_account_username.length() + in_account_password.length() + 2;
|
||||
|
||||
std::unique_ptr<char[]> buffer(new char[buffer_len]);
|
||||
|
||||
strcpy(&buffer[0], in_account_username.c_str());
|
||||
strcpy(&buffer[in_account_username.length() + 1], in_account_password.c_str());
|
||||
|
||||
size_t encrypted_len = buffer_len;
|
||||
|
||||
if (encrypted_len % 8 > 0) {
|
||||
encrypted_len = ((encrypted_len / 8) + 1) * 8;
|
||||
}
|
||||
|
||||
EQ::Net::DynamicPacket p;
|
||||
p.Resize(12 + encrypted_len);
|
||||
p.PutUInt16(0, 2); //OP_Login
|
||||
p.PutUInt32(2, 3);
|
||||
|
||||
eqcrypt_block(&buffer[0], buffer_len, (char *) p.Data() + 12, true);
|
||||
c->QueuePacket(p);
|
||||
break;
|
||||
}
|
||||
case 0x0018: {
|
||||
auto encrypt_size = p.Length() - 12;
|
||||
if (encrypt_size % 8 > 0) {
|
||||
encrypt_size = (encrypt_size / 8) * 8;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> decrypted(new char[encrypt_size]);
|
||||
|
||||
eqcrypt_block((char *) p.Data() + 12, encrypt_size, &decrypted[0], false);
|
||||
|
||||
EQ::Net::StaticPacket sp(&decrypted[0], encrypt_size);
|
||||
auto response_error = sp.GetUInt16(1);
|
||||
|
||||
{
|
||||
// we only care to see the response code
|
||||
ret = response_error;
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
mgr.Connect("127.0.0.1", 5999);
|
||||
|
||||
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
|
||||
auto &loop = EQ::EventLoop::Get();
|
||||
while (running) {
|
||||
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() > 2000) {
|
||||
ret = 0;
|
||||
running = false;
|
||||
}
|
||||
|
||||
loop.Process();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
return res.get();
|
||||
}
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef EQEMU_ACCOUNT_MANAGEMENT_H
|
||||
#define EQEMU_ACCOUNT_MANAGEMENT_H
|
||||
|
||||
@@ -108,6 +89,8 @@ public:
|
||||
uint32 in_account_id,
|
||||
const std::string &in_account_password_hash
|
||||
);
|
||||
|
||||
static uint32 HealthCheckUserLogin();
|
||||
};
|
||||
|
||||
|
||||
|
||||
+150
-199
@@ -1,29 +1,10 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "login_server.h"
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "encryption.h"
|
||||
#include "account_management.h"
|
||||
|
||||
extern LoginServer server;
|
||||
|
||||
@@ -33,17 +14,17 @@ extern LoginServer server;
|
||||
*/
|
||||
Client::Client(std::shared_ptr<EQStreamInterface> c, LSClientVersion v)
|
||||
{
|
||||
connection = c;
|
||||
version = v;
|
||||
status = cs_not_sent_session_ready;
|
||||
account_id = 0;
|
||||
play_server_id = 0;
|
||||
play_sequence_id = 0;
|
||||
m_connection = c;
|
||||
m_client_version = v;
|
||||
m_client_status = cs_not_sent_session_ready;
|
||||
m_account_id = 0;
|
||||
m_play_server_id = 0;
|
||||
m_play_sequence_id = 0;
|
||||
}
|
||||
|
||||
bool Client::Process()
|
||||
{
|
||||
EQApplicationPacket *app = connection->PopPacket();
|
||||
EQApplicationPacket *app = m_connection->PopPacket();
|
||||
while (app) {
|
||||
if (server.options.IsTraceOn()) {
|
||||
LogDebug("Application packet received from client (size {0})", app->Size());
|
||||
@@ -53,9 +34,9 @@ bool Client::Process()
|
||||
DumpPacket(app);
|
||||
}
|
||||
|
||||
if (status == cs_failed_to_login) {
|
||||
if (m_client_status == cs_failed_to_login) {
|
||||
delete app;
|
||||
app = connection->PopPacket();
|
||||
app = m_connection->PopPacket();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -112,7 +93,7 @@ bool Client::Process()
|
||||
}
|
||||
|
||||
delete app;
|
||||
app = connection->PopPacket();
|
||||
app = m_connection->PopPacket();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -126,7 +107,7 @@ bool Client::Process()
|
||||
*/
|
||||
void Client::Handle_SessionReady(const char *data, unsigned int size)
|
||||
{
|
||||
if (status != cs_not_sent_session_ready) {
|
||||
if (m_client_status != cs_not_sent_session_ready) {
|
||||
LogError("Session ready received again after already being received");
|
||||
return;
|
||||
}
|
||||
@@ -136,39 +117,23 @@ void Client::Handle_SessionReady(const char *data, unsigned int size)
|
||||
return;
|
||||
}
|
||||
|
||||
status = cs_waiting_for_login;
|
||||
m_client_status = cs_waiting_for_login;
|
||||
|
||||
/**
|
||||
* The packets are mostly the same but slightly different between the two versions
|
||||
* The packets are identical between the two versions
|
||||
*/
|
||||
if (version == cv_sod) {
|
||||
auto *outapp = new EQApplicationPacket(OP_ChatMessage, 17);
|
||||
outapp->pBuffer[0] = 0x02;
|
||||
outapp->pBuffer[10] = 0x01;
|
||||
outapp->pBuffer[11] = 0x65;
|
||||
auto *outapp = new EQApplicationPacket(OP_ChatMessage, sizeof(LoginHandShakeReply_Struct));
|
||||
auto buf = reinterpret_cast<LoginHandShakeReply_Struct*>(outapp->pBuffer);
|
||||
buf->base_header.sequence = 0x02;
|
||||
buf->base_reply.success = true;
|
||||
buf->base_reply.error_str_id = 0x65; // 101 "No Error"
|
||||
|
||||
if (server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
}
|
||||
|
||||
connection->QueuePacket(outapp);
|
||||
delete outapp;
|
||||
if (server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
}
|
||||
else {
|
||||
const char *msg = "ChatMessage";
|
||||
auto *outapp = new EQApplicationPacket(OP_ChatMessage, 16 + strlen(msg));
|
||||
outapp->pBuffer[0] = 0x02;
|
||||
outapp->pBuffer[10] = 0x01;
|
||||
outapp->pBuffer[11] = 0x65;
|
||||
strcpy((char *) (outapp->pBuffer + 15), msg);
|
||||
|
||||
if (server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
}
|
||||
|
||||
connection->QueuePacket(outapp);
|
||||
delete outapp;
|
||||
}
|
||||
m_connection->QueuePacket(outapp);
|
||||
delete outapp;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,19 +144,23 @@ void Client::Handle_SessionReady(const char *data, unsigned int size)
|
||||
*/
|
||||
void Client::Handle_Login(const char *data, unsigned int size)
|
||||
{
|
||||
if (status != cs_waiting_for_login) {
|
||||
if (m_client_status != cs_waiting_for_login) {
|
||||
LogError("Login received after already having logged in");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size - 12) % 8 != 0) {
|
||||
LogError("Login received packet of size: {0}, this would cause a block corruption, discarding", size);
|
||||
// login user/pass are variable length after unencrypted opcode and base message header (size includes opcode)
|
||||
constexpr int header_size = sizeof(uint16_t) + sizeof(LoginBaseMessage_Struct);
|
||||
int data_size = size - header_size;
|
||||
|
||||
if (size <= header_size) {
|
||||
LogError("Login received packet of size: {0}, this would cause a buffer overflow, discarding", size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (size < sizeof(LoginLoginRequest_Struct)) {
|
||||
LogError("Login received packet of size: {0}, this would cause a buffer overflow, discarding", size);
|
||||
if (data_size % 8 != 0) {
|
||||
LogError("Login received packet of size: {0}, this would cause a block corruption, discarding", size);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -208,13 +177,14 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
||||
std::string db_account_password_hash;
|
||||
|
||||
std::string outbuffer;
|
||||
outbuffer.resize(size - 12);
|
||||
outbuffer.resize(data_size);
|
||||
if (outbuffer.length() == 0) {
|
||||
LogError("Corrupt buffer sent to server, no length");
|
||||
return;
|
||||
}
|
||||
|
||||
auto r = eqcrypt_block(data + 10, size - 12, &outbuffer[0], 0);
|
||||
// data starts at base message header (opcode not included)
|
||||
auto r = eqcrypt_block(data + sizeof(LoginBaseMessage_Struct), data_size, &outbuffer[0], 0);
|
||||
if (r == nullptr) {
|
||||
LogError("Failed to decrypt eqcrypt block");
|
||||
return;
|
||||
@@ -228,7 +198,8 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&llrs, data, sizeof(LoginLoginRequest_Struct));
|
||||
// only need to copy the base header for reply options, ignore login info
|
||||
memcpy(&m_llrs, data, sizeof(LoginBaseMessage_Struct));
|
||||
|
||||
bool result = false;
|
||||
if (outbuffer[0] == 0 && outbuffer[1] == 0) {
|
||||
@@ -236,7 +207,7 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
||||
cred = (&outbuffer[2 + user.length()]);
|
||||
result = server.db->GetLoginTokenDataFromToken(
|
||||
cred,
|
||||
connection->GetRemoteAddr(),
|
||||
m_connection->GetRemoteAddr(),
|
||||
db_account_id,
|
||||
db_loginserver,
|
||||
user
|
||||
@@ -252,11 +223,16 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
||||
user = components[1];
|
||||
}
|
||||
|
||||
// health checks
|
||||
if (ProcessHealthCheck(user)) {
|
||||
DoFailedLogin();
|
||||
return;
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
"Attempting password based login [{0}] login [{1}] user [{2}]",
|
||||
"Attempting password based login [{0}] login [{1}]",
|
||||
user,
|
||||
db_loginserver,
|
||||
user
|
||||
db_loginserver
|
||||
);
|
||||
|
||||
ParseAccountString(user, user, db_loginserver);
|
||||
@@ -267,7 +243,7 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
||||
LogDebug("[VerifyLoginHash] Success [{0}]", (result ? "true" : "false"));
|
||||
}
|
||||
else {
|
||||
status = cs_creating_account;
|
||||
m_client_status = cs_creating_account;
|
||||
AttemptLoginAccountCreation(user, cred, db_loginserver);
|
||||
|
||||
return;
|
||||
@@ -305,14 +281,14 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
||||
*/
|
||||
void Client::Handle_Play(const char *data)
|
||||
{
|
||||
if (status != cs_logged_in) {
|
||||
if (m_client_status != cs_logged_in) {
|
||||
LogError("Client sent a play request when they were not logged in, discarding");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto *play = (const PlayEverquestRequest_Struct *) data;
|
||||
auto server_id_in = (unsigned int) play->ServerNumber;
|
||||
auto sequence_in = (unsigned int) play->Sequence;
|
||||
auto server_id_in = (unsigned int) play->server_number;
|
||||
auto sequence_in = (unsigned int) play->base_header.sequence;
|
||||
|
||||
if (server.options.IsTraceOn()) {
|
||||
LogInfo(
|
||||
@@ -323,10 +299,10 @@ void Client::Handle_Play(const char *data)
|
||||
);
|
||||
}
|
||||
|
||||
this->play_server_id = (unsigned int) play->ServerNumber;
|
||||
play_sequence_id = sequence_in;
|
||||
play_server_id = server_id_in;
|
||||
server.server_manager->SendUserToWorldRequest(server_id_in, account_id, loginserver_name);
|
||||
m_play_server_id = (unsigned int) play->server_number;
|
||||
m_play_sequence_id = sequence_in;
|
||||
m_play_server_id = server_id_in;
|
||||
server.server_manager->SendUserToWorldRequest(server_id_in, m_account_id, m_loginserver_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,14 +310,13 @@ void Client::Handle_Play(const char *data)
|
||||
*/
|
||||
void Client::SendServerListPacket(uint32 seq)
|
||||
{
|
||||
EQApplicationPacket *outapp = server.server_manager->CreateServerListPacket(this, seq);
|
||||
auto outapp = server.server_manager->CreateServerListPacket(this, seq);
|
||||
|
||||
if (server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
DumpPacket(outapp.get());
|
||||
}
|
||||
|
||||
connection->QueuePacket(outapp);
|
||||
delete outapp;
|
||||
m_connection->QueuePacket(outapp.get());
|
||||
}
|
||||
|
||||
void Client::SendPlayResponse(EQApplicationPacket *outapp)
|
||||
@@ -350,12 +325,12 @@ void Client::SendPlayResponse(EQApplicationPacket *outapp)
|
||||
LogDebug("Sending play response for {0}", GetAccountName());
|
||||
// server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
|
||||
}
|
||||
connection->QueuePacket(outapp);
|
||||
m_connection->QueuePacket(outapp);
|
||||
}
|
||||
|
||||
void Client::GenerateKey()
|
||||
{
|
||||
key.clear();
|
||||
m_key.clear();
|
||||
int count = 0;
|
||||
while (count < 10) {
|
||||
static const char key_selection[] =
|
||||
@@ -367,7 +342,7 @@ void Client::GenerateKey()
|
||||
'6', '7', '8', '9'
|
||||
};
|
||||
|
||||
key.append((const char *) &key_selection[random.Int(0, 35)], 1);
|
||||
m_key.append((const char *) &key_selection[m_random.Int(0, 35)], 1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -383,6 +358,8 @@ void Client::AttemptLoginAccountCreation(
|
||||
const std::string &loginserver
|
||||
)
|
||||
{
|
||||
LogInfo("[AttemptLoginAccountCreation] user [{}] loginserver [{}]", user, loginserver);
|
||||
|
||||
#ifdef LSPX
|
||||
if (loginserver == "eqemu") {
|
||||
LogInfo("Attempting login account creation via '{0}'", loginserver);
|
||||
@@ -393,59 +370,19 @@ void Client::AttemptLoginAccountCreation(
|
||||
return;
|
||||
}
|
||||
|
||||
if (server.options.GetEQEmuLoginServerAddress().length() == 0) {
|
||||
DoFailedLogin();
|
||||
return;
|
||||
}
|
||||
|
||||
auto addr_components = SplitString(server.options.GetEQEmuLoginServerAddress(), ':');
|
||||
if (addr_components.size() != 2) {
|
||||
DoFailedLogin();
|
||||
return;
|
||||
}
|
||||
|
||||
stored_user = user;
|
||||
stored_pass = pass;
|
||||
|
||||
auto address = addr_components[0];
|
||||
auto port = std::stoi(addr_components[1]);
|
||||
EQ::Net::DNSLookup(
|
||||
address, port, false, [=](const std::string &addr) {
|
||||
if (addr.empty()) {
|
||||
DoFailedLogin();
|
||||
return;
|
||||
}
|
||||
|
||||
login_connection_manager.reset(new EQ::Net::DaybreakConnectionManager());
|
||||
login_connection_manager->OnNewConnection(
|
||||
std::bind(
|
||||
&Client::LoginOnNewConnection,
|
||||
this,
|
||||
std::placeholders::_1
|
||||
)
|
||||
);
|
||||
login_connection_manager->OnConnectionStateChange(
|
||||
std::bind(
|
||||
&Client::LoginOnStatusChange,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3
|
||||
)
|
||||
);
|
||||
login_connection_manager->OnPacketRecv(
|
||||
std::bind(
|
||||
&Client::LoginOnPacketRecv,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2
|
||||
)
|
||||
);
|
||||
|
||||
login_connection_manager->Connect(addr, port);
|
||||
}
|
||||
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(
|
||||
user,
|
||||
pass
|
||||
);
|
||||
|
||||
if (account_id > 0) {
|
||||
LogInfo("[AttemptLoginAccountCreation] Found and creating eqemu account [{}]", account_id);
|
||||
CreateEQEmuAccount(user, pass, account_id);
|
||||
return;
|
||||
}
|
||||
|
||||
DoFailedLogin();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -461,26 +398,36 @@ void Client::AttemptLoginAccountCreation(
|
||||
|
||||
void Client::DoFailedLogin()
|
||||
{
|
||||
stored_user.clear();
|
||||
stored_pass.clear();
|
||||
m_stored_user.clear();
|
||||
m_stored_pass.clear();
|
||||
|
||||
EQApplicationPacket outapp(OP_LoginAccepted, sizeof(LoginLoginFailed_Struct));
|
||||
auto *login_failed = (LoginLoginFailed_Struct *) outapp.pBuffer;
|
||||
// unencrypted
|
||||
LoginBaseMessage_Struct base_header{};
|
||||
base_header.sequence = m_llrs.sequence; // login (3)
|
||||
base_header.encrypt_type = m_llrs.encrypt_type;
|
||||
|
||||
login_failed->unknown1 = llrs.unknown1;
|
||||
login_failed->unknown2 = llrs.unknown2;
|
||||
login_failed->unknown3 = llrs.unknown3;
|
||||
login_failed->unknown4 = llrs.unknown4;
|
||||
login_failed->unknown5 = llrs.unknown5;
|
||||
// encrypted
|
||||
PlayerLoginReply_Struct login_reply{};
|
||||
login_reply.base_reply.success = false;
|
||||
login_reply.base_reply.error_str_id = 105; // Error - The username and/or password were not valid
|
||||
|
||||
memcpy(login_failed->unknown6, FailedLoginResponseData, sizeof(FailedLoginResponseData));
|
||||
char encrypted_buffer[80] = {0};
|
||||
auto rc = eqcrypt_block((const char*)&login_reply, sizeof(login_reply), encrypted_buffer, 1);
|
||||
if (rc == nullptr) {
|
||||
LogDebug("Failed to encrypt eqcrypt block for failed login");
|
||||
}
|
||||
|
||||
constexpr int outsize = sizeof(LoginBaseMessage_Struct) + sizeof(encrypted_buffer);
|
||||
EQApplicationPacket outapp(OP_LoginAccepted, outsize);
|
||||
outapp.WriteData(&base_header, sizeof(base_header));
|
||||
outapp.WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
|
||||
|
||||
if (server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(&outapp);
|
||||
}
|
||||
|
||||
connection->QueuePacket(&outapp);
|
||||
status = cs_failed_to_login;
|
||||
m_connection->QueuePacket(&outapp);
|
||||
m_client_status = cs_failed_to_login;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,68 +523,64 @@ void Client::DoSuccessfulLogin(
|
||||
const std::string &db_loginserver
|
||||
)
|
||||
{
|
||||
stored_user.clear();
|
||||
stored_pass.clear();
|
||||
m_stored_user.clear();
|
||||
m_stored_pass.clear();
|
||||
|
||||
server.client_manager->RemoveExistingClient(db_account_id, db_loginserver);
|
||||
|
||||
in_addr in{};
|
||||
in.s_addr = connection->GetRemoteIP();
|
||||
in.s_addr = m_connection->GetRemoteIP();
|
||||
|
||||
server.db->UpdateLSAccountData(db_account_id, std::string(inet_ntoa(in)));
|
||||
GenerateKey();
|
||||
|
||||
account_id = db_account_id;
|
||||
account_name = in_account_name;
|
||||
loginserver_name = db_loginserver;
|
||||
m_account_id = db_account_id;
|
||||
m_account_name = in_account_name;
|
||||
m_loginserver_name = db_loginserver;
|
||||
|
||||
auto *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80);
|
||||
auto *login_accepted = (LoginAccepted_Struct *) outapp->pBuffer;
|
||||
login_accepted->unknown1 = llrs.unknown1;
|
||||
login_accepted->unknown2 = llrs.unknown2;
|
||||
login_accepted->unknown3 = llrs.unknown3;
|
||||
login_accepted->unknown4 = llrs.unknown4;
|
||||
login_accepted->unknown5 = llrs.unknown5;
|
||||
// unencrypted
|
||||
LoginBaseMessage_Struct base_header{};
|
||||
base_header.sequence = m_llrs.sequence;
|
||||
base_header.compressed = false;
|
||||
base_header.encrypt_type = m_llrs.encrypt_type;
|
||||
base_header.unk3 = m_llrs.unk3;
|
||||
|
||||
auto *login_failed_attempts = new LoginFailedAttempts_Struct;
|
||||
memset(login_failed_attempts, 0, sizeof(LoginFailedAttempts_Struct));
|
||||
|
||||
login_failed_attempts->failed_attempts = 0;
|
||||
login_failed_attempts->message = 0x01;
|
||||
login_failed_attempts->lsid = db_account_id;
|
||||
login_failed_attempts->unknown3[3] = 0x03;
|
||||
login_failed_attempts->unknown4[3] = 0x02;
|
||||
login_failed_attempts->unknown5[0] = 0xe7;
|
||||
login_failed_attempts->unknown5[1] = 0x03;
|
||||
login_failed_attempts->unknown6[0] = 0xff;
|
||||
login_failed_attempts->unknown6[1] = 0xff;
|
||||
login_failed_attempts->unknown6[2] = 0xff;
|
||||
login_failed_attempts->unknown6[3] = 0xff;
|
||||
login_failed_attempts->unknown7[0] = 0xa0;
|
||||
login_failed_attempts->unknown7[1] = 0x05;
|
||||
login_failed_attempts->unknown8[3] = 0x02;
|
||||
login_failed_attempts->unknown9[0] = 0xff;
|
||||
login_failed_attempts->unknown9[1] = 0x03;
|
||||
login_failed_attempts->unknown11[0] = 0x63;
|
||||
login_failed_attempts->unknown12[0] = 0x01;
|
||||
memcpy(login_failed_attempts->key, key.c_str(), key.size());
|
||||
// not serializing any of the variable length strings so just use struct directly
|
||||
PlayerLoginReply_Struct login_reply{};
|
||||
login_reply.base_reply.success = true;
|
||||
login_reply.base_reply.error_str_id = 101; // No Error
|
||||
login_reply.unk1 = 0;
|
||||
login_reply.unk2 = 0;
|
||||
login_reply.lsid = db_account_id;
|
||||
login_reply.failed_attempts = 0;
|
||||
login_reply.show_player_count = server.options.IsShowPlayerCountEnabled();
|
||||
login_reply.offer_min_days = 99;
|
||||
login_reply.offer_min_views = -1;
|
||||
login_reply.offer_cooldown_minutes = 0;
|
||||
login_reply.web_offer_number = 0;
|
||||
login_reply.web_offer_min_days = 99;
|
||||
login_reply.web_offer_min_views = -1;
|
||||
login_reply.web_offer_cooldown_minutes = 0;
|
||||
memcpy(login_reply.key, m_key.c_str(), m_key.size());
|
||||
|
||||
char encrypted_buffer[80] = {0};
|
||||
auto rc = eqcrypt_block((const char *) login_failed_attempts, 75, encrypted_buffer, 1);
|
||||
auto rc = eqcrypt_block((const char*)&login_reply, sizeof(login_reply), encrypted_buffer, 1);
|
||||
if (rc == nullptr) {
|
||||
LogDebug("Failed to encrypt eqcrypt block");
|
||||
}
|
||||
|
||||
memcpy(login_accepted->encrypt, encrypted_buffer, 80);
|
||||
constexpr int outsize = sizeof(LoginBaseMessage_Struct) + sizeof(encrypted_buffer);
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_LoginAccepted, outsize);
|
||||
outapp->WriteData(&base_header, sizeof(base_header));
|
||||
outapp->WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
|
||||
|
||||
if (server.options.IsDumpOutPacketsOn()) {
|
||||
DumpPacket(outapp);
|
||||
DumpPacket(outapp.get());
|
||||
}
|
||||
|
||||
connection->QueuePacket(outapp);
|
||||
delete outapp;
|
||||
m_connection->QueuePacket(outapp.get());
|
||||
|
||||
status = cs_logged_in;
|
||||
m_client_status = cs_logged_in;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -689,7 +632,7 @@ void Client::CreateEQEmuAccount(
|
||||
*/
|
||||
void Client::LoginOnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection)
|
||||
{
|
||||
login_connection = connection;
|
||||
m_login_connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -751,16 +694,16 @@ void Client::LoginSendSessionReady()
|
||||
p.PutUInt16(0, 1); //OP_SessionReady
|
||||
p.PutUInt32(2, 2);
|
||||
|
||||
login_connection->QueuePacket(p);
|
||||
m_login_connection->QueuePacket(p);
|
||||
}
|
||||
|
||||
void Client::LoginSendLogin()
|
||||
{
|
||||
size_t buffer_len = stored_user.length() + stored_pass.length() + 2;
|
||||
size_t buffer_len = m_stored_user.length() + m_stored_pass.length() + 2;
|
||||
std::unique_ptr<char[]> buffer(new char[buffer_len]);
|
||||
|
||||
strcpy(&buffer[0], stored_user.c_str());
|
||||
strcpy(&buffer[stored_user.length() + 1], stored_pass.c_str());
|
||||
strcpy(&buffer[0], m_stored_user.c_str());
|
||||
strcpy(&buffer[m_stored_user.length() + 1], m_stored_pass.c_str());
|
||||
|
||||
size_t encrypted_len = buffer_len;
|
||||
|
||||
@@ -775,7 +718,7 @@ void Client::LoginSendLogin()
|
||||
|
||||
eqcrypt_block(&buffer[0], buffer_len, (char *) p.Data() + 12, true);
|
||||
|
||||
login_connection->QueuePacket(p);
|
||||
m_login_connection->QueuePacket(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -796,7 +739,7 @@ void Client::LoginProcessLoginResponse(const EQ::Net::Packet &p)
|
||||
EQ::Net::StaticPacket sp(&decrypted[0], encrypt_size);
|
||||
auto response_error = sp.GetUInt16(1);
|
||||
|
||||
login_connection_manager->OnConnectionStateChange(
|
||||
m_login_connection_manager->OnConnectionStateChange(
|
||||
std::bind(
|
||||
&Client::LoginOnStatusChangeIgnored,
|
||||
this,
|
||||
@@ -809,18 +752,26 @@ void Client::LoginProcessLoginResponse(const EQ::Net::Packet &p)
|
||||
if (response_error > 101) {
|
||||
LogDebug("response [{0}] failed login", response_error);
|
||||
DoFailedLogin();
|
||||
login_connection->Close();
|
||||
m_login_connection->Close();
|
||||
}
|
||||
else {
|
||||
LogDebug(
|
||||
"response [{0}] login succeeded user [{1}]",
|
||||
response_error,
|
||||
stored_user
|
||||
m_stored_user
|
||||
);
|
||||
|
||||
auto m_dbid = sp.GetUInt32(8);
|
||||
|
||||
CreateEQEmuAccount(stored_user, stored_pass, m_dbid);
|
||||
login_connection->Close();
|
||||
CreateEQEmuAccount(m_stored_user, m_stored_pass, m_dbid);
|
||||
m_login_connection->Close();
|
||||
}
|
||||
}
|
||||
bool Client::ProcessHealthCheck(std::string username)
|
||||
{
|
||||
if (username == "healthcheckuser") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+24
-56
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_CLIENT_H
|
||||
#define EQEMU_CLIENT_H
|
||||
|
||||
@@ -27,22 +7,9 @@
|
||||
#include "../common/eq_stream_intf.h"
|
||||
#include "../common/net/dns.h"
|
||||
#include "../common/net/daybreak_connection.h"
|
||||
#include "login_structures.h"
|
||||
#include "login_types.h"
|
||||
#include <memory>
|
||||
|
||||
enum LSClientVersion {
|
||||
cv_titanium,
|
||||
cv_sod
|
||||
};
|
||||
|
||||
enum LSClientStatus {
|
||||
cs_not_sent_session_ready,
|
||||
cs_waiting_for_login,
|
||||
cs_creating_account,
|
||||
cs_failed_to_login,
|
||||
cs_logged_in
|
||||
};
|
||||
|
||||
/**
|
||||
* Client class, controls a single client and it's connection to the login server
|
||||
*/
|
||||
@@ -116,49 +83,49 @@ public:
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
unsigned int GetAccountID() const { return account_id; }
|
||||
unsigned int GetAccountID() const { return m_account_id; }
|
||||
|
||||
/**
|
||||
* Gets the loginserver name of this client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::string GetLoginServerName() const { return loginserver_name; }
|
||||
std::string GetLoginServerName() const { return m_loginserver_name; }
|
||||
|
||||
/**
|
||||
* Gets the account name of this client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::string GetAccountName() const { return account_name; }
|
||||
std::string GetAccountName() const { return m_account_name; }
|
||||
|
||||
/**
|
||||
* Gets the key generated at login for this client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::string GetKey() const { return key; }
|
||||
std::string GetKey() const { return m_key; }
|
||||
|
||||
/**
|
||||
* Gets the server selected to be played on for this client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
unsigned int GetPlayServerID() const { return play_server_id; }
|
||||
unsigned int GetPlayServerID() const { return m_play_server_id; }
|
||||
|
||||
/**
|
||||
* Gets the play sequence state for this client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
unsigned int GetPlaySequence() const { return play_sequence_id; }
|
||||
unsigned int GetPlaySequence() const { return m_play_sequence_id; }
|
||||
|
||||
/**
|
||||
* Gets the connection for this client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<EQStreamInterface> GetConnection() { return connection; }
|
||||
std::shared_ptr<EQStreamInterface> GetConnection() { return m_connection; }
|
||||
|
||||
/**
|
||||
* Attempts to create a login account
|
||||
@@ -195,24 +162,24 @@ public:
|
||||
void CreateEQEmuAccount(const std::string &in_account_name, const std::string &in_account_password, unsigned int loginserver_account_id);
|
||||
|
||||
private:
|
||||
EQ::Random random;
|
||||
std::shared_ptr<EQStreamInterface> connection;
|
||||
LSClientVersion version;
|
||||
LSClientStatus status;
|
||||
EQ::Random m_random;
|
||||
std::shared_ptr<EQStreamInterface> m_connection;
|
||||
LSClientVersion m_client_version;
|
||||
LSClientStatus m_client_status;
|
||||
|
||||
std::string account_name;
|
||||
unsigned int account_id;
|
||||
std::string loginserver_name;
|
||||
unsigned int play_server_id;
|
||||
unsigned int play_sequence_id;
|
||||
std::string key;
|
||||
std::string m_account_name;
|
||||
unsigned int m_account_id;
|
||||
std::string m_loginserver_name;
|
||||
unsigned int m_play_server_id;
|
||||
unsigned int m_play_sequence_id;
|
||||
std::string m_key;
|
||||
|
||||
std::unique_ptr<EQ::Net::DaybreakConnectionManager> login_connection_manager;
|
||||
std::shared_ptr<EQ::Net::DaybreakConnection> login_connection;
|
||||
LoginLoginRequest_Struct llrs;
|
||||
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_login_connection_manager;
|
||||
std::shared_ptr<EQ::Net::DaybreakConnection> m_login_connection;
|
||||
LoginBaseMessage_Struct m_llrs;
|
||||
|
||||
std::string stored_user;
|
||||
std::string stored_pass;
|
||||
std::string m_stored_user;
|
||||
std::string m_stored_pass;
|
||||
void LoginOnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection);
|
||||
void LoginOnStatusChange(
|
||||
std::shared_ptr<EQ::Net::DaybreakConnection> conn,
|
||||
@@ -228,6 +195,7 @@ private:
|
||||
void LoginSendSessionReady();
|
||||
void LoginSendLogin();
|
||||
void LoginProcessLoginResponse(const EQ::Net::Packet &p);
|
||||
static bool ProcessHealthCheck(std::string username);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "client_manager.h"
|
||||
#include "login_server.h"
|
||||
|
||||
@@ -25,6 +5,7 @@ extern LoginServer server;
|
||||
extern bool run_server;
|
||||
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/misc.h"
|
||||
|
||||
ClientManager::ClientManager()
|
||||
{
|
||||
@@ -52,8 +33,8 @@ ClientManager::ClientManager()
|
||||
titanium_stream->OnNewConnection(
|
||||
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
||||
LogInfo(
|
||||
"New Titanium client connection from {0}:{1}",
|
||||
stream->GetRemoteIP(),
|
||||
"New Titanium client connection from [{0}:{1}]",
|
||||
long2ip(stream->GetRemoteIP()),
|
||||
stream->GetRemotePort()
|
||||
);
|
||||
|
||||
@@ -87,13 +68,13 @@ ClientManager::ClientManager()
|
||||
sod_stream->OnNewConnection(
|
||||
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
||||
LogInfo(
|
||||
"New SoD client connection from {0}:{1}",
|
||||
stream->GetRemoteIP(),
|
||||
"New SoD+ client connection from [{0}:{1}]",
|
||||
long2ip(stream->GetRemoteIP()),
|
||||
stream->GetRemotePort()
|
||||
);
|
||||
|
||||
stream->SetOpcodeManager(&sod_ops);
|
||||
Client *c = new Client(stream, cv_sod);
|
||||
auto *c = new Client(stream, cv_sod);
|
||||
clients.push_back(c);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_CLIENTMANAGER_H
|
||||
#define EQEMU_CLIENTMANAGER_H
|
||||
|
||||
|
||||
+44
-66
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../common/global_define.h"
|
||||
|
||||
#include "database.h"
|
||||
@@ -45,11 +25,6 @@ Database::Database(
|
||||
std::string name
|
||||
)
|
||||
{
|
||||
this->user = user;
|
||||
this->pass = pass;
|
||||
this->host = host;
|
||||
this->name = name;
|
||||
|
||||
uint32 errnum = 0;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
if (!Open(
|
||||
@@ -75,8 +50,8 @@ Database::Database(
|
||||
*/
|
||||
Database::~Database()
|
||||
{
|
||||
if (database) {
|
||||
mysql_close(database);
|
||||
if (m_database) {
|
||||
mysql_close(m_database);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,11 +330,13 @@ void Database::UpdateLoginserverAccountPasswordHash(
|
||||
|
||||
/**
|
||||
* @param short_name
|
||||
* @param long_name
|
||||
* @param login_world_server_admin_id
|
||||
* @return
|
||||
*/
|
||||
Database::DbWorldRegistration Database::GetWorldRegistration(
|
||||
const std::string &short_name,
|
||||
const std::string &long_name,
|
||||
uint32 login_world_server_admin_id
|
||||
)
|
||||
{
|
||||
@@ -375,45 +352,46 @@ Database::DbWorldRegistration Database::GetWorldRegistration(
|
||||
" login_world_servers AS WSR\n"
|
||||
" JOIN login_server_list_types AS SLT ON WSR.login_server_list_type_id = SLT.id\n"
|
||||
"WHERE\n"
|
||||
" WSR.short_name = '{0}' AND WSR.login_server_admin_id = {1} LIMIT 1",
|
||||
" WSR.short_name = '{}' AND WSR.long_name = '{}' AND WSR.login_server_admin_id = {} LIMIT 1",
|
||||
EscapeString(short_name),
|
||||
EscapeString(long_name),
|
||||
login_world_server_admin_id
|
||||
);
|
||||
|
||||
Database::DbWorldRegistration world_registration{};
|
||||
Database::DbWorldRegistration r{};
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success() || results.RowCount() != 1) {
|
||||
return world_registration;
|
||||
return r;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
world_registration.loaded = true;
|
||||
world_registration.server_id = std::stoi(row[0]);
|
||||
world_registration.server_description = row[1];
|
||||
world_registration.server_list_type = std::stoi(row[3]);
|
||||
world_registration.is_server_trusted = std::stoi(row[2]) > 0;
|
||||
world_registration.server_list_description = row[4];
|
||||
world_registration.server_admin_id = std::stoi(row[5]);
|
||||
r.loaded = true;
|
||||
r.server_id = std::stoi(row[0]);
|
||||
r.server_description = row[1];
|
||||
r.server_list_type = std::stoi(row[3]);
|
||||
r.is_server_trusted = std::stoi(row[2]) > 0;
|
||||
r.server_list_description = row[4];
|
||||
r.server_admin_id = std::stoi(row[5]);
|
||||
|
||||
if (world_registration.server_admin_id <= 0) {
|
||||
return world_registration;
|
||||
if (r.server_admin_id <= 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
auto world_registration_query = fmt::format(
|
||||
"SELECT account_name, account_password FROM login_server_admins WHERE id = {0} LIMIT 1",
|
||||
world_registration.server_admin_id
|
||||
r.server_admin_id
|
||||
);
|
||||
|
||||
auto world_registration_results = QueryDatabase(world_registration_query);
|
||||
if (world_registration_results.Success() && world_registration_results.RowCount() == 1) {
|
||||
auto world_registration_row = world_registration_results.begin();
|
||||
world_registration.server_admin_account_name = world_registration_row[0];
|
||||
world_registration.server_admin_account_password = world_registration_row[1];
|
||||
r.server_admin_account_name = world_registration_row[0];
|
||||
r.server_admin_account_password = world_registration_row[1];
|
||||
}
|
||||
|
||||
return world_registration;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,21 +643,21 @@ Database::DbLoginServerAdmin Database::GetLoginServerAdmin(const std::string &ac
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
Database::DbLoginServerAdmin login_server_admin{};
|
||||
Database::DbLoginServerAdmin r{};
|
||||
if (results.RowCount() == 1) {
|
||||
auto row = results.begin();
|
||||
login_server_admin.loaded = true;
|
||||
login_server_admin.id = std::stoi(row[0]);
|
||||
login_server_admin.account_name = row[1];
|
||||
login_server_admin.account_password = row[2];
|
||||
login_server_admin.first_name = row[3];
|
||||
login_server_admin.last_name = row[4];
|
||||
login_server_admin.email = row[5];
|
||||
login_server_admin.registration_date = row[7];
|
||||
login_server_admin.registration_ip_address = row[8];
|
||||
r.loaded = true;
|
||||
r.id = std::stoi(row[0]);
|
||||
r.account_name = row[1];
|
||||
r.account_password = row[2];
|
||||
r.first_name = row[3];
|
||||
r.last_name = row[4];
|
||||
r.email = row[5];
|
||||
r.registration_date = row[7];
|
||||
r.registration_ip_address = row[8];
|
||||
}
|
||||
|
||||
return login_server_admin;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -701,20 +679,20 @@ Database::DbLoginServerAccount Database::GetLoginServerAccountByAccountName(
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
Database::DbLoginServerAccount login_server_account{};
|
||||
Database::DbLoginServerAccount r{};
|
||||
if (results.RowCount() == 1) {
|
||||
auto row = results.begin();
|
||||
login_server_account.loaded = true;
|
||||
login_server_account.id = std::stoi(row[0]);
|
||||
login_server_account.account_name = row[1];
|
||||
login_server_account.account_password = row[2];
|
||||
login_server_account.account_email = row[3];
|
||||
login_server_account.source_loginserver = row[4];
|
||||
login_server_account.last_ip_address = row[5];
|
||||
login_server_account.last_login_date = row[6];
|
||||
login_server_account.created_at = row[7];
|
||||
login_server_account.updated_at = row[8];
|
||||
r.loaded = true;
|
||||
r.id = std::stoi(row[0]);
|
||||
r.account_name = row[1];
|
||||
r.account_password = row[2];
|
||||
r.account_email = row[3];
|
||||
r.source_loginserver = row[4];
|
||||
r.last_ip_address = row[5];
|
||||
r.last_login_date = row[6];
|
||||
r.created_at = row[7];
|
||||
r.updated_at = row[8];
|
||||
}
|
||||
|
||||
return login_server_account;
|
||||
return r;
|
||||
}
|
||||
|
||||
+5
-24
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_DATABASEMYSQL_H
|
||||
#define EQEMU_DATABASEMYSQL_H
|
||||
|
||||
@@ -32,7 +12,7 @@
|
||||
class Database : public DBcore {
|
||||
public:
|
||||
|
||||
Database() { database = nullptr; }
|
||||
Database() { m_database = nullptr; }
|
||||
|
||||
/**
|
||||
* Constructor, tries to set our database to connect to the supplied options.
|
||||
@@ -49,7 +29,7 @@ public:
|
||||
* Destructor, frees our database if needed.
|
||||
*/
|
||||
~Database();
|
||||
bool IsConnected() { return (database != nullptr); }
|
||||
bool IsConnected() { return (m_database != nullptr); }
|
||||
|
||||
/**
|
||||
* Retrieves the login data (password hash and account id) from the account name provided needed for client login procedure.
|
||||
@@ -158,11 +138,13 @@ public:
|
||||
* Returns true if the record was found, false otherwise
|
||||
*
|
||||
* @param short_name
|
||||
* @param long_name
|
||||
* @param login_world_server_admin_id
|
||||
* @return
|
||||
*/
|
||||
Database::DbWorldRegistration GetWorldRegistration(
|
||||
const std::string &short_name,
|
||||
const std::string &long_name,
|
||||
uint32 login_world_server_admin_id
|
||||
);
|
||||
|
||||
@@ -298,8 +280,7 @@ public:
|
||||
);
|
||||
|
||||
protected:
|
||||
std::string user, pass, host, port, name;
|
||||
MYSQL *database{};
|
||||
MYSQL *m_database{};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EQEMUCAPI__H
|
||||
#define EQEMUCAPI__H
|
||||
|
||||
|
||||
@@ -1,29 +1,7 @@
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EQEMU_LOGINSERVER_H
|
||||
#define EQEMU_LOGINSERVER_H
|
||||
|
||||
#include <utility>
|
||||
#include "../common/json_config.h"
|
||||
#include "database.h"
|
||||
#include "encryption.h"
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_LOGINSTRUCTURES_H
|
||||
#define EQEMU_LOGINSTRUCTURES_H
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct LoginChatMessage_Struct {
|
||||
short Unknown0;
|
||||
uint32 Unknown1;
|
||||
uint32 Unknown2;
|
||||
uint32 Unknown3;
|
||||
uint8 Unknown4;
|
||||
char ChatMessage[1];
|
||||
};
|
||||
|
||||
struct LoginLoginRequest_Struct {
|
||||
short unknown1;
|
||||
short unknown2;
|
||||
short unknown3;
|
||||
short unknown4;
|
||||
short unknown5;
|
||||
char unknown6[16];
|
||||
};
|
||||
|
||||
struct LoginAccepted_Struct {
|
||||
short unknown1;
|
||||
short unknown2;
|
||||
short unknown3;
|
||||
short unknown4;
|
||||
short unknown5;
|
||||
char encrypt[80];
|
||||
};
|
||||
|
||||
struct LoginFailedAttempts_Struct {
|
||||
char message; //0x01
|
||||
char unknown2[7]; //0x00
|
||||
uint32 lsid;
|
||||
char key[11]; //10 char + null term;
|
||||
uint32 failed_attempts;
|
||||
char unknown3[4]; //0x00, 0x00, 0x00, 0x03
|
||||
char unknown4[4]; //0x00, 0x00, 0x00, 0x02
|
||||
char unknown5[4]; //0xe7, 0x03, 0x00, 0x00
|
||||
char unknown6[4]; //0xff, 0xff, 0xff, 0xff
|
||||
char unknown7[4]; //0xa0, 0x05, 0x00, 0x00
|
||||
char unknown8[4]; //0x00, 0x00, 0x00, 0x02
|
||||
char unknown9[4]; //0xff, 0x03, 0x00, 0x00
|
||||
char unknown10[4]; //0x00, 0x00, 0x00, 0x00
|
||||
char unknown11[4]; //0x63, 0x00, 0x00, 0x00
|
||||
char unknown12[4]; //0x01, 0x00, 0x00, 0x00
|
||||
char unknown13[4]; //0x00, 0x00, 0x00, 0x00
|
||||
char unknown14[4]; //0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
struct LoginLoginFailed_Struct {
|
||||
short unknown1;
|
||||
short unknown2;
|
||||
short unknown3;
|
||||
short unknown4;
|
||||
short unknown5;
|
||||
char unknown6[74];
|
||||
};
|
||||
|
||||
struct ServerListHeader_Struct {
|
||||
|
||||
uint32 Unknown1;
|
||||
uint32 Unknown2;
|
||||
uint32 Unknown3;
|
||||
uint32 Unknown4;
|
||||
uint32 NumberOfServers;
|
||||
};
|
||||
|
||||
struct PlayEverquestRequest_Struct {
|
||||
uint16 Sequence;
|
||||
uint32 Unknown1;
|
||||
uint32 Unknown2;
|
||||
uint32 ServerNumber;
|
||||
};
|
||||
|
||||
struct PlayEverquestResponse_Struct {
|
||||
uint8 Sequence;
|
||||
uint8 Unknown1[9];
|
||||
uint8 Allowed;
|
||||
uint16 Message;
|
||||
uint8 Unknown2[3];
|
||||
uint32 ServerNumber;
|
||||
};
|
||||
|
||||
static const unsigned char FailedLoginResponseData[] = {
|
||||
0xf6, 0x85, 0x9c, 0x23, 0x57, 0x7e, 0x3e, 0x55, 0xb3, 0x4c, 0xf8, 0xc8, 0xcb, 0x77, 0xd5, 0x16,
|
||||
0x09, 0x7a, 0x63, 0xdc, 0x57, 0x7e, 0x3e, 0x55, 0xb3, 0x4c, 0xf8, 0xc8, 0xcb, 0x77, 0xd5, 0x16,
|
||||
0x09, 0x7a, 0x63, 0xdc, 0x57, 0x7e, 0x3e, 0x55, 0xb3
|
||||
};
|
||||
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
#ifndef EQEMU_LOGINSTRUCTURES_H
|
||||
#define EQEMU_LOGINSTRUCTURES_H
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
// unencrypted base message header in all packets
|
||||
struct LoginBaseMessage_Struct {
|
||||
int32_t sequence; // request type/login sequence (2: handshake, 3: login, 4: serverlist, ...)
|
||||
bool compressed; // true: deflated
|
||||
int8_t encrypt_type; // 1: invert (unused) 2: des (2 for encrypted player logins and order expansions) (client uses what it sent, ignores in reply)
|
||||
int32_t unk3; // unused?
|
||||
};
|
||||
|
||||
struct LoginBaseReplyMessage_Struct {
|
||||
bool success; // 0: failure (shows error string) 1: success
|
||||
int32_t error_str_id; // last error eqlsstr id, default: 101 (no error)
|
||||
char str[1]; // variable length, unknown (may be unused, this struct is a common pattern elsewhere)
|
||||
};
|
||||
|
||||
struct LoginHandShakeReply_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
LoginBaseReplyMessage_Struct base_reply;
|
||||
char unknown[1]; // variable length string
|
||||
};
|
||||
|
||||
// for reference, login buffer is variable (minimum size 8 due to encryption)
|
||||
struct PlayerLogin_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
char username[1];
|
||||
char password[1];
|
||||
};
|
||||
|
||||
// variable length, can use directly if not serializing strings
|
||||
struct PlayerLoginReply_Struct {
|
||||
// base header excluded to make struct data easier to encrypt
|
||||
//LoginBaseMessage_Struct base_header;
|
||||
LoginBaseReplyMessage_Struct base_reply;
|
||||
|
||||
int8_t unk1; // (default: 0)
|
||||
int8_t unk2; // (default: 0)
|
||||
int32_t lsid; // (default: -1)
|
||||
char key[11]; // client reads until null (variable length)
|
||||
int32_t failed_attempts;
|
||||
bool show_player_count; // admin flag, enables admin button and shows server player counts (default: false)
|
||||
int32_t offer_min_days; // guess, needs more investigation, maybe expansion offers (default: 99)
|
||||
int32_t offer_min_views; // guess (default: -1)
|
||||
int32_t offer_cooldown_minutes; // guess (default: 0)
|
||||
int32_t web_offer_number; // web order view number, 0 nothing (default: 0)
|
||||
int32_t web_offer_min_days; // number of days to show offer (based on first offer time in client eqls ini) (default: 99)
|
||||
int32_t web_offer_min_views; // mininum views, -1 for no minimum, 0 for never shows (based on client eqls ini) (default: -1)
|
||||
int32_t web_offer_cooldown_minutes; // minimum minutes between offers (based on last offer time in client eqls ini) (default: 0)
|
||||
char username[1]; // variable length, if not empty client attempts to re-login to server select when quitting from char select and sends this in a struct
|
||||
char unknown[1]; // variable length, password unlikely? client doesn't send this on re-login from char select
|
||||
};
|
||||
|
||||
// variable length, for reference
|
||||
struct LoginClientServerData_Struct {
|
||||
char ip[1];
|
||||
int32_t server_type; // legends, preferred, standard
|
||||
int32_t server_id;
|
||||
char server_name[1];
|
||||
char country_code[1]; // if doesn't match client locale then server is colored dark grey in list and joining is prevented (to block for "us" use one of "kr", "tw", "jp", "de", "fr", or "cn") (ISO 3166-1 alpha-2)
|
||||
char language_code[1];
|
||||
int32_t server_status; // see ServerStatusFlags
|
||||
int32_t player_count;
|
||||
};
|
||||
|
||||
// variable length, for reference
|
||||
struct ServerListReply_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
LoginBaseReplyMessage_Struct base_reply;
|
||||
|
||||
int32_t server_count;
|
||||
LoginClientServerData_Struct servers[0];
|
||||
};
|
||||
|
||||
struct PlayEverquestRequest_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
uint32 server_number;
|
||||
};
|
||||
|
||||
// SCJoinServerReply
|
||||
struct PlayEverquestResponse_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
LoginBaseReplyMessage_Struct base_reply;
|
||||
uint32 server_number;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
enum LSClientVersion {
|
||||
cv_titanium,
|
||||
cv_sod
|
||||
};
|
||||
|
||||
enum LSClientStatus {
|
||||
cs_not_sent_session_ready,
|
||||
cs_waiting_for_login,
|
||||
cs_creating_account,
|
||||
cs_failed_to_login,
|
||||
cs_logged_in
|
||||
};
|
||||
|
||||
namespace LS {
|
||||
namespace ServerStatusFlags {
|
||||
enum eServerStatusFlags {
|
||||
Up = 0, // default
|
||||
Down = 1,
|
||||
Unused = 2,
|
||||
Locked = 4 // can be combined with Down to show "Locked (Down)"
|
||||
};
|
||||
}
|
||||
|
||||
namespace ServerTypeFlags {
|
||||
enum eServerTypeFlags {
|
||||
None = 0,
|
||||
Standard = 1,
|
||||
Unknown2 = 2,
|
||||
Unknown4 = 4,
|
||||
Preferred = 8,
|
||||
Legends = 16 // can be combined with Preferred flag to override color in Legends section with Preferred color (green)
|
||||
};
|
||||
}
|
||||
|
||||
enum ServerType {
|
||||
Standard = 3,
|
||||
Preferred = 2,
|
||||
Legends = 1,
|
||||
};
|
||||
|
||||
namespace ErrStr {
|
||||
constexpr static int ERROR_NONE = 101; // No Error
|
||||
constexpr static int ERROR_UNKNOWN = 102; // Error - Unknown Error Occurred
|
||||
constexpr static int ERROR_ACTIVE_CHARACTER = 111; // Error 1018: You currently have an active character on that EverQuest Server, please allow a minute for synchronization and try again.
|
||||
constexpr static int ERROR_SERVER_UNAVAILABLE = 326; // That server is currently unavailable. Please check the EverQuest webpage for current server status and try again later.
|
||||
constexpr static int ERROR_ACCOUNT_SUSPENDED = 337; // This account is currently suspended. Please contact customer service for more information.
|
||||
constexpr static int ERROR_ACCOUNT_BANNED = 338; // This account is currently banned. Please contact customer service for more information.
|
||||
constexpr static int ERROR_WORLD_MAX_CAPACITY = 339; // The world server is currently at maximum capacity and not allowing further logins until the number of players online decreases. Please try again later.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
},
|
||||
"worldservers": {
|
||||
"unregistered_allowed": true,
|
||||
"show_player_count": false,
|
||||
"dev_test_servers_list_bottom": false,
|
||||
"special_character_start_list_bottom": false,
|
||||
"reject_duplicate_servers": false
|
||||
},
|
||||
"web_api": {
|
||||
|
||||
@@ -5,7 +5,7 @@ CREATE TABLE `login_accounts` (
|
||||
`account_password` text NOT NULL,
|
||||
`account_email` varchar(100) NOT NULL,
|
||||
`source_loginserver` varchar(64) DEFAULT NULL,
|
||||
`last_ip_address` varchar(15) NOT NULL,
|
||||
`last_ip_address` varchar(80) NOT NULL,
|
||||
`last_login_date` datetime NOT NULL,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT current_timestamp(),
|
||||
@@ -22,7 +22,7 @@ CREATE TABLE `login_server_admins` (
|
||||
`last_name` varchar(50) NOT NULL,
|
||||
`email` varchar(100) NOT NULL,
|
||||
`registration_date` datetime NOT NULL,
|
||||
`registration_ip_address` varchar(15) NOT NULL,
|
||||
`registration_ip_address` varchar(80) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
||||
|
||||
@@ -45,7 +45,7 @@ CREATE TABLE `login_world_servers` (
|
||||
`tag_description` varchar(50) NOT NULL DEFAULT '',
|
||||
`login_server_list_type_id` int(11) NOT NULL,
|
||||
`last_login_date` datetime DEFAULT NULL,
|
||||
`last_ip_address` varchar(15) DEFAULT NULL,
|
||||
`last_ip_address` varchar(80) DEFAULT NULL,
|
||||
`login_server_admin_id` int(11) NOT NULL,
|
||||
`is_server_trusted` int(11) NOT NULL,
|
||||
`note` varchar(255) DEFAULT NULL,
|
||||
@@ -61,4 +61,4 @@ CREATE TABLE `login_api_tokens` (
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include "loginserver_command_handler.h"
|
||||
@@ -58,6 +38,7 @@ namespace LoginserverCommandHandler {
|
||||
function_map["web-api-token:list"] = &LoginserverCommandHandler::ListLoginserverApiTokens;
|
||||
function_map["world-admin:create"] = &LoginserverCommandHandler::CreateLoginserverWorldAdminAccount;
|
||||
function_map["world-admin:update"] = &LoginserverCommandHandler::UpdateLoginserverWorldAdminAccountPassword;
|
||||
function_map["health:check-login"] = &LoginserverCommandHandler::HealthCheckLogin;
|
||||
|
||||
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
|
||||
}
|
||||
@@ -301,4 +282,24 @@ namespace LoginserverCommandHandler {
|
||||
cmd(3).str()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @param cmd
|
||||
* @param description
|
||||
*/
|
||||
void HealthCheckLogin(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||
{
|
||||
description = "Checks login health using a test user";
|
||||
|
||||
std::vector<std::string> arguments = {};
|
||||
std::vector<std::string> options = {};
|
||||
|
||||
if (cmd[{"-h", "--help"}]) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogInfo("[CLI] [HealthCheck] Response code [{}]", AccountManagement::HealthCheckUserLogin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iostream"
|
||||
#include "../common/cli/eqemu_command_handler.h"
|
||||
|
||||
@@ -34,6 +14,7 @@ namespace LoginserverCommandHandler {
|
||||
void UpdateLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
void CheckExternalLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
void UpdateLoginserverWorldAdminAccountPassword(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
void HealthCheckLogin(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "loginserver_webserver.h"
|
||||
#include "server_manager.h"
|
||||
#include "login_server.h"
|
||||
@@ -51,14 +31,15 @@ namespace LoginserverWebserver {
|
||||
auto iter = server.server_manager->getWorldServers().begin();
|
||||
while (iter != server.server_manager->getWorldServers().end()) {
|
||||
Json::Value row;
|
||||
row["server_long_name"] = (*iter)->GetServerLongName();
|
||||
row["server_short_name"] = (*iter)->GetServerLongName();
|
||||
row["server_list_id"] = (*iter)->GetServerListID();
|
||||
row["server_status"] = (*iter)->GetStatus();
|
||||
row["zones_booted"] = (*iter)->GetZonesBooted();
|
||||
row["local_ip"] = (*iter)->GetLocalIP();
|
||||
row["remote_ip"] = (*iter)->GetRemoteIP();
|
||||
row["players_online"] = (*iter)->GetPlayersOnline();
|
||||
row["server_long_name"] = (*iter)->GetServerLongName();
|
||||
row["server_short_name"] = (*iter)->GetServerShortName();
|
||||
row["server_list_type_id"] = (*iter)->GetServerListID();
|
||||
row["server_status"] = (*iter)->GetStatus();
|
||||
row["zones_booted"] = (*iter)->GetZonesBooted();
|
||||
row["local_ip"] = (*iter)->GetLocalIP();
|
||||
row["remote_ip"] = (*iter)->GetRemoteIP();
|
||||
row["players_online"] = (*iter)->GetPlayersOnline();
|
||||
row["world_id"] = (*iter)->GetServerId();
|
||||
response.append(row);
|
||||
++iter;
|
||||
}
|
||||
@@ -316,6 +297,24 @@ namespace LoginserverWebserver {
|
||||
LoginserverWebserver::SendResponse(response, res);
|
||||
}
|
||||
);
|
||||
|
||||
api.Get(
|
||||
"/probes/healthcheck", [](const httplib::Request &request, httplib::Response &res) {
|
||||
Json::Value response;
|
||||
uint32 login_response = AccountManagement::HealthCheckUserLogin();
|
||||
|
||||
response["status"] = login_response;
|
||||
if (login_response == 0) {
|
||||
response["message"] = "Process unresponsive, exiting...";
|
||||
LogInfo("Probes healthcheck unresponsive, exiting...");
|
||||
}
|
||||
|
||||
LoginserverWebserver::SendResponse(response, res);
|
||||
if (login_response == 0) {
|
||||
std::exit(0);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user