mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
Compare commits
495 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 451d791336 | |||
| f17779efeb | |||
| 3aed0e257a | |||
| 7fb3146a77 | |||
| a26227f258 | |||
| db085b7126 | |||
| bca567d2f5 | |||
| c62d9040cb | |||
| abb1086e52 | |||
| 1f04938535 | |||
| 12204dd927 | |||
| b118864920 | |||
| af749cf07a | |||
| bf45e8b491 | |||
| 29b90fbeaf | |||
| 6cecc85d17 | |||
| f3c85dc585 | |||
| 2e4868d3eb | |||
| 0005df31f7 | |||
| 1f3287759a | |||
| 0b3c489028 | |||
| cda6a1465b | |||
| 9a4a49fc9e | |||
| 118c6b5636 | |||
| 161edef2a8 | |||
| 54053f7e24 | |||
| fdf2fe71e1 | |||
| 5a600cd7c0 | |||
| 91a7ebbdfb | |||
| 3dbb5fab50 | |||
| 9bc96432be | |||
| 48cb96214a | |||
| 084e588843 | |||
| 11fdbb6a49 | |||
| 96ef76847b | |||
| 9a7ecb4e8d | |||
| 578fafb485 | |||
| 4e2b2aca6a | |||
| ae0eebe043 | |||
| 4e129ca7b5 | |||
| 1521e3810f | |||
| 2a18d7cd80 | |||
| d0b505f32d | |||
| 9c95d1bfa2 | |||
| 70ad517c14 | |||
| 265458a6da | |||
| 8ab2b15768 | |||
| cf80e594bc | |||
| 655cb798c3 | |||
| 499c0fdca5 | |||
| 28d5c8f301 | |||
| 7911225960 | |||
| 1990ae970a | |||
| b41ae05dc4 | |||
| 8bb76ae2fe | |||
| e846fc4eea | |||
| e9f5c03141 | |||
| 8a26eaabf3 | |||
| a73df6aa09 | |||
| 420667a35b | |||
| b63821bbae | |||
| 51995ca7f2 | |||
| edf93f20e5 | |||
| 1e6a67e1ad | |||
| 4f20236440 | |||
| 40696a132b | |||
| 34a4db6302 | |||
| b2526ff6d6 | |||
| 6fcb97e153 | |||
| 3177b6ac46 | |||
| 3230d81d2c | |||
| 89dbdff925 | |||
| 5206983513 | |||
| 1bfbe51d89 | |||
| 0041d3e0da | |||
| fec567c2f3 | |||
| 4b61d00dfe | |||
| 4cba9439b9 | |||
| dad1efbeaa | |||
| ae781ee962 | |||
| 67d8d6d67d | |||
| b69fee5619 | |||
| f698571f35 | |||
| 891944a1ba | |||
| cc377f2659 | |||
| 6222132625 | |||
| 9e3f9f9749 | |||
| b8216a5d40 | |||
| 7154873091 | |||
| 052583d170 | |||
| 463aeea5a3 | |||
| a624b85ea1 | |||
| 4b77f573c0 | |||
| 1f928cd161 | |||
| b97696a8c0 | |||
| a428eb61a1 | |||
| 1515785ada | |||
| 8673aec9fd | |||
| 534bed1483 | |||
| 45278f80ca | |||
| 1e1b21f2bf | |||
| fcaa685e77 | |||
| 96103b09e0 | |||
| de38440c4f | |||
| 512880e316 | |||
| e4bfc547cb | |||
| afa6358838 | |||
| c53c769a7c | |||
| 4ef481dbc0 | |||
| c887b7eae3 | |||
| eefe0dfbb7 | |||
| 8e1b6a23eb | |||
| c1b48b9931 | |||
| fceca6e72f | |||
| eb4592c3ae | |||
| f9536f9621 | |||
| c89cd9d3c4 | |||
| 2e98de3923 | |||
| 26e14c02b6 | |||
| b45fd24f9d | |||
| acae5d81ab | |||
| 89bfbe6bd2 | |||
| 3e4587cd57 | |||
| 076d393f79 | |||
| 44e3f28cb0 | |||
| b4339691f9 | |||
| b738f8852d | |||
| 405ed5447d | |||
| 70ba7c9c85 | |||
| c3a94766ea | |||
| 698d6d4ed2 | |||
| af4c630ede | |||
| b83c0f8bf9 | |||
| 1acb76bc74 | |||
| ed4fc74bd4 | |||
| b402e8f33d | |||
| c8e673c6d4 | |||
| 674dfc5fac | |||
| 2970afff67 | |||
| 2b1950d2e2 | |||
| 31cebb5793 | |||
| ccbbadc5ee | |||
| bfd0752c4d | |||
| 00c40f5d9e | |||
| 859252a270 | |||
| 2eb14a5c8a | |||
| be291d58b0 | |||
| 678c25e02c | |||
| 98cbb7d781 | |||
| d3803045bc | |||
| db5e511af3 | |||
| 585c07210d | |||
| b8624d0488 | |||
| 206b769731 | |||
| 5381dcead1 | |||
| 5c14bc92bd | |||
| 898aea80c7 | |||
| 69a3432898 | |||
| 1acf78101f | |||
| 0d6d78ebda | |||
| a534ab83ec | |||
| 3092a8ba3b | |||
| d341a1b38f | |||
| f837d423ef | |||
| 7749f83134 | |||
| c0575892cb | |||
| 377c569635 | |||
| 5e60fcdc0c | |||
| 4d1d9df05d | |||
| c6c4480061 | |||
| c2794b244d | |||
| 83cae7aaf3 | |||
| 08d197fe15 | |||
| 5a0fcdfefd | |||
| 49094bcfbc | |||
| 6fb1d95518 | |||
| bf25937ee0 | |||
| 05e7c473df | |||
| c149e6ca5f | |||
| 537e3931ef | |||
| 9476f9e417 | |||
| 1f4753b719 | |||
| 65c05f227b | |||
| ef6b2976a3 | |||
| 7b4908957d | |||
| 963da70506 | |||
| 1ef577bc25 | |||
| a2364023c4 | |||
| 1c6a76246f | |||
| 8c17c42a10 | |||
| e9cb8781bf | |||
| 04a18786f9 | |||
| 20bd37dde7 | |||
| 665efe09f3 | |||
| a28ea6419f | |||
| 9f25c9070c | |||
| 57354579aa | |||
| 25a5310f49 | |||
| 66ee0dc9bd | |||
| f39684b7f7 | |||
| f06ff14f9e | |||
| 661ad09291 | |||
| 9708bd38c4 | |||
| 8a2fce83e0 | |||
| 2081b0e214 | |||
| eaf31fb14b | |||
| d2e7cf96bd | |||
| 24d2a5723b | |||
| 17c8af3814 | |||
| 69bad593cd | |||
| 0884c57928 | |||
| 461931f5bd | |||
| 0d76e224fd | |||
| ea15e9bc5f | |||
| 5fce042a31 | |||
| 6a64d845c2 | |||
| 19c92173d2 | |||
| 880de837d9 | |||
| 8df7bcc2c8 | |||
| d9eeb00dea | |||
| a6af014d5e | |||
| 758a1af6ae | |||
| f1ee042de6 | |||
| 2014b6c251 | |||
| 8fa76b9154 | |||
| 9f6976e852 | |||
| b117be29fb | |||
| d3641be6c0 | |||
| 06fbd7103e | |||
| acef4c0264 | |||
| b62944c5fb | |||
| 8065cdb89d | |||
| 20530ed3cf | |||
| 4aa8cecc55 | |||
| 4ec210c411 | |||
| 4de85ff836 | |||
| ba6009730b | |||
| b0d33f094d | |||
| 5ff0f4851e | |||
| 63e1599e9b | |||
| 4498819fad | |||
| f5cfec529e | |||
| 9d9374ec19 | |||
| e56edd9231 | |||
| 979c819075 | |||
| b754ddbc67 | |||
| 3f2f7b3929 | |||
| 9297fc38f6 | |||
| ff4e549ec0 | |||
| a8ec176432 | |||
| 212f8a3062 | |||
| cca5fe3286 | |||
| 9ac15d7a4b | |||
| 23a187f6c1 | |||
| f3255c17da | |||
| 90eb9e9da2 | |||
| ffb5b2393f | |||
| cd32a5a47a | |||
| debc2644b1 | |||
| 9c9615e8bb | |||
| 53ec007459 | |||
| f5da6e18fc | |||
| 72ae1b0e0b | |||
| 581cbccad5 | |||
| 4aca39ad9b | |||
| 5a7186305d | |||
| 780f8f8515 | |||
| 186834594f | |||
| f4310c5a06 | |||
| 4d77ba28fe | |||
| 222fd060a3 | |||
| 31d0adbacc | |||
| 9fe17f4d46 | |||
| 16d6014a87 | |||
| 7801b295d6 | |||
| e92d130538 | |||
| 7c2ee06355 | |||
| f6259af22b | |||
| 25c119b843 | |||
| 6d9bcfe39f | |||
| ce09aad28a | |||
| 460468224e | |||
| 6bdc9b6ba5 | |||
| 7181b46608 | |||
| eb8cd1a5b4 | |||
| a8e65cdce1 | |||
| 949e7adff8 | |||
| 1ba78d0988 | |||
| 35eb5b24dd | |||
| 7b808ee6e0 | |||
| dfa90aaac5 | |||
| 525813be02 | |||
| 2a927c5c80 | |||
| 6e550ecc75 | |||
| 839baba553 | |||
| 5c2ac5ab24 | |||
| 553d9aca6f | |||
| 910dfaf082 | |||
| 9730917d73 | |||
| 32e8a0fa45 | |||
| 193dbe5938 | |||
| 86943ce6be | |||
| 739f54bbfb | |||
| b165760f18 | |||
| 1a577014d9 | |||
| 54ea7d7c4b | |||
| 0111e9a5d0 | |||
| 0c2d26579a | |||
| 8eaeda5ec5 | |||
| 8c75cf1ff5 | |||
| 87b1d32ce8 | |||
| d8f34651de | |||
| c2917a9004 | |||
| 5473457c0c | |||
| 392b328a95 | |||
| 4bc6493718 | |||
| 78d8b909be | |||
| 7d71163fa0 | |||
| 0668f41de2 | |||
| a9969e500b | |||
| 3eb102a006 | |||
| 9d3ece8133 | |||
| b2ed5fe479 | |||
| 86f9a205e5 | |||
| f0937c3963 | |||
| ffd652a643 | |||
| feea52f79e | |||
| 2c922876a9 | |||
| b41e58fd10 | |||
| 8b582730a8 | |||
| d5eb015533 | |||
| 8ad4ef503b | |||
| a914e97c29 | |||
| 126d8edc57 | |||
| d17cfff8fe | |||
| 1a5ce7a9de | |||
| bd2836db61 | |||
| ff5783965a | |||
| 7fcf6b51d8 | |||
| eea3965d02 | |||
| d40b95f2e8 | |||
| dc9e4e8260 | |||
| 8c25486112 | |||
| 9613d128ae | |||
| 11bc21f99f | |||
| cdfd473476 | |||
| bb7cae46c5 | |||
| c7e196e26d | |||
| daec42c4d9 | |||
| b04d71ff45 | |||
| fbebec03ae | |||
| 217c9751a8 | |||
| 9e0f440106 | |||
| 6638b9ade5 | |||
| ea02042ace | |||
| 4e7bcd86ff | |||
| 915bbe32f0 | |||
| 151cb5f286 | |||
| c8d6895526 | |||
| dce5d774e2 | |||
| 69c57d8715 | |||
| a42d77c204 | |||
| 6757f61249 | |||
| 6e51783d4b | |||
| a4f68f755f | |||
| 8d67c1aed7 | |||
| 1e90e64178 | |||
| f50d502f3d | |||
| e086f53b97 | |||
| 682054970c | |||
| d7c110041a | |||
| 6c73fee075 | |||
| 8bb909090b | |||
| ee49ad3ce9 | |||
| 89691d6c32 | |||
| 09b633e374 | |||
| 18fa056a38 | |||
| 2e9cf7dbd7 | |||
| c9d4bb178f | |||
| 5d138891d8 | |||
| 5fdf976137 | |||
| a8d3ba41a7 | |||
| 2cd910ad86 | |||
| e903b06c22 | |||
| ca874cb861 | |||
| a2a13e9779 | |||
| 104edee427 | |||
| 6256660972 | |||
| 0541eec8bf | |||
| 1aab23098a | |||
| c74c46263a | |||
| 51c51b0d72 | |||
| f4e609ef0a | |||
| 9356b5dc7f | |||
| 6a31af81ee | |||
| 2a308b1f14 | |||
| 8681d0acf7 | |||
| 7d1362732d | |||
| 86ed2c1e76 | |||
| d817f08373 | |||
| 882e3742d9 | |||
| 660416065e | |||
| 79d8a6329c | |||
| a2dd1fc753 | |||
| ce41cf9cd5 | |||
| c0e07cec01 | |||
| 3c8ecd6715 | |||
| b6e592db13 | |||
| 94cce09253 | |||
| f6a96ae941 | |||
| 290133803e | |||
| 4627bfe271 | |||
| c3e10a7409 | |||
| 65e429a596 | |||
| 63933f53c8 | |||
| d23a6e646e | |||
| 2690e4de4d | |||
| 1122d29e19 | |||
| b2aa696a3a | |||
| 40b63f74ee | |||
| 9c931ced4e | |||
| 52276d06b0 | |||
| 597c4e8c60 | |||
| 5b41060588 | |||
| c737504645 | |||
| e277e55718 | |||
| 5936d865b5 | |||
| f2d47927b8 | |||
| 4836db73d7 | |||
| e00cd4afd9 | |||
| ebca112769 | |||
| 5bfcef600f | |||
| 845dd339b2 | |||
| 09b91f5229 | |||
| 0eeb73b436 | |||
| ad790ac8ef | |||
| d7abf3f26c | |||
| 6739eea78b | |||
| cd3125ced0 | |||
| 72e0320509 | |||
| 15ff0bf5c3 | |||
| a402f01514 | |||
| dfe4bb5b78 | |||
| c24bfaf35f | |||
| 7dc1e10956 | |||
| 63198d974e | |||
| cd8ab727aa | |||
| 1d88b063aa | |||
| 54da27424f | |||
| 6e1f317c60 | |||
| 3e8ef681a3 | |||
| e009e064f3 | |||
| 9654beda9f | |||
| 3105577c1b | |||
| c06774ca61 | |||
| e1e3d99a79 | |||
| 8942c0ea24 | |||
| 1603ea097f | |||
| 0426a15fec | |||
| 5b374927f2 | |||
| d59170f84f | |||
| 8aaf39d2d9 | |||
| 2bb305305a | |||
| e8127f4b8a | |||
| 762de03be7 | |||
| f18b9c99b5 | |||
| 8f9a859c56 | |||
| 5e008a5a97 | |||
| fa2052236c | |||
| f75c5b6fc8 | |||
| 63045fadd9 | |||
| 850b32f2ca | |||
| 60d5c11c43 | |||
| 03458b88a4 | |||
| 0852468b88 | |||
| 3d1dda888d | |||
| a4c171cb1d | |||
| 20de6acfea | |||
| 9c42f28b0d | |||
| 75d3329d37 | |||
| 26a95998da | |||
| 6715977a1f | |||
| 7a28a6e9a7 | |||
| 44f85f140c | |||
| a73bf221ed | |||
| f16faae964 | |||
| e0391dfcb8 | |||
| cc0034fd3c | |||
| 3fdfc82ca0 | |||
| 0ec53eff52 | |||
| 7a778c549f | |||
| 3ee5730890 | |||
| 569a907e43 | |||
| 5bbeec626c | |||
| 6b70faf141 |
+4
-12
@@ -23,21 +23,13 @@ CMakeFiles
|
|||||||
Makefile
|
Makefile
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
Build/
|
[Bb]uild*/
|
||||||
build/
|
|
||||||
Build32/
|
|
||||||
build32/
|
|
||||||
Build64/
|
|
||||||
build64/
|
|
||||||
Build_32/
|
|
||||||
build_32/
|
|
||||||
Build_64/
|
|
||||||
build_64/
|
|
||||||
x64/
|
|
||||||
x86/
|
|
||||||
log/
|
log/
|
||||||
logs/
|
logs/
|
||||||
vcpkg/
|
vcpkg/
|
||||||
|
|
||||||
.idea/*
|
.idea/*
|
||||||
*cbp
|
*cbp
|
||||||
|
|
||||||
|
submodules/*
|
||||||
|
cmake-build-debug/
|
||||||
+4
-4
@@ -1,6 +1,3 @@
|
|||||||
[submodule "submodules/websocketpp"]
|
|
||||||
path = submodules/websocketpp
|
|
||||||
url = https://github.com/zaphoyd/websocketpp.git
|
|
||||||
[submodule "submodules/glm"]
|
[submodule "submodules/glm"]
|
||||||
path = submodules/glm
|
path = submodules/glm
|
||||||
url = https://github.com/g-truc/glm.git
|
url = https://github.com/g-truc/glm.git
|
||||||
@@ -13,6 +10,9 @@
|
|||||||
[submodule "submodules/cereal"]
|
[submodule "submodules/cereal"]
|
||||||
path = submodules/cereal
|
path = submodules/cereal
|
||||||
url = https://github.com/USCiLab/cereal.git
|
url = https://github.com/USCiLab/cereal.git
|
||||||
|
[submodule "submodules/websocketpp"]
|
||||||
|
path = submodules/websocketpp
|
||||||
|
url = https://github.com/zaphoyd/websocketpp.git
|
||||||
[submodule "submodules/recastnavigation"]
|
[submodule "submodules/recastnavigation"]
|
||||||
path = submodules/recastnavigation
|
path = submodules/recastnavigation
|
||||||
url = https://github.com/recastnavigation/recastnavigation.git
|
url = https://github.com/EQEmu/recastnavigation.git
|
||||||
|
|||||||
+62
-110
@@ -6,16 +6,8 @@
|
|||||||
#EQEMU_DISABLE_SAFESEH
|
#EQEMU_DISABLE_SAFESEH
|
||||||
#EQEMU_BUILD_MSVC_MP
|
#EQEMU_BUILD_MSVC_MP
|
||||||
#EQEMU_DEBUG_LEVEL
|
#EQEMU_DEBUG_LEVEL
|
||||||
#EQEMU_LOG_LEVEL_STATUS
|
|
||||||
#EQEMU_LOG_LEVEL_NORMAL
|
|
||||||
#EQEMU_LOG_LEVEL_ERROR
|
|
||||||
#EQEMU_LOG_LEVEL_DEBUG
|
#EQEMU_LOG_LEVEL_DEBUG
|
||||||
#EQEMU_LOG_LEVEL_QUEST
|
|
||||||
#EQEMU_LOG_LEVEL_COMMANDS
|
|
||||||
#EQEMU_LOG_LEVEL_CRASH
|
|
||||||
#EQEMU_DEPOP_INVALIDATES_CACHE
|
|
||||||
#EQEMU_ENABLE_BOTS
|
#EQEMU_ENABLE_BOTS
|
||||||
#EQEMU_DISABLE_LOGSYS
|
|
||||||
#EQEMU_COMMANDS_LOGGING
|
#EQEMU_COMMANDS_LOGGING
|
||||||
#EQEMU_BUILD_SERVER
|
#EQEMU_BUILD_SERVER
|
||||||
#EQEMU_BUILD_LOGIN
|
#EQEMU_BUILD_LOGIN
|
||||||
@@ -26,6 +18,8 @@
|
|||||||
#EQEMU_BUILD_CLIENT_FILES
|
#EQEMU_BUILD_CLIENT_FILES
|
||||||
#EQEMU_USE_MAP_MMFS
|
#EQEMU_USE_MAP_MMFS
|
||||||
#EQEMU_MAP_DIR
|
#EQEMU_MAP_DIR
|
||||||
|
#EQEMU_ARCH
|
||||||
|
#EQEMU_ARCH_ALT
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||||
IF(POLICY CMP0074)
|
IF(POLICY CMP0074)
|
||||||
@@ -57,33 +51,37 @@ ENDIF(MSVC OR MINGW)
|
|||||||
|
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
IF(CMAKE_CL_64)
|
IF(CMAKE_CL_64)
|
||||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64")
|
SET(EQEMU_ARCH "x64")
|
||||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x64")
|
SET(EQEMU_ARCH_ALT "x64")
|
||||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x64")
|
|
||||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x64")
|
|
||||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
|
||||||
IF(MSVC_VERSION GREATER 1800)
|
|
||||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v140/dynamic")
|
|
||||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
|
||||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v120/dynamic")
|
|
||||||
ELSE()
|
|
||||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic")
|
|
||||||
ENDIF()
|
|
||||||
ELSE(CMAKE_CL_64)
|
ELSE(CMAKE_CL_64)
|
||||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86")
|
SET(EQEMU_ARCH "x86")
|
||||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86")
|
SET(EQEMU_ARCH_ALT "Win32")
|
||||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
|
|
||||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
|
||||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
|
|
||||||
IF(MSVC_VERSION GREATER 1800)
|
|
||||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
|
|
||||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
|
||||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v120/dynamic")
|
|
||||||
ELSE()
|
|
||||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic")
|
|
||||||
ENDIF()
|
|
||||||
ENDIF(CMAKE_CL_64)
|
ENDIF(CMAKE_CL_64)
|
||||||
|
|
||||||
|
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_${EQEMU_ARCH}")
|
||||||
|
|
||||||
|
IF(VCPKG_TOOLCHAIN)
|
||||||
|
IF(NOT MSVC_VERSION GREATER 1800)
|
||||||
|
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||||
|
ENDIF()
|
||||||
|
ELSE(VCPKG_TOOLCHAIN)
|
||||||
|
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_${EQEMU_ARCH}")
|
||||||
|
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_${EQEMU_ARCH}")
|
||||||
|
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_${EQEMU_ARCH}")
|
||||||
|
|
||||||
|
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||||
|
ENDIF(VCPKG_TOOLCHAIN)
|
||||||
|
|
||||||
|
IF(SODIUM_INCLUDE_HINTS)
|
||||||
|
IF(MSVC_VERSION GREATER 1800)
|
||||||
|
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v140/dynamic")
|
||||||
|
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||||
|
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v120/dynamic")
|
||||||
|
ELSE()
|
||||||
|
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v110/dynamic")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF(SODIUM_INCLUDE_HINTS)
|
||||||
|
|
||||||
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
|
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
|
||||||
OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON)
|
OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON)
|
||||||
IF(EQEMU_DISABLE_CRT_SECURE_WARNINGS)
|
IF(EQEMU_DISABLE_CRT_SECURE_WARNINGS)
|
||||||
@@ -144,36 +142,6 @@ SET(EQEMU_DEBUG_LEVEL 5 CACHE STRING "EQEmu debug level:
|
|||||||
10 - More errors than you ever wanted to see"
|
10 - More errors than you ever wanted to see"
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(EQEMU_LOG_LEVEL_STATUS 2 CACHE STRING "EQEmu logging level for [Status]:
|
|
||||||
0 - Disabled
|
|
||||||
1 - Ouput to File Enabled
|
|
||||||
2 - Output to stdout Enabled
|
|
||||||
3 - Output to File and stdout Enabled
|
|
||||||
8 - Output to stderr Enabled
|
|
||||||
9 - Output to File and stderr Enabled
|
|
||||||
11 - Output to File, stdout and stderr Enabled"
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(EQEMU_LOG_LEVEL_NORMAL 3 CACHE STRING "EQEmu logging level for [Normal]:
|
|
||||||
0 - Disabled
|
|
||||||
1 - Ouput to File Enabled
|
|
||||||
2 - Output to stdout Enabled
|
|
||||||
3 - Output to File and stdout Enabled
|
|
||||||
8 - Output to stderr Enabled
|
|
||||||
9 - Output to File and stderr Enabled
|
|
||||||
11 - Output to File, stdout and stderr Enabled"
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(EQEMU_LOG_LEVEL_ERROR 2 CACHE STRING "EQEmu logging level for [Error]:
|
|
||||||
0 - Disabled
|
|
||||||
1 - Ouput to File Enabled
|
|
||||||
2 - Output to stdout Enabled
|
|
||||||
3 - Output to File and stdout Enabled
|
|
||||||
8 - Output to stderr Enabled
|
|
||||||
9 - Output to File and stderr Enabled
|
|
||||||
11 - Output to File, stdout and stderr Enabled"
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(EQEMU_LOG_LEVEL_DEBUG 3 CACHE STRING "EQEmu logging level for [Debug]:
|
SET(EQEMU_LOG_LEVEL_DEBUG 3 CACHE STRING "EQEmu logging level for [Debug]:
|
||||||
0 - Disabled
|
0 - Disabled
|
||||||
1 - Ouput to File Enabled
|
1 - Ouput to File Enabled
|
||||||
@@ -184,47 +152,14 @@ SET(EQEMU_LOG_LEVEL_DEBUG 3 CACHE STRING "EQEmu logging level for [Debug]:
|
|||||||
11 - Output to File, stdout and stderr Enabled"
|
11 - Output to File, stdout and stderr Enabled"
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(EQEMU_LOG_LEVEL_QUEST 2 CACHE STRING "EQEmu logging level for [Quest]:
|
OPTION(EQEMU_LSPX "" OFF)
|
||||||
0 - Disabled
|
MARK_AS_ADVANCED(EQEMU_LSPX)
|
||||||
1 - Ouput to File Enabled
|
|
||||||
2 - Output to stdout Enabled
|
|
||||||
3 - Output to File and stdout Enabled
|
|
||||||
8 - Output to stderr Enabled
|
|
||||||
9 - Output to File and stderr Enabled
|
|
||||||
11 - Output to File, stdout and stderr Enabled"
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(EQEMU_LOG_LEVEL_COMMANDS 1 CACHE STRING "EQEmu logging level for [Commands]:
|
MARK_AS_ADVANCED(EQEMU_LOG_LEVEL_DEBUG)
|
||||||
0 - Disabled
|
|
||||||
1 - Ouput to File Enabled
|
|
||||||
2 - Output to stdout Enabled
|
|
||||||
3 - Output to File and stdout Enabled
|
|
||||||
8 - Output to stderr Enabled
|
|
||||||
9 - Output to File and stderr Enabled
|
|
||||||
11 - Output to File, stdout and stderr Enabled"
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(EQEMU_LOG_LEVEL_CRASH 3 CACHE STRING "EQEmu logging level for [Crash]:
|
|
||||||
0 - Disabled
|
|
||||||
1 - Ouput to File Enabled
|
|
||||||
2 - Output to stdout Enabled
|
|
||||||
3 - Output to File and stdout Enabled
|
|
||||||
8 - Output to stderr Enabled
|
|
||||||
9 - Output to File and stderr Enabled
|
|
||||||
11 - Output to File, stdout and stderr Enabled"
|
|
||||||
)
|
|
||||||
|
|
||||||
MARK_AS_ADVANCED(EQEMU_LOG_LEVEL_STATUS EQEMU_LOG_LEVEL_NORMAL EQEMU_LOG_LEVEL_ERROR EQEMU_LOG_LEVEL_DEBUG EQEMU_LOG_LEVEL_QUEST EQEMU_LOG_LEVEL_COMMANDS EQEMU_LOG_LEVEL_CRASH)
|
|
||||||
|
|
||||||
#NPC Types Cache Behavior
|
|
||||||
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
|
|
||||||
|
|
||||||
#Bots are a compile time option so on/off
|
#Bots are a compile time option so on/off
|
||||||
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
|
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
|
||||||
|
|
||||||
#Disable entire _mlog system (excludes trade/command logs)
|
|
||||||
OPTION(EQEMU_DISABLE_LOGSYS "Disable Logging INI System" ON)
|
|
||||||
|
|
||||||
#Enable GM Command log system
|
#Enable GM Command log system
|
||||||
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
|
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
|
||||||
|
|
||||||
@@ -232,9 +167,9 @@ IF(EQEMU_COMMANDS_LOGGING)
|
|||||||
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
|
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
|
||||||
ENDIF(EQEMU_COMMANDS_LOGGING)
|
ENDIF(EQEMU_COMMANDS_LOGGING)
|
||||||
|
|
||||||
IF(EQEMU_DISABLE_LOGSYS)
|
IF(EQEMU_LSPX)
|
||||||
ADD_DEFINITIONS(-DDISABLE_LOGSYS)
|
ADD_DEFINITIONS(-DLSPX=ON)
|
||||||
ENDIF(EQEMU_DISABLE_LOGSYS)
|
ENDIF(EQEMU_LSPX)
|
||||||
|
|
||||||
IF(EQEMU_ENABLE_BOTS)
|
IF(EQEMU_ENABLE_BOTS)
|
||||||
ADD_DEFINITIONS(-DBOTS)
|
ADD_DEFINITIONS(-DBOTS)
|
||||||
@@ -278,26 +213,20 @@ ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL})
|
|||||||
ADD_DEFINITIONS(-DINVERSEXY)
|
ADD_DEFINITIONS(-DINVERSEXY)
|
||||||
ADD_DEFINITIONS(-DFIELD_ITEMS)
|
ADD_DEFINITIONS(-DFIELD_ITEMS)
|
||||||
ADD_DEFINITIONS(-DMAP_DIR="${EQEMU_MAP_DIR}")
|
ADD_DEFINITIONS(-DMAP_DIR="${EQEMU_MAP_DIR}")
|
||||||
ADD_DEFINITIONS(-DLOG_LEVEL_STATUS=${EQEMU_LOG_LEVEL_STATUS})
|
|
||||||
ADD_DEFINITIONS(-DLOG_LEVEL_NORMAL=${EQEMU_LOG_LEVEL_NORMAL})
|
|
||||||
ADD_DEFINITIONS(-DLOG_LEVEL_ERROR=${EQEMU_LOG_LEVEL_ERROR})
|
|
||||||
ADD_DEFINITIONS(-DLOG_LEVEL_DEBUG=${EQEMU_LOG_LEVEL_DEBUG})
|
ADD_DEFINITIONS(-DLOG_LEVEL_DEBUG=${EQEMU_LOG_LEVEL_DEBUG})
|
||||||
ADD_DEFINITIONS(-DLOG_LEVEL_QUEST=${EQEMU_LOG_LEVEL_QUEST})
|
|
||||||
ADD_DEFINITIONS(-DLOG_LEVEL_COMMANDS=${EQEMU_LOG_LEVEL_COMMANDS})
|
|
||||||
ADD_DEFINITIONS(-DLOG_LEVEL_CRASH=${EQEMU_LOG_LEVEL_CRASH})
|
|
||||||
ADD_DEFINITIONS(-DGLM_FORCE_RADIANS)
|
ADD_DEFINITIONS(-DGLM_FORCE_RADIANS)
|
||||||
ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT)
|
ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT)
|
||||||
ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL)
|
ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL)
|
||||||
|
|
||||||
#Find everything we need
|
#Find everything we need
|
||||||
FIND_PACKAGE(ZLIB REQUIRED)
|
FIND_PACKAGE(ZLIB)
|
||||||
FIND_PACKAGE(MySQL REQUIRED)
|
FIND_PACKAGE(MySQL REQUIRED)
|
||||||
IF(EQEMU_BUILD_PERL)
|
IF(EQEMU_BUILD_PERL)
|
||||||
FIND_PACKAGE(PerlLibs REQUIRED)
|
FIND_PACKAGE(PerlLibs REQUIRED)
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
||||||
ENDIF(EQEMU_BUILD_PERL)
|
ENDIF(EQEMU_BUILD_PERL)
|
||||||
|
|
||||||
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} uv_a fmt RecastNavigation::Detour)
|
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} uv_a fmt RecastNavigation::Detour)
|
||||||
|
|
||||||
FIND_PACKAGE(Sodium REQUIRED)
|
FIND_PACKAGE(Sodium REQUIRED)
|
||||||
IF(SODIUM_FOUND)
|
IF(SODIUM_FOUND)
|
||||||
@@ -309,6 +238,23 @@ IF(SODIUM_FOUND)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF(ZLIB_FOUND)
|
||||||
|
OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." OFF)
|
||||||
|
|
||||||
|
IF(EQEMU_BUILD_ZLIB)
|
||||||
|
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||||
|
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||||
|
ELSE()
|
||||||
|
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||||
|
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
|
||||||
|
ENDIF()
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
|
||||||
|
SET(EQEMU_BUILD_ZLIB ON)
|
||||||
|
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||||
|
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv")
|
SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
@@ -338,7 +284,6 @@ IF(EQEMU_BUILD_LUA)
|
|||||||
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
||||||
ENDIF(EQEMU_BUILD_LUA)
|
ENDIF(EQEMU_BUILD_LUA)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
|
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
|
||||||
@@ -349,6 +294,7 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigat
|
|||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourCrowd/Include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourCrowd/Include")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourTileCache/Include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourTileCache/Include")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
|
||||||
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
|
||||||
|
|
||||||
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
||||||
ADD_SUBDIRECTORY(common)
|
ADD_SUBDIRECTORY(common)
|
||||||
@@ -360,6 +306,12 @@ IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_H
|
|||||||
SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests")
|
SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests")
|
||||||
SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples")
|
SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples")
|
||||||
ADD_SUBDIRECTORY(submodules/recastnavigation)
|
ADD_SUBDIRECTORY(submodules/recastnavigation)
|
||||||
|
|
||||||
|
IF(EQEMU_BUILD_ZLIB)
|
||||||
|
SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API")
|
||||||
|
SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries")
|
||||||
|
ADD_SUBDIRECTORY(libs/zlibng)
|
||||||
|
ENDIF()
|
||||||
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
||||||
IF(EQEMU_BUILD_SERVER)
|
IF(EQEMU_BUILD_SERVER)
|
||||||
ADD_SUBDIRECTORY(shared_memory)
|
ADD_SUBDIRECTORY(shared_memory)
|
||||||
|
|||||||
@@ -70,3 +70,9 @@ forum, although pull requests will be much quicker and easier on all parties.
|
|||||||
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
||||||
* CPPUnit - GLP StringUtilities - Apache
|
* CPPUnit - GLP StringUtilities - Apache
|
||||||
* LUA - MIT
|
* LUA - MIT
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
||||||
|
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
||||||
|
</a>
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Security Policy - Reporting Vulnerabilities
|
||||||
|
|
||||||
|
When reporting active hacks, exploits and other vulnerabilities, please describe how to reproduce said report and if you can provide context into a possible solution
|
||||||
+558
-478
File diff suppressed because it is too large
Load Diff
@@ -39,20 +39,19 @@ int main(int argc, char **argv) {
|
|||||||
LogSys.LoadLogSettingsDefaults();
|
LogSys.LoadLogSettingsDefaults();
|
||||||
set_exception_handler();
|
set_exception_handler();
|
||||||
|
|
||||||
Log(Logs::General, Logs::Status, "Client Files Export Utility");
|
LogInfo("Client Files Export Utility");
|
||||||
if(!EQEmuConfig::LoadConfig()) {
|
if(!EQEmuConfig::LoadConfig()) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to load configuration file.");
|
LogError("Unable to load configuration file");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Config = EQEmuConfig::get();
|
auto Config = EQEmuConfig::get();
|
||||||
|
|
||||||
SharedDatabase database;
|
SharedDatabase database;
|
||||||
Log(Logs::General, Logs::Status, "Connecting to database...");
|
LogInfo("Connecting to database");
|
||||||
if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(),
|
if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(),
|
||||||
Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) {
|
Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a "
|
LogError("Unable to connect to the database, cannot continue without a database connection");
|
||||||
"database connection");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,11 +93,11 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExportSpells(SharedDatabase *db) {
|
void ExportSpells(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Exporting Spells...");
|
LogInfo("Exporting Spells");
|
||||||
|
|
||||||
FILE *f = fopen("export/spells_us.txt", "w");
|
FILE *f = fopen("export/spells_us.txt", "w");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open export/spells_us.txt to write, skipping.");
|
LogError("Unable to open export/spells_us.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,11 +164,11 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExportSkillCaps(SharedDatabase *db) {
|
void ExportSkillCaps(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Exporting Skill Caps...");
|
LogInfo("Exporting Skill Caps");
|
||||||
|
|
||||||
FILE *f = fopen("export/SkillCaps.txt", "w");
|
FILE *f = fopen("export/SkillCaps.txt", "w");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open export/SkillCaps.txt to write, skipping.");
|
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,11 +193,11 @@ void ExportSkillCaps(SharedDatabase *db) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExportBaseData(SharedDatabase *db) {
|
void ExportBaseData(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Exporting Base Data...");
|
LogInfo("Exporting Base Data");
|
||||||
|
|
||||||
FILE *f = fopen("export/BaseData.txt", "w");
|
FILE *f = fopen("export/BaseData.txt", "w");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open export/BaseData.txt to write, skipping.");
|
LogError("Unable to open export/BaseData.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,11 +224,11 @@ void ExportBaseData(SharedDatabase *db) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExportDBStrings(SharedDatabase *db) {
|
void ExportDBStrings(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Exporting DB Strings...");
|
LogInfo("Exporting DB Strings");
|
||||||
|
|
||||||
FILE *f = fopen("export/dbstr_us.txt", "w");
|
FILE *f = fopen("export/dbstr_us.txt", "w");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open export/dbstr_us.txt to write, skipping.");
|
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,19 +37,19 @@ int main(int argc, char **argv) {
|
|||||||
LogSys.LoadLogSettingsDefaults();
|
LogSys.LoadLogSettingsDefaults();
|
||||||
set_exception_handler();
|
set_exception_handler();
|
||||||
|
|
||||||
Log(Logs::General, Logs::Status, "Client Files Import Utility");
|
LogInfo("Client Files Import Utility");
|
||||||
if(!EQEmuConfig::LoadConfig()) {
|
if(!EQEmuConfig::LoadConfig()) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to load configuration file.");
|
LogError("Unable to load configuration file.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Config = EQEmuConfig::get();
|
auto Config = EQEmuConfig::get();
|
||||||
|
|
||||||
SharedDatabase database;
|
SharedDatabase database;
|
||||||
Log(Logs::General, Logs::Status, "Connecting to database...");
|
LogInfo("Connecting to database");
|
||||||
if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(),
|
if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(),
|
||||||
Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) {
|
Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a "
|
LogError("Unable to connect to the database, cannot continue without a "
|
||||||
"database connection");
|
"database connection");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -97,10 +97,10 @@ bool IsStringField(int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImportSpells(SharedDatabase *db) {
|
void ImportSpells(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Importing Spells...");
|
LogInfo("Importing Spells");
|
||||||
FILE *f = fopen("import/spells_us.txt", "r");
|
FILE *f = fopen("import/spells_us.txt", "r");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open import/spells_us.txt to read, skipping.");
|
LogError("Unable to open import/spells_us.txt to read, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,23 +173,23 @@ void ImportSpells(SharedDatabase *db) {
|
|||||||
|
|
||||||
spells_imported++;
|
spells_imported++;
|
||||||
if(spells_imported % 1000 == 0) {
|
if(spells_imported % 1000 == 0) {
|
||||||
Log(Logs::General, Logs::Status, "%d spells imported.", spells_imported);
|
LogInfo("[{}] spells imported", spells_imported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(spells_imported % 1000 != 0) {
|
if(spells_imported % 1000 != 0) {
|
||||||
Log(Logs::General, Logs::Status, "%d spells imported.", spells_imported);
|
LogInfo("[{}] spells imported", spells_imported);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportSkillCaps(SharedDatabase *db) {
|
void ImportSkillCaps(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Importing Skill Caps...");
|
LogInfo("Importing Skill Caps");
|
||||||
|
|
||||||
FILE *f = fopen("import/SkillCaps.txt", "r");
|
FILE *f = fopen("import/SkillCaps.txt", "r");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open import/SkillCaps.txt to read, skipping.");
|
LogError("Unable to open import/SkillCaps.txt to read, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,11 +220,11 @@ void ImportSkillCaps(SharedDatabase *db) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImportBaseData(SharedDatabase *db) {
|
void ImportBaseData(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Importing Base Data...");
|
LogInfo("Importing Base Data");
|
||||||
|
|
||||||
FILE *f = fopen("import/BaseData.txt", "r");
|
FILE *f = fopen("import/BaseData.txt", "r");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open import/BaseData.txt to read, skipping.");
|
LogError("Unable to open import/BaseData.txt to read, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,11 +265,11 @@ void ImportBaseData(SharedDatabase *db) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImportDBStrings(SharedDatabase *db) {
|
void ImportDBStrings(SharedDatabase *db) {
|
||||||
Log(Logs::General, Logs::Status, "Importing DB Strings...");
|
LogInfo("Importing DB Strings");
|
||||||
|
|
||||||
FILE *f = fopen("import/dbstr_us.txt", "r");
|
FILE *f = fopen("import/dbstr_us.txt", "r");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
Log(Logs::General, Logs::Error, "Unable to open import/dbstr_us.txt to read, skipping.");
|
LogError("Unable to open import/dbstr_us.txt to read, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-23
@@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
|||||||
SET(common_sources
|
SET(common_sources
|
||||||
base_packet.cpp
|
base_packet.cpp
|
||||||
classes.cpp
|
classes.cpp
|
||||||
|
cli/eqemu_command_handler.cpp
|
||||||
compression.cpp
|
compression.cpp
|
||||||
condition.cpp
|
condition.cpp
|
||||||
crash.cpp
|
crash.cpp
|
||||||
@@ -35,6 +36,7 @@ SET(common_sources
|
|||||||
inventory_profile.cpp
|
inventory_profile.cpp
|
||||||
inventory_slot.cpp
|
inventory_slot.cpp
|
||||||
ipc_mutex.cpp
|
ipc_mutex.cpp
|
||||||
|
ip_util.cpp
|
||||||
item_data.cpp
|
item_data.cpp
|
||||||
item_instance.cpp
|
item_instance.cpp
|
||||||
json_config.cpp
|
json_config.cpp
|
||||||
@@ -71,7 +73,6 @@ SET(common_sources
|
|||||||
textures.cpp
|
textures.cpp
|
||||||
timer.cpp
|
timer.cpp
|
||||||
unix.cpp
|
unix.cpp
|
||||||
xml_parser.cpp
|
|
||||||
platform.cpp
|
platform.cpp
|
||||||
json/jsoncpp.cpp
|
json/jsoncpp.cpp
|
||||||
net/console_server.cpp
|
net/console_server.cpp
|
||||||
@@ -86,6 +87,8 @@ SET(common_sources
|
|||||||
net/servertalk_server_connection.cpp
|
net/servertalk_server_connection.cpp
|
||||||
net/tcp_connection.cpp
|
net/tcp_connection.cpp
|
||||||
net/tcp_server.cpp
|
net/tcp_server.cpp
|
||||||
|
net/websocket_server.cpp
|
||||||
|
net/websocket_server_connection.cpp
|
||||||
patches/patches.cpp
|
patches/patches.cpp
|
||||||
patches/sod.cpp
|
patches/sod.cpp
|
||||||
patches/sod_limits.cpp
|
patches/sod_limits.cpp
|
||||||
@@ -100,13 +103,8 @@ SET(common_sources
|
|||||||
patches/uf.cpp
|
patches/uf.cpp
|
||||||
patches/uf_limits.cpp
|
patches/uf_limits.cpp
|
||||||
StackWalker/StackWalker.cpp
|
StackWalker/StackWalker.cpp
|
||||||
tinyxml/tinystr.cpp
|
|
||||||
tinyxml/tinyxml.cpp
|
|
||||||
tinyxml/tinyxmlerror.cpp
|
|
||||||
tinyxml/tinyxmlparser.cpp
|
|
||||||
util/directory.cpp
|
util/directory.cpp
|
||||||
util/uuid.cpp
|
util/uuid.cpp)
|
||||||
)
|
|
||||||
|
|
||||||
SET(common_headers
|
SET(common_headers
|
||||||
any.h
|
any.h
|
||||||
@@ -119,6 +117,9 @@ SET(common_headers
|
|||||||
crash.h
|
crash.h
|
||||||
crc16.h
|
crc16.h
|
||||||
crc32.h
|
crc32.h
|
||||||
|
cli/argh.h
|
||||||
|
cli/eqemu_command_handler.h
|
||||||
|
cli/terminal_color.hpp
|
||||||
data_verification.h
|
data_verification.h
|
||||||
database.h
|
database.h
|
||||||
dbcore.h
|
dbcore.h
|
||||||
@@ -136,7 +137,7 @@ SET(common_headers
|
|||||||
eqemu_config.h
|
eqemu_config.h
|
||||||
eqemu_config_elements.h
|
eqemu_config_elements.h
|
||||||
eqemu_logsys.h
|
eqemu_logsys.h
|
||||||
eqemu_logsys_fmt.h
|
eqemu_logsys_log_aliases.h
|
||||||
eq_limits.h
|
eq_limits.h
|
||||||
eq_packet.h
|
eq_packet.h
|
||||||
eq_stream_ident.h
|
eq_stream_ident.h
|
||||||
@@ -154,9 +155,11 @@ SET(common_headers
|
|||||||
global_define.h
|
global_define.h
|
||||||
guild_base.h
|
guild_base.h
|
||||||
guilds.h
|
guilds.h
|
||||||
|
http/httplib.h
|
||||||
inventory_profile.h
|
inventory_profile.h
|
||||||
inventory_slot.h
|
inventory_slot.h
|
||||||
ipc_mutex.h
|
ipc_mutex.h
|
||||||
|
ip_util.h
|
||||||
item_data.h
|
item_data.h
|
||||||
item_fieldlist.h
|
item_fieldlist.h
|
||||||
item_instance.h
|
item_instance.h
|
||||||
@@ -207,7 +210,6 @@ SET(common_headers
|
|||||||
unix.h
|
unix.h
|
||||||
useperl.h
|
useperl.h
|
||||||
version.h
|
version.h
|
||||||
xml_parser.h
|
|
||||||
zone_numbers.h
|
zone_numbers.h
|
||||||
event/event_loop.h
|
event/event_loop.h
|
||||||
event/task.h
|
event/task.h
|
||||||
@@ -230,6 +232,8 @@ SET(common_headers
|
|||||||
net/servertalk_server_connection.h
|
net/servertalk_server_connection.h
|
||||||
net/tcp_connection.h
|
net/tcp_connection.h
|
||||||
net/tcp_server.h
|
net/tcp_server.h
|
||||||
|
net/websocket_server.h
|
||||||
|
net/websocket_server_connection.h
|
||||||
patches/patches.h
|
patches/patches.h
|
||||||
patches/sod.h
|
patches/sod.h
|
||||||
patches/sod_limits.h
|
patches/sod_limits.h
|
||||||
@@ -259,12 +263,9 @@ SET(common_headers
|
|||||||
patches/uf_ops.h
|
patches/uf_ops.h
|
||||||
patches/uf_structs.h
|
patches/uf_structs.h
|
||||||
StackWalker/StackWalker.h
|
StackWalker/StackWalker.h
|
||||||
tinyxml/tinystr.h
|
|
||||||
tinyxml/tinyxml.h
|
|
||||||
util/memory_stream.h
|
util/memory_stream.h
|
||||||
util/directory.h
|
util/directory.h
|
||||||
util/uuid.h
|
util/uuid.h)
|
||||||
)
|
|
||||||
|
|
||||||
SOURCE_GROUP(Event FILES
|
SOURCE_GROUP(Event FILES
|
||||||
event/event_loop.h
|
event/event_loop.h
|
||||||
@@ -309,6 +310,10 @@ SOURCE_GROUP(Net FILES
|
|||||||
net/tcp_connection.h
|
net/tcp_connection.h
|
||||||
net/tcp_server.cpp
|
net/tcp_server.cpp
|
||||||
net/tcp_server.h
|
net/tcp_server.h
|
||||||
|
net/websocket_server.cpp
|
||||||
|
net/websocket_server.h
|
||||||
|
net/websocket_server_connection.cpp
|
||||||
|
net/websocket_server_connection.h
|
||||||
)
|
)
|
||||||
|
|
||||||
SOURCE_GROUP(Patches FILES
|
SOURCE_GROUP(Patches FILES
|
||||||
@@ -360,15 +365,6 @@ SOURCE_GROUP(StackWalker FILES
|
|||||||
StackWalker/StackWalker.cpp
|
StackWalker/StackWalker.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
SOURCE_GROUP(TinyXML FILES
|
|
||||||
tinyxml/tinystr.h
|
|
||||||
tinyxml/tinyxml.h
|
|
||||||
tinyxml/tinystr.cpp
|
|
||||||
tinyxml/tinyxml.cpp
|
|
||||||
tinyxml/tinyxmlerror.cpp
|
|
||||||
tinyxml/tinyxmlparser.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
SOURCE_GROUP(Util FILES
|
SOURCE_GROUP(Util FILES
|
||||||
util/memory_stream.h
|
util/memory_stream.h
|
||||||
util/directory.cpp
|
util/directory.cpp
|
||||||
@@ -377,7 +373,7 @@ SOURCE_GROUP(Util FILES
|
|||||||
util/uuid.h
|
util/uuid.h
|
||||||
)
|
)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(Patches SocketLib StackWalker TinyXML)
|
INCLUDE_DIRECTORIES(Patches SocketLib StackWalker)
|
||||||
|
|
||||||
ADD_LIBRARY(common ${common_sources} ${common_headers})
|
ADD_LIBRARY(common ${common_sources} ${common_headers})
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ public:
|
|||||||
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
|
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
|
||||||
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
|
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
|
||||||
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
|
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
|
||||||
|
void ReadString(std::string &str) { str = reinterpret_cast<char *>(pBuffer + _rpos); _rpos += str.length() + 1; }
|
||||||
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
|
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
|
||||||
|
|
||||||
uint32 GetWritePosition() { return _wpos; }
|
uint32 GetWritePosition() { return _wpos; }
|
||||||
|
|||||||
@@ -0,0 +1,434 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace argh
|
||||||
|
{
|
||||||
|
// Terminology:
|
||||||
|
// A command line is composed of 2 types of args:
|
||||||
|
// 1. Positional args, i.e. free standing values
|
||||||
|
// 2. Options: args beginning with '-'. We identify two kinds:
|
||||||
|
// 2.1: Flags: boolean options => (exist ? true : false)
|
||||||
|
// 2.2: Parameters: a name followed by a non-option value
|
||||||
|
|
||||||
|
#if !defined(__GNUC__) || (__GNUC__ >= 5)
|
||||||
|
using string_stream = std::istringstream;
|
||||||
|
#else
|
||||||
|
// Until GCC 5, istringstream did not have a move constructor.
|
||||||
|
// stringstream_proxy is used instead, as a workaround.
|
||||||
|
class stringstream_proxy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
stringstream_proxy() = default;
|
||||||
|
|
||||||
|
// Construct with a value.
|
||||||
|
stringstream_proxy(std::string const& value) :
|
||||||
|
stream_(value)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Copy constructor.
|
||||||
|
stringstream_proxy(const stringstream_proxy& other) :
|
||||||
|
stream_(other.stream_.str())
|
||||||
|
{
|
||||||
|
stream_.setstate(other.stream_.rdstate());
|
||||||
|
}
|
||||||
|
|
||||||
|
void setstate(std::ios_base::iostate state) { stream_.setstate(state); }
|
||||||
|
|
||||||
|
// Stream out the value of the parameter.
|
||||||
|
// If the conversion was not possible, the stream will enter the fail state,
|
||||||
|
// and operator bool will return false.
|
||||||
|
template<typename T>
|
||||||
|
stringstream_proxy& operator >> (T& thing)
|
||||||
|
{
|
||||||
|
stream_ >> thing;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get the string value.
|
||||||
|
std::string str() const { return stream_.str(); }
|
||||||
|
|
||||||
|
std::stringbuf* rdbuf() const { return stream_.rdbuf(); }
|
||||||
|
|
||||||
|
// Check the state of the stream.
|
||||||
|
// False when the most recent stream operation failed
|
||||||
|
operator bool() const { return !!stream_; }
|
||||||
|
|
||||||
|
~stringstream_proxy() = default;
|
||||||
|
private:
|
||||||
|
std::istringstream stream_;
|
||||||
|
};
|
||||||
|
using string_stream = stringstream_proxy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Mode { PREFER_FLAG_FOR_UNREG_OPTION = 1 << 0,
|
||||||
|
PREFER_PARAM_FOR_UNREG_OPTION = 1 << 1,
|
||||||
|
NO_SPLIT_ON_EQUALSIGN = 1 << 2,
|
||||||
|
SINGLE_DASH_IS_MULTIFLAG = 1 << 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
parser() = default;
|
||||||
|
|
||||||
|
parser(std::initializer_list<char const* const> pre_reg_names)
|
||||||
|
{ add_params(pre_reg_names); }
|
||||||
|
|
||||||
|
parser(const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION)
|
||||||
|
{ parse(argv, mode); }
|
||||||
|
|
||||||
|
parser(int argc, const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION)
|
||||||
|
{ parse(argc, argv, mode); }
|
||||||
|
|
||||||
|
void add_param(std::string const& name);
|
||||||
|
void add_params(std::initializer_list<char const* const> init_list);
|
||||||
|
|
||||||
|
void parse(const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION);
|
||||||
|
void parse(int argc, const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION);
|
||||||
|
|
||||||
|
std::multiset<std::string> const& flags() const { return flags_; }
|
||||||
|
std::map<std::string, std::string> const& params() const { return params_; }
|
||||||
|
std::vector<std::string> const& pos_args() const { return pos_args_; }
|
||||||
|
|
||||||
|
// begin() and end() for using range-for over positional args.
|
||||||
|
std::vector<std::string>::const_iterator begin() const { return pos_args_.cbegin(); }
|
||||||
|
std::vector<std::string>::const_iterator end() const { return pos_args_.cend(); }
|
||||||
|
size_t size() const { return pos_args_.size(); }
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Accessors
|
||||||
|
|
||||||
|
// flag (boolean) accessors: return true if the flag appeared, otherwise false.
|
||||||
|
bool operator[](std::string const& name) const;
|
||||||
|
|
||||||
|
// multiple flag (boolean) accessors: return true if at least one of the flag appeared, otherwise false.
|
||||||
|
bool operator[](std::initializer_list<char const* const> init_list) const;
|
||||||
|
|
||||||
|
// returns positional arg string by order. Like argv[] but without the options
|
||||||
|
std::string const& operator[](size_t ind) const;
|
||||||
|
|
||||||
|
// returns a std::istream that can be used to convert a positional arg to a typed value.
|
||||||
|
string_stream operator()(size_t ind) const;
|
||||||
|
|
||||||
|
// same as above, but with a default value in case the arg is missing (index out of range).
|
||||||
|
template<typename T>
|
||||||
|
string_stream operator()(size_t ind, T&& def_val) const;
|
||||||
|
|
||||||
|
// parameter accessors, give a name get an std::istream that can be used to convert to a typed value.
|
||||||
|
// call .str() on result to get as string
|
||||||
|
string_stream operator()(std::string const& name) const;
|
||||||
|
|
||||||
|
// accessor for a parameter with multiple names, give a list of names, get an std::istream that can be used to convert to a typed value.
|
||||||
|
// call .str() on result to get as string
|
||||||
|
// returns the first value in the list to be found.
|
||||||
|
string_stream operator()(std::initializer_list<char const* const> init_list) const;
|
||||||
|
|
||||||
|
// same as above, but with a default value in case the param was missing.
|
||||||
|
// Non-string def_val types must have an operator<<() (output stream operator)
|
||||||
|
// If T only has an input stream operator, pass the string version of the type as in "3" instead of 3.
|
||||||
|
template<typename T>
|
||||||
|
string_stream operator()(std::string const& name, T&& def_val) const;
|
||||||
|
|
||||||
|
// same as above but for a list of names. returns the first value to be found.
|
||||||
|
template<typename T>
|
||||||
|
string_stream operator()(std::initializer_list<char const* const> init_list, T&& def_val) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
string_stream bad_stream() const;
|
||||||
|
std::string trim_leading_dashes(std::string const& name) const;
|
||||||
|
bool is_number(std::string const& arg) const;
|
||||||
|
bool is_option(std::string const& arg) const;
|
||||||
|
bool got_flag(std::string const& name) const;
|
||||||
|
bool is_param(std::string const& name) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> args_;
|
||||||
|
std::map<std::string, std::string> params_;
|
||||||
|
std::vector<std::string> pos_args_;
|
||||||
|
std::multiset<std::string> flags_;
|
||||||
|
std::set<std::string> registeredParams_;
|
||||||
|
std::string empty_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::parse(const char * const argv[], int mode)
|
||||||
|
{
|
||||||
|
int argc = 0;
|
||||||
|
for (auto argvp = argv; *argvp; ++argc, ++argvp);
|
||||||
|
parse(argc, argv, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::parse(int argc, const char* const argv[], int mode /*= PREFER_FLAG_FOR_UNREG_OPTION*/)
|
||||||
|
{
|
||||||
|
// convert to strings
|
||||||
|
args_.resize(argc);
|
||||||
|
std::transform(argv, argv + argc, args_.begin(), [](const char* const arg) { return arg; });
|
||||||
|
|
||||||
|
// parse line
|
||||||
|
for (auto i = 0u; i < args_.size(); ++i)
|
||||||
|
{
|
||||||
|
if (!is_option(args_[i]))
|
||||||
|
{
|
||||||
|
pos_args_.emplace_back(args_[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto name = trim_leading_dashes(args_[i]);
|
||||||
|
|
||||||
|
if (!(mode & NO_SPLIT_ON_EQUALSIGN))
|
||||||
|
{
|
||||||
|
auto equalPos = name.find('=');
|
||||||
|
if (equalPos != std::string::npos)
|
||||||
|
{
|
||||||
|
params_.insert({ name.substr(0, equalPos), name.substr(equalPos + 1) });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the option is unregistered and should be a multi-flag
|
||||||
|
if (1 == (args_[i].size() - name.size()) && // single dash
|
||||||
|
argh::parser::SINGLE_DASH_IS_MULTIFLAG & mode && // multi-flag mode
|
||||||
|
!is_param(name)) // unregistered
|
||||||
|
{
|
||||||
|
std::string keep_param;
|
||||||
|
|
||||||
|
if (!name.empty() && is_param(std::string(1ul, name.back()))) // last char is param
|
||||||
|
{
|
||||||
|
keep_param += name.back();
|
||||||
|
name.resize(name.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& c : name)
|
||||||
|
{
|
||||||
|
flags_.emplace(std::string{ c });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keep_param.empty())
|
||||||
|
{
|
||||||
|
name = keep_param;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue; // do not consider other options for this arg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// any potential option will get as its value the next arg, unless that arg is an option too
|
||||||
|
// in that case it will be determined a flag.
|
||||||
|
if (i == args_.size() - 1 || is_option(args_[i + 1]))
|
||||||
|
{
|
||||||
|
flags_.emplace(name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if 'name' is a pre-registered option, then the next arg cannot be a free parameter to it is skipped
|
||||||
|
// otherwise we have 2 modes:
|
||||||
|
// PREFER_FLAG_FOR_UNREG_OPTION: a non-registered 'name' is determined a flag.
|
||||||
|
// The following value (the next arg) will be a free parameter.
|
||||||
|
//
|
||||||
|
// PREFER_PARAM_FOR_UNREG_OPTION: a non-registered 'name' is determined a parameter, the next arg
|
||||||
|
// will be the value of that option.
|
||||||
|
|
||||||
|
assert(!(mode & argh::parser::PREFER_FLAG_FOR_UNREG_OPTION)
|
||||||
|
|| !(mode & argh::parser::PREFER_PARAM_FOR_UNREG_OPTION));
|
||||||
|
|
||||||
|
bool preferParam = mode & argh::parser::PREFER_PARAM_FOR_UNREG_OPTION;
|
||||||
|
|
||||||
|
if (is_param(name) || preferParam)
|
||||||
|
{
|
||||||
|
params_.insert({ name, args_[i + 1] });
|
||||||
|
++i; // skip next value, it is not a free parameter
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flags_.emplace(name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline string_stream parser::bad_stream() const
|
||||||
|
{
|
||||||
|
string_stream bad;
|
||||||
|
bad.setstate(std::ios_base::failbit);
|
||||||
|
return bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::is_number(std::string const& arg) const
|
||||||
|
{
|
||||||
|
// inefficient but simple way to determine if a string is a number (which can start with a '-')
|
||||||
|
std::istringstream istr(arg);
|
||||||
|
double number;
|
||||||
|
istr >> number;
|
||||||
|
return !(istr.fail() || istr.bad());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::is_option(std::string const& arg) const
|
||||||
|
{
|
||||||
|
assert(0 != arg.size());
|
||||||
|
if (is_number(arg))
|
||||||
|
return false;
|
||||||
|
return '-' == arg[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline std::string parser::trim_leading_dashes(std::string const& name) const
|
||||||
|
{
|
||||||
|
auto pos = name.find_first_not_of('-');
|
||||||
|
return std::string::npos != pos ? name.substr(pos) : name;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool argh::parser::got_flag(std::string const& name) const
|
||||||
|
{
|
||||||
|
return flags_.end() != flags_.find(trim_leading_dashes(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool argh::parser::is_param(std::string const& name) const
|
||||||
|
{
|
||||||
|
return registeredParams_.count(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::operator[](std::string const& name) const
|
||||||
|
{
|
||||||
|
return got_flag(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::operator[](std::initializer_list<char const* const> init_list) const
|
||||||
|
{
|
||||||
|
return std::any_of(init_list.begin(), init_list.end(), [&](char const* const name) { return got_flag(name); });
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline std::string const& parser::operator[](size_t ind) const
|
||||||
|
{
|
||||||
|
if (ind < pos_args_.size())
|
||||||
|
return pos_args_[ind];
|
||||||
|
return empty_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline string_stream parser::operator()(std::string const& name) const
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
return bad_stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline string_stream parser::operator()(std::initializer_list<char const* const> init_list) const
|
||||||
|
{
|
||||||
|
for (auto& name : init_list)
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
}
|
||||||
|
return bad_stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
string_stream parser::operator()(std::string const& name, T&& def_val) const
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
|
||||||
|
std::ostringstream ostr;
|
||||||
|
ostr.precision(std::numeric_limits<long double>::max_digits10);
|
||||||
|
ostr << def_val;
|
||||||
|
return string_stream(ostr.str()); // use default
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// same as above but for a list of names. returns the first value to be found.
|
||||||
|
template<typename T>
|
||||||
|
string_stream parser::operator()(std::initializer_list<char const* const> init_list, T&& def_val) const
|
||||||
|
{
|
||||||
|
for (auto& name : init_list)
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
}
|
||||||
|
std::ostringstream ostr;
|
||||||
|
ostr.precision(std::numeric_limits<long double>::max_digits10);
|
||||||
|
ostr << def_val;
|
||||||
|
return string_stream(ostr.str()); // use default
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline string_stream parser::operator()(size_t ind) const
|
||||||
|
{
|
||||||
|
if (pos_args_.size() <= ind)
|
||||||
|
return bad_stream();
|
||||||
|
|
||||||
|
return string_stream(pos_args_[ind]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
string_stream parser::operator()(size_t ind, T&& def_val) const
|
||||||
|
{
|
||||||
|
if (pos_args_.size() <= ind)
|
||||||
|
{
|
||||||
|
std::ostringstream ostr;
|
||||||
|
ostr.precision(std::numeric_limits<long double>::max_digits10);
|
||||||
|
ostr << def_val;
|
||||||
|
return string_stream(ostr.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return string_stream(pos_args_[ind]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::add_param(std::string const& name)
|
||||||
|
{
|
||||||
|
registeredParams_.insert(trim_leading_dashes(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::add_params(std::initializer_list<char const* const> init_list)
|
||||||
|
{
|
||||||
|
for (auto& name : init_list)
|
||||||
|
registeredParams_.insert(trim_leading_dashes(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
/**
|
||||||
|
* 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 <fmt/format.h>
|
||||||
|
#include "eqemu_command_handler.h"
|
||||||
|
#include "terminal_color.hpp"
|
||||||
|
#include "../platform.h"
|
||||||
|
|
||||||
|
namespace EQEmuCommand {
|
||||||
|
|
||||||
|
std::map<std::string, void (*)(
|
||||||
|
int argc,
|
||||||
|
char **argv,
|
||||||
|
argh::parser &cmd,
|
||||||
|
std::string &description
|
||||||
|
)> function_map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cmd
|
||||||
|
*/
|
||||||
|
void DisplayDebug(argh::parser &cmd)
|
||||||
|
{
|
||||||
|
if (cmd[{"-d", "--debug"}]) {
|
||||||
|
std::cout << "Positional args:\n";
|
||||||
|
for (auto &pos_arg : cmd)
|
||||||
|
std::cout << '\t' << pos_arg << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Positional args:\n";
|
||||||
|
for (auto &pos_arg : cmd.pos_args())
|
||||||
|
std::cout << '\t' << pos_arg << std::endl;
|
||||||
|
|
||||||
|
std::cout << "\nFlags:\n";
|
||||||
|
for (auto &flag : cmd.flags())
|
||||||
|
std::cout << '\t' << flag << std::endl;
|
||||||
|
|
||||||
|
std::cout << "\nParameters:\n";
|
||||||
|
for (auto ¶m : cmd.params())
|
||||||
|
std::cout << '\t' << param.first << " : " << param.second << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param arguments
|
||||||
|
* @param options
|
||||||
|
* @param cmd
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
*/
|
||||||
|
void ValidateCmdInput(
|
||||||
|
std::vector<std::string> &arguments,
|
||||||
|
std::vector<std::string> &options,
|
||||||
|
argh::parser &cmd,
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool arguments_filled = true;
|
||||||
|
|
||||||
|
for (auto &arg : arguments) {
|
||||||
|
if (cmd(arg).str().empty()) {
|
||||||
|
arguments_filled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arguments_filled || argc == 2) {
|
||||||
|
std::string arguments_string;
|
||||||
|
for (auto &arg : arguments) {
|
||||||
|
arguments_string += " " + arg + "=*\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string options_string;
|
||||||
|
for (auto &opt : options) {
|
||||||
|
options_string += " " + opt + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << fmt::format(
|
||||||
|
"Command\n\n{0} \n\nArgs\n{1}\nOptions\n{2}",
|
||||||
|
argv[1],
|
||||||
|
arguments_string,
|
||||||
|
options_string
|
||||||
|
) << std::endl;
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in_function_map
|
||||||
|
* @param cmd
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
*/
|
||||||
|
void HandleMenu(
|
||||||
|
std::map<std::string, void (*)(
|
||||||
|
int argc,
|
||||||
|
char **argv,
|
||||||
|
argh::parser &cmd,
|
||||||
|
std::string &description
|
||||||
|
)> &in_function_map,
|
||||||
|
argh::parser &cmd,
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string description;
|
||||||
|
bool ran_command = false;
|
||||||
|
for (auto &it: in_function_map) {
|
||||||
|
if (it.first == argv[1]) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "> " << termcolor::cyan << "Executing CLI Command" << termcolor::reset << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
(it.second)(argc, argv, cmd, description);
|
||||||
|
ran_command = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd[{"-h", "--help"}]) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout <<
|
||||||
|
"> " <<
|
||||||
|
termcolor::yellow <<
|
||||||
|
"EQEmulator [" + GetPlatformName() + "] CLI Menu" <<
|
||||||
|
termcolor::reset
|
||||||
|
<< std::endl
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get max command length for padding length
|
||||||
|
*/
|
||||||
|
int max_command_length = 0;
|
||||||
|
|
||||||
|
for (auto &it: in_function_map) {
|
||||||
|
std::stringstream command;
|
||||||
|
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
|
||||||
|
if (command.str().length() > max_command_length) {
|
||||||
|
max_command_length = command.str().length() + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display command menu
|
||||||
|
*/
|
||||||
|
std::string command_section;
|
||||||
|
for (auto &it: in_function_map) {
|
||||||
|
description = "";
|
||||||
|
|
||||||
|
(it.second)(argc, argv, cmd, description);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print section header
|
||||||
|
*/
|
||||||
|
std::string command_prefix = it.first.substr(0, it.first.find(":"));
|
||||||
|
if (command_section != command_prefix) {
|
||||||
|
command_section = command_prefix;
|
||||||
|
std::cout << termcolor::reset << command_prefix << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print commands
|
||||||
|
*/
|
||||||
|
std::stringstream command;
|
||||||
|
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
|
||||||
|
printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
else if (!ran_command) {
|
||||||
|
std::cerr << "Unknown command [" << argv[1] << "] ! Try --help" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,15 +16,60 @@
|
|||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef EQEMU_EQEMU_COMMAND_HANDLER_H
|
||||||
|
#define EQEMU_EQEMU_COMMAND_HANDLER_H
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include "argh.h"
|
||||||
|
|
||||||
template <typename... Args>
|
namespace EQEmuCommand {
|
||||||
void OutF(EQEmuLogSys &ls, Logs::DebugLevel debug_level, uint16 log_category, const char *fmt, const Args&... args)
|
|
||||||
{
|
extern std::map<std::string, void (*)(
|
||||||
std::string log_str = fmt::format(fmt, args...);
|
int argc,
|
||||||
ls.Out(debug_level, log_category, log_str);
|
char **argv,
|
||||||
}
|
argh::parser &cmd,
|
||||||
|
std::string &description
|
||||||
|
)> function_map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param arguments
|
||||||
|
* @param options
|
||||||
|
* @param cmd
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
*/
|
||||||
|
void ValidateCmdInput(
|
||||||
|
std::vector<std::string> &arguments,
|
||||||
|
std::vector<std::string> &options,
|
||||||
|
argh::parser &cmd,
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cmd
|
||||||
|
*/
|
||||||
|
void DisplayDebug(argh::parser &cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in_function_map
|
||||||
|
* @param cmd
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
*/
|
||||||
|
void HandleMenu(
|
||||||
|
std::map<std::string, void (*)(
|
||||||
|
int argc,
|
||||||
|
char **argv,
|
||||||
|
argh::parser &cmd,
|
||||||
|
std::string &description
|
||||||
|
)> &in_function_map,
|
||||||
|
argh::parser &cmd,
|
||||||
|
int argc,
|
||||||
|
char **argv
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EQEMU_EQEMU_COMMAND_HANDLER_H
|
||||||
@@ -0,0 +1,557 @@
|
|||||||
|
//!
|
||||||
|
//! termcolor
|
||||||
|
//! ~~~~~~~~~
|
||||||
|
//!
|
||||||
|
//! termcolor is a header-only c++ library for printing colored messages
|
||||||
|
//! to the terminal. Written just for fun with a help of the Force.
|
||||||
|
//!
|
||||||
|
//! :copyright: (c) 2013 by Ihor Kalnytskyi
|
||||||
|
//! :license: BSD, see LICENSE for details
|
||||||
|
//!
|
||||||
|
|
||||||
|
#ifndef TERMCOLOR_HPP_
|
||||||
|
#define TERMCOLOR_HPP_
|
||||||
|
|
||||||
|
// the following snippet of code detects the current OS and
|
||||||
|
// defines the appropriate macro that is used to wrap some
|
||||||
|
// platform specific things
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
# define TERMCOLOR_OS_WINDOWS
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
# define TERMCOLOR_OS_MACOS
|
||||||
|
#elif defined(__unix__) || defined(__unix)
|
||||||
|
# define TERMCOLOR_OS_LINUX
|
||||||
|
#else
|
||||||
|
# error unsupported platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// This headers provides the `isatty()`/`fileno()` functions,
|
||||||
|
// which are used for testing whether a standart stream refers
|
||||||
|
// to the terminal. As for Windows, we also need WinApi funcs
|
||||||
|
// for changing colors attributes of the terminal.
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
# include <unistd.h>
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
# include <io.h>
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace termcolor
|
||||||
|
{
|
||||||
|
// Forward declaration of the `_internal` namespace.
|
||||||
|
// All comments are below.
|
||||||
|
namespace _internal
|
||||||
|
{
|
||||||
|
// An index to be used to access a private storage of I/O streams. See
|
||||||
|
// colorize / nocolorize I/O manipulators for details.
|
||||||
|
static int colorize_index = std::ios_base::xalloc();
|
||||||
|
|
||||||
|
inline FILE* get_standard_stream(const std::ostream& stream);
|
||||||
|
inline bool is_colorized(std::ostream& stream);
|
||||||
|
inline bool is_atty(const std::ostream& stream);
|
||||||
|
|
||||||
|
#if defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
inline void win_change_attributes(std::ostream& stream, int foreground, int background=-1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& colorize(std::ostream& stream)
|
||||||
|
{
|
||||||
|
stream.iword(_internal::colorize_index) = 1L;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& nocolorize(std::ostream& stream)
|
||||||
|
{
|
||||||
|
stream.iword(_internal::colorize_index) = 0L;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& reset(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;00m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1, -1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& bold(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;1m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& dark(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;2m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& underline(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;4m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& blink(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;5m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& reverse(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;7m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& concealed(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;8m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& grey(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;30m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
0 // grey (black)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& red(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;31m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
FOREGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& green(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;32m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
FOREGROUND_GREEN
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& yellow(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;33m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
FOREGROUND_GREEN | FOREGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& blue(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;34m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
FOREGROUND_BLUE
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& magenta(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;35m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
FOREGROUND_BLUE | FOREGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& cyan(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;36m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
FOREGROUND_BLUE | FOREGROUND_GREEN
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& white(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;37m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream,
|
||||||
|
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_grey(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;40m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
0 // grey (black)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_red(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;41m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
BACKGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_green(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;42m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
BACKGROUND_GREEN
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_yellow(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;43m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
BACKGROUND_GREEN | BACKGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_blue(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;44m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
BACKGROUND_BLUE
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_magenta(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;45m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
BACKGROUND_BLUE | BACKGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_cyan(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;46m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
BACKGROUND_GREEN | BACKGROUND_BLUE
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::ostream& on_white(std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (_internal::is_colorized(stream))
|
||||||
|
{
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
stream << "\e[1;47m";
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
_internal::win_change_attributes(stream, -1,
|
||||||
|
BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//! Since C++ hasn't a way to hide something in the header from
|
||||||
|
//! the outer access, I have to introduce this namespace which
|
||||||
|
//! is used for internal purpose and should't be access from
|
||||||
|
//! the user code.
|
||||||
|
namespace _internal
|
||||||
|
{
|
||||||
|
//! Since C++ hasn't a true way to extract stream handler
|
||||||
|
//! from the a given `std::ostream` object, I have to write
|
||||||
|
//! this kind of hack.
|
||||||
|
inline
|
||||||
|
FILE* get_standard_stream(const std::ostream& stream)
|
||||||
|
{
|
||||||
|
if (&stream == &std::cout)
|
||||||
|
return stdout;
|
||||||
|
else if ((&stream == &std::cerr) || (&stream == &std::clog))
|
||||||
|
return stderr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Say whether a given stream should be colorized or not. It's always
|
||||||
|
// true for ATTY streams and may be true for streams marked with
|
||||||
|
// colorize flag.
|
||||||
|
inline
|
||||||
|
bool is_colorized(std::ostream& stream)
|
||||||
|
{
|
||||||
|
return is_atty(stream) || static_cast<bool>(stream.iword(colorize_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Test whether a given `std::ostream` object refers to
|
||||||
|
//! a terminal.
|
||||||
|
inline
|
||||||
|
bool is_atty(const std::ostream& stream)
|
||||||
|
{
|
||||||
|
FILE* std_stream = get_standard_stream(stream);
|
||||||
|
|
||||||
|
// Unfortunately, fileno() ends with segmentation fault
|
||||||
|
// if invalid file descriptor is passed. So we need to
|
||||||
|
// handle this case gracefully and assume it's not a tty
|
||||||
|
// if standard stream is not detected, and 0 is returned.
|
||||||
|
if (!std_stream)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||||
|
return ::isatty(fileno(std_stream));
|
||||||
|
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
return ::_isatty(_fileno(std_stream));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(TERMCOLOR_OS_WINDOWS)
|
||||||
|
//! Change Windows Terminal colors attribute. If some
|
||||||
|
//! parameter is `-1` then attribute won't changed.
|
||||||
|
inline void win_change_attributes(std::ostream& stream, int foreground, int background)
|
||||||
|
{
|
||||||
|
// yeah, i know.. it's ugly, it's windows.
|
||||||
|
static WORD defaultAttributes = 0;
|
||||||
|
|
||||||
|
// Windows doesn't have ANSI escape sequences and so we use special
|
||||||
|
// API to change Terminal output color. That means we can't
|
||||||
|
// manipulate colors by means of "std::stringstream" and hence
|
||||||
|
// should do nothing in this case.
|
||||||
|
if (!_internal::is_atty(stream))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get terminal handle
|
||||||
|
HANDLE hTerminal = INVALID_HANDLE_VALUE;
|
||||||
|
if (&stream == &std::cout)
|
||||||
|
hTerminal = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
else if (&stream == &std::cerr)
|
||||||
|
hTerminal = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
|
// save default terminal attributes if it unsaved
|
||||||
|
if (!defaultAttributes)
|
||||||
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||||
|
if (!GetConsoleScreenBufferInfo(hTerminal, &info))
|
||||||
|
return;
|
||||||
|
defaultAttributes = info.wAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore all default settings
|
||||||
|
if (foreground == -1 && background == -1)
|
||||||
|
{
|
||||||
|
SetConsoleTextAttribute(hTerminal, defaultAttributes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get current settings
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||||
|
if (!GetConsoleScreenBufferInfo(hTerminal, &info))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (foreground != -1)
|
||||||
|
{
|
||||||
|
info.wAttributes &= ~(info.wAttributes & 0x0F);
|
||||||
|
info.wAttributes |= static_cast<WORD>(foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (background != -1)
|
||||||
|
{
|
||||||
|
info.wAttributes &= ~(info.wAttributes & 0xF0);
|
||||||
|
info.wAttributes |= static_cast<WORD>(background);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetConsoleTextAttribute(hTerminal, info.wAttributes);
|
||||||
|
}
|
||||||
|
#endif // TERMCOLOR_OS_WINDOWS
|
||||||
|
|
||||||
|
} // namespace _internal
|
||||||
|
|
||||||
|
} // namespace termcolor
|
||||||
|
|
||||||
|
|
||||||
|
#undef TERMCOLOR_OS_WINDOWS
|
||||||
|
#undef TERMCOLOR_OS_MACOS
|
||||||
|
#undef TERMCOLOR_OS_LINUX
|
||||||
|
|
||||||
|
#endif // TERMCOLOR_HPP_
|
||||||
+54
-1
@@ -111,7 +111,60 @@ void set_exception_handler() {
|
|||||||
SetUnhandledExceptionFilter(windows_exception_handler);
|
SetUnhandledExceptionFilter(windows_exception_handler);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
|
||||||
|
void print_trace()
|
||||||
|
{
|
||||||
|
auto uid = geteuid();
|
||||||
|
|
||||||
|
std::string temp_output_file = "/tmp/dump-output";
|
||||||
|
|
||||||
|
char pid_buf[30];
|
||||||
|
sprintf(pid_buf, "%d", getpid());
|
||||||
|
char name_buf[512];
|
||||||
|
name_buf[readlink("/proc/self/exe", name_buf, 511)] = 0;
|
||||||
|
int child_pid = fork();
|
||||||
|
if (!child_pid) {
|
||||||
|
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||||
|
|
||||||
|
dup2(fd, 1); // redirect output to stderr
|
||||||
|
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
|
||||||
|
if (uid == 0) {
|
||||||
|
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
execlp("sudo", "gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
abort(); /* If gdb failed to start */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
waitpid(child_pid, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream input(temp_output_file);
|
||||||
|
for (std::string line; getline(input, line);) {
|
||||||
|
LogCrash("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::remove(temp_output_file.c_str());
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// crash is off or an unhandled platform
|
// crash is off or an unhandled platform
|
||||||
void set_exception_handler() {
|
void set_exception_handler()
|
||||||
|
{
|
||||||
|
signal(SIGABRT, reinterpret_cast<void (*)(int)>(print_trace));
|
||||||
|
signal(SIGFPE, reinterpret_cast<void (*)(int)>(print_trace));
|
||||||
|
signal(SIGFPE, reinterpret_cast<void (*)(int)>(print_trace));
|
||||||
|
signal(SIGSEGV, reinterpret_cast<void (*)(int)>(print_trace));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+36
-32
@@ -1,53 +1,57 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; version 2 of the License.
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
are required to give you total support for your newly bought product;
|
* are required to give you total support for your newly bought product;
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace EQEmu
|
namespace EQEmu {
|
||||||
{
|
template<typename T>
|
||||||
template <typename T>
|
T Clamp(const T &value, const T &lower, const T &upper)
|
||||||
T Clamp(const T& value, const T& lower, const T& upper) {
|
{
|
||||||
return std::max(lower, std::min(value, upper));
|
return std::max(lower, std::min(value, upper));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
T ClampLower(const T& value, const T& lower) {
|
T ClampLower(const T &value, const T &lower)
|
||||||
|
{
|
||||||
return std::max(lower, value);
|
return std::max(lower, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
T ClampUpper(const T& value, const T& upper) {
|
T ClampUpper(const T &value, const T &upper)
|
||||||
|
{
|
||||||
return std::min(value, upper);
|
return std::min(value, upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
bool ValueWithin(const T& value, const T& lower, const T& upper) {
|
bool ValueWithin(const T &value, const T &lower, const T &upper)
|
||||||
|
{
|
||||||
return value >= lower && value <= upper;
|
return value >= lower && value <= upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T2, typename T3>
|
template<typename T1, typename T2, typename T3>
|
||||||
bool ValueWithin(const T1& value, const T2& lower, const T3& upper) {
|
bool ValueWithin(const T1 &value, const T2 &lower, const T3 &upper)
|
||||||
return value >= (T1)lower && value <= (T1)upper;
|
{
|
||||||
|
return value >= (T1) lower && value <= (T1) upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /*EQEmu*/
|
} /*EQEmu*/
|
||||||
|
|
||||||
|
|||||||
+117
-78
@@ -64,11 +64,11 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c
|
|||||||
uint32 errnum= 0;
|
uint32 errnum= 0;
|
||||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||||
if (!Open(host, user, passwd, database, port, &errnum, errbuf)) {
|
if (!Open(host, user, passwd, database, port, &errnum, errbuf)) {
|
||||||
Log(Logs::General, Logs::Error, "Failed to connect to database: Error: %s", errbuf);
|
LogError("Failed to connect to database: Error: {}", errbuf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log(Logs::General, Logs::Status, "Using database '%s' at %s:%d", database, host,port);
|
LogInfo("Using database [{}] at [{}]:[{}]", database, host,port);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ Database::~Database()
|
|||||||
Return the account id or zero if no account matches.
|
Return the account id or zero if no account matches.
|
||||||
Zero will also be returned if there is a database error.
|
Zero will also be returned if there is a database error.
|
||||||
*/
|
*/
|
||||||
uint32 Database::CheckLogin(const char* name, const char* password, int16* oStatus) {
|
uint32 Database::CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus) {
|
||||||
|
|
||||||
if(strlen(name) >= 50 || strlen(password) >= 50)
|
if(strlen(name) >= 50 || strlen(password) >= 50)
|
||||||
return(0);
|
return(0);
|
||||||
@@ -97,9 +97,10 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat
|
|||||||
DoEscapeString(tmpUN, name, strlen(name));
|
DoEscapeString(tmpUN, name, strlen(name));
|
||||||
DoEscapeString(tmpPW, password, strlen(password));
|
DoEscapeString(tmpPW, password, strlen(password));
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND password is not null "
|
std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND ls_id='%s' AND password is not null "
|
||||||
"and length(password) > 0 and (password='%s' or password=MD5('%s'))",
|
"and length(password) > 0 and (password='%s' or password=MD5('%s'))",
|
||||||
tmpUN, tmpPW, tmpPW);
|
tmpUN, EscapeString(loginserver).c_str(), tmpPW, tmpPW);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
@@ -171,61 +172,87 @@ void Database::LoginIP(uint32 AccountID, const char* LoginIP) {
|
|||||||
QueryDatabase(query);
|
QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16 Database::CheckStatus(uint32 account_id) {
|
int16 Database::CheckStatus(uint32 account_id)
|
||||||
std::string query = StringFormat("SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`"
|
{
|
||||||
" FROM `account` WHERE `id` = %i", account_id);
|
std::string query = StringFormat(
|
||||||
|
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = %i",
|
||||||
|
account_id);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success())
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (results.RowCount() != 1)
|
if (results.RowCount() != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
int16 status = atoi(row[0]);
|
int16 status = atoi(row[0]);
|
||||||
int32 suspendeduntil = 0;
|
int32 date_diff = 0;
|
||||||
|
|
||||||
// MariaDB initalizes with NULL if unix_timestamp() is out of range
|
if (row[1] != nullptr)
|
||||||
if (row[1] != nullptr) {
|
date_diff = atoi(row[1]);
|
||||||
suspendeduntil = atoi(row[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 current = atoi(row[2]);
|
if (date_diff > 0)
|
||||||
|
|
||||||
if(suspendeduntil > current)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Database::CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id) {
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param password
|
||||||
|
* @param status
|
||||||
|
* @param loginserver
|
||||||
|
* @param lsaccount_id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint32 Database::CreateAccount(
|
||||||
|
const char *name,
|
||||||
|
const char *password,
|
||||||
|
int16 status,
|
||||||
|
const char *loginserver,
|
||||||
|
uint32 lsaccount_id
|
||||||
|
)
|
||||||
|
{
|
||||||
std::string query;
|
std::string query;
|
||||||
|
|
||||||
if (password)
|
if (password) {
|
||||||
query = StringFormat("INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id);
|
query = StringFormat(
|
||||||
else
|
"INSERT INTO account SET name='%s', password='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",
|
||||||
query = StringFormat("INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id);
|
name,
|
||||||
|
password,
|
||||||
|
status,
|
||||||
|
loginserver,
|
||||||
|
lsaccount_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
query = StringFormat(
|
||||||
|
"INSERT INTO account SET name='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",
|
||||||
|
name,
|
||||||
|
status,
|
||||||
|
loginserver,
|
||||||
|
lsaccount_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Log(Logs::General, Logs::World_Server, "Account Attempting to be created: '%s' status: %i", name, status);
|
LogInfo("Account Attempting to be created: [{0}:{1}] status: {2}", loginserver, name, status);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.LastInsertedID() == 0)
|
if (results.LastInsertedID() == 0) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return results.LastInsertedID();
|
return results.LastInsertedID();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::DeleteAccount(const char* name) {
|
bool Database::DeleteAccount(const char* name, const char *loginserver) {
|
||||||
std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name);
|
std::string query = StringFormat("DELETE FROM account WHERE name='%s' AND ls_id='%s'", name, loginserver);
|
||||||
Log(Logs::General, Logs::World_Server, "Account Attempting to be deleted:'%s'", name);
|
LogInfo("Account Attempting to be deleted:'[{}]:[{}]'", loginserver, name);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
@@ -272,7 +299,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
|||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
if (row[0] && atoi(row[0]) > 0){
|
if (row[0] && atoi(row[0]) > 0){
|
||||||
Log(Logs::General, Logs::World_Server, "Account: %i tried to request name: %s, but it is already taken...", account_id, name);
|
LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,17 +317,17 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
|||||||
bool Database::DeleteCharacter(char *name) {
|
bool Database::DeleteCharacter(char *name) {
|
||||||
uint32 charid = 0;
|
uint32 charid = 0;
|
||||||
if(!name || !strlen(name)) {
|
if(!name || !strlen(name)) {
|
||||||
Log(Logs::General, Logs::World_Server, "DeleteCharacter: request to delete without a name (empty char slot)");
|
LogInfo("DeleteCharacter: request to delete without a name (empty char slot)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::World_Server, "Database::DeleteCharacter name : '%s'", name);
|
LogInfo("Database::DeleteCharacter name : [{}]", name);
|
||||||
|
|
||||||
/* Get id from character_data before deleting record so we can clean up the rest of the tables */
|
/* Get id from character_data before deleting record so we can clean up the rest of the tables */
|
||||||
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name);
|
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); }
|
for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); }
|
||||||
if (charid <= 0){
|
if (charid <= 0){
|
||||||
Log(Logs::General, Logs::Error, "Database::DeleteCharacter :: Character (%s) not found, stopping delete...", name);
|
LogError("Database::DeleteCharacter :: Character ({}) not found, stopping delete...", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,7 +714,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, EQEmu
|
|||||||
charid = GetCharacterID(pp->name);
|
charid = GetCharacterID(pp->name);
|
||||||
|
|
||||||
if(!charid) {
|
if(!charid) {
|
||||||
Log(Logs::General, Logs::Error, "StoreCharacter: no character id");
|
LogError("StoreCharacter: no character id");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -788,11 +815,12 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) {
|
|||||||
return atoi(row[0]);
|
return atoi(row[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) {
|
uint32 Database::GetAccountIDByName(const char* accname, const char *loginserver, int16* status, uint32* lsid) {
|
||||||
if (!isAlphaNumeric(accname))
|
if (!isAlphaNumeric(accname))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' LIMIT 1", accname);
|
std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' AND `ls_id`='%s' LIMIT 1",
|
||||||
|
EscapeString(accname).c_str(), EscapeString(loginserver).c_str());
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
@@ -921,18 +949,6 @@ bool Database::SetVariable(const std::string varname, const std::string &varvalu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Database::GetMiniLoginAccount(char* ip)
|
|
||||||
{
|
|
||||||
std::string query = StringFormat("SELECT `id` FROM `account` WHERE `minilogin_ip` = '%s'", ip);
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
if (!results.Success())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
return atoi(row[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get zone starting points from DB
|
// Get zone starting points from DB
|
||||||
bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe_x, float* safe_y, float* safe_z, int16* minstatus, uint8* minlevel, char *flag_needed) {
|
bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe_x, float* safe_y, float* safe_z, int16* minstatus, uint8* minlevel, char *flag_needed) {
|
||||||
|
|
||||||
@@ -1194,25 +1210,46 @@ bool Database::AddToNameFilter(const char* name) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* oStatus) {
|
/**
|
||||||
|
* @param in_loginserver_id
|
||||||
|
* @param in_loginserver_account_id
|
||||||
|
* @param in_account_name
|
||||||
|
* @param in_status
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint32 Database::GetAccountIDFromLSID(
|
||||||
|
const std::string &in_loginserver_id,
|
||||||
|
uint32 in_loginserver_account_id,
|
||||||
|
char *in_account_name,
|
||||||
|
int16 *in_status
|
||||||
|
)
|
||||||
|
{
|
||||||
uint32 account_id = 0;
|
uint32 account_id = 0;
|
||||||
std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID);
|
auto query = fmt::format(
|
||||||
|
"SELECT id, name, status FROM account WHERE lsaccount_id = {0} AND ls_id = '{1}'",
|
||||||
|
in_loginserver_account_id,
|
||||||
|
in_loginserver_id
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() != 1)
|
if (results.RowCount() != 1) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
account_id = atoi(row[0]);
|
account_id = std::stoi(row[0]);
|
||||||
|
|
||||||
if (oAccountName)
|
if (in_account_name) {
|
||||||
strcpy(oAccountName, row[1]);
|
strcpy(in_account_name, row[1]);
|
||||||
if (oStatus)
|
}
|
||||||
*oStatus = atoi(row[2]);
|
if (in_status) {
|
||||||
|
*in_status = std::stoi(row[2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return account_id;
|
return account_id;
|
||||||
@@ -1445,9 +1482,9 @@ uint32 Database::GetCharacterInfo(
|
|||||||
return charid;
|
return charid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) {
|
bool Database::UpdateLiveChar(char* charname, uint32 account_id) {
|
||||||
|
|
||||||
std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id);
|
std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;", charname, account_id);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success()){
|
if (!results.Success()){
|
||||||
@@ -1514,7 +1551,7 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism
|
|||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
Log(Logs::General, Logs::Error, "Error deleting character from group id: %s", results.ErrorMessage().c_str());
|
LogError("Error deleting character from group id: {}", results.ErrorMessage().c_str());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1557,7 +1594,7 @@ uint32 Database::GetGroupID(const char* name){
|
|||||||
if (results.RowCount() == 0)
|
if (results.RowCount() == 0)
|
||||||
{
|
{
|
||||||
// Commenting this out until logging levels can prevent this from going to console
|
// Commenting this out until logging levels can prevent this from going to console
|
||||||
//Log(Logs::General, Logs::None,, "Character not in a group: %s", name);
|
//LogDebug(, "Character not in a group: [{}]", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1604,7 +1641,7 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) {
|
|||||||
result = QueryDatabase(query);
|
result = QueryDatabase(query);
|
||||||
|
|
||||||
if(!result.Success()) {
|
if(!result.Success()) {
|
||||||
Log(Logs::General, Logs::None, "Error in Database::SetGroupLeaderName: %s", result.ErrorMessage().c_str());
|
LogDebug("Error in Database::SetGroupLeaderName: [{}]", result.ErrorMessage().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1810,7 +1847,7 @@ const char* Database::GetRaidLeaderName(uint32 raid_id)
|
|||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Debug, "Unable to get Raid Leader Name for Raid ID: %u", raid_id);
|
LogDebug("Unable to get Raid Leader Name for Raid ID: [{}]", raid_id);
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2077,9 +2114,11 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
|
|||||||
return atoi(row[0]);
|
return atoi(row[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) {
|
/**
|
||||||
// log_settings previously initialized to '0' by EQEmuLogSys::LoadLogSettingsDefaults()
|
* @param log_settings
|
||||||
|
*/
|
||||||
|
void Database::LoadLogSettings(EQEmuLogSys::LogSettings *log_settings)
|
||||||
|
{
|
||||||
std::string query =
|
std::string query =
|
||||||
"SELECT "
|
"SELECT "
|
||||||
"log_category_id, "
|
"log_category_id, "
|
||||||
@@ -2092,10 +2131,9 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) {
|
|||||||
"ORDER BY log_category_id";
|
"ORDER BY log_category_id";
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
int log_category_id = 0;
|
int log_category_id = 0;
|
||||||
|
|
||||||
int categories_in_database[1000] = {};
|
int *categories_in_database = new int[1000];
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
log_category_id = atoi(row[0]);
|
log_category_id = atoi(row[0]);
|
||||||
@@ -2135,15 +2173,14 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) {
|
|||||||
* Auto inject categories that don't exist in the database...
|
* Auto inject categories that don't exist in the database...
|
||||||
*/
|
*/
|
||||||
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
|
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
|
||||||
if (!categories_in_database[log_index]) {
|
if (categories_in_database[log_index] != 1) {
|
||||||
|
|
||||||
Log(Logs::General,
|
LogInfo(
|
||||||
Logs::Status,
|
"New Log Category [{0}] doesn't exist... Automatically adding to [logsys_categories] table...",
|
||||||
"New Log Category '%s' doesn't exist... Automatically adding to `logsys_categories` table...",
|
|
||||||
Logs::LogCategoryName[log_index]
|
Logs::LogCategoryName[log_index]
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string inject_query = StringFormat(
|
auto inject_query = fmt::format(
|
||||||
"INSERT INTO logsys_categories "
|
"INSERT INTO logsys_categories "
|
||||||
"(log_category_id, "
|
"(log_category_id, "
|
||||||
"log_category_description, "
|
"log_category_description, "
|
||||||
@@ -2151,17 +2188,19 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) {
|
|||||||
"log_to_file, "
|
"log_to_file, "
|
||||||
"log_to_gmsay) "
|
"log_to_gmsay) "
|
||||||
"VALUES "
|
"VALUES "
|
||||||
"(%i, '%s', %i, %i, %i)",
|
"({0}, '{1}', {2}, {3}, {4})",
|
||||||
log_index,
|
log_index,
|
||||||
EscapeString(Logs::LogCategoryName[log_index]).c_str(),
|
EscapeString(Logs::LogCategoryName[log_index]),
|
||||||
log_settings[log_category_id].log_to_console,
|
std::to_string(log_settings[log_index].log_to_console),
|
||||||
log_settings[log_category_id].log_to_file,
|
std::to_string(log_settings[log_index].log_to_file),
|
||||||
log_settings[log_category_id].log_to_gmsay
|
std::to_string(log_settings[log_index].log_to_gmsay)
|
||||||
);
|
);
|
||||||
|
|
||||||
QueryDatabase(inject_query);
|
QueryDatabase(inject_query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete[] categories_in_database;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Database::CountInvSnapshots() {
|
int Database::CountInvSnapshots() {
|
||||||
@@ -2198,7 +2237,7 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
|
|||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
if (!results.Success() || results.RowCount() == 0){
|
if (!results.Success() || results.RowCount() == 0){
|
||||||
Log(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults.");
|
LogInfo("Loading EQ time of day failed. Using defaults");
|
||||||
eqTime.minute = 0;
|
eqTime.minute = 0;
|
||||||
eqTime.hour = 9;
|
eqTime.hour = 9;
|
||||||
eqTime.day = 1;
|
eqTime.day = 1;
|
||||||
|
|||||||
+8
-7
@@ -94,6 +94,8 @@ class PTimerList;
|
|||||||
# define _ISNAN_(a) std::isnan(a)
|
# define _ISNAN_(a) std::isnan(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SQL(...) #__VA_ARGS__
|
||||||
|
|
||||||
class Database : public DBcore {
|
class Database : public DBcore {
|
||||||
public:
|
public:
|
||||||
Database();
|
Database();
|
||||||
@@ -127,7 +129,7 @@ public:
|
|||||||
|
|
||||||
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
|
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
|
||||||
uint32 GetAccountIDByChar(uint32 char_id);
|
uint32 GetAccountIDByChar(uint32 char_id);
|
||||||
uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0);
|
uint32 GetAccountIDByName(const char* accname, const char *loginserver, int16* status = 0, uint32* lsid = 0);
|
||||||
uint32 GetCharacterID(const char *name);
|
uint32 GetCharacterID(const char *name);
|
||||||
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
|
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
|
||||||
uint32 GetGuildIDByCharID(uint32 char_id);
|
uint32 GetGuildIDByCharID(uint32 char_id);
|
||||||
@@ -174,18 +176,17 @@ public:
|
|||||||
|
|
||||||
/* Account Related */
|
/* Account Related */
|
||||||
|
|
||||||
bool DeleteAccount(const char* name);
|
bool DeleteAccount(const char *name, const char* loginserver);
|
||||||
bool GetLiveChar(uint32 account_id, char* cname);
|
bool GetLiveChar(uint32 account_id, char* cname);
|
||||||
bool SetAccountStatus(const char* name, int16 status);
|
bool SetAccountStatus(const char* name, int16 status);
|
||||||
bool SetLocalPassword(uint32 accid, const char* password);
|
bool SetLocalPassword(uint32 accid, const char* password);
|
||||||
bool UpdateLiveChar(char* charname, uint32 lsaccount_id);
|
bool UpdateLiveChar(char* charname, uint32 account_id);
|
||||||
|
|
||||||
int16 CheckStatus(uint32 account_id);
|
int16 CheckStatus(uint32 account_id);
|
||||||
|
|
||||||
uint32 CheckLogin(const char* name, const char* password, int16* oStatus = 0);
|
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
|
||||||
uint32 CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id = 0);
|
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
|
||||||
uint32 GetAccountIDFromLSID(uint32 iLSID, char* oAccountName = 0, int16* oStatus = 0);
|
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
|
||||||
uint32 GetMiniLoginAccount(char* ip);
|
|
||||||
uint8 GetAgreementFlag(uint32 acctid);
|
uint8 GetAgreementFlag(uint32 acctid);
|
||||||
|
|
||||||
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ bool Database::CheckDatabaseConversions() {
|
|||||||
CheckDatabaseConvertCorpseDeblob();
|
CheckDatabaseConvertCorpseDeblob();
|
||||||
|
|
||||||
/* Run EQEmu Server script (Checks for database updates) */
|
/* Run EQEmu Server script (Checks for database updates) */
|
||||||
system("perl eqemu_server.pl ran_from_world");
|
if(system("perl eqemu_server.pl ran_from_world"));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+102
-50
@@ -2,8 +2,9 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../common/misc_functions.h"
|
#include "misc_functions.h"
|
||||||
#include "../common/eqemu_logsys.h"
|
#include "eqemu_logsys.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
#include "dbcore.h"
|
#include "dbcore.h"
|
||||||
|
|
||||||
@@ -14,22 +15,25 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#define strncasecmp _strnicmp
|
#define strncasecmp _strnicmp
|
||||||
#define strcasecmp _stricmp
|
#define strcasecmp _stricmp
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#else
|
#else
|
||||||
#include "unix.h"
|
|
||||||
#include <pthread.h>
|
#include "unix.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _EQDEBUG
|
#ifdef _EQDEBUG
|
||||||
#define DEBUG_MYSQL_QUERIES 0
|
#define DEBUG_MYSQL_QUERIES 0
|
||||||
#else
|
#else
|
||||||
#define DEBUG_MYSQL_QUERIES 0
|
#define DEBUG_MYSQL_QUERIES 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DBcore::DBcore() {
|
DBcore::DBcore()
|
||||||
|
{
|
||||||
mysql_init(&mysql);
|
mysql_init(&mysql);
|
||||||
pHost = 0;
|
pHost = 0;
|
||||||
pUser = 0;
|
pUser = 0;
|
||||||
@@ -40,7 +44,8 @@ DBcore::DBcore() {
|
|||||||
pStatus = Closed;
|
pStatus = Closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBcore::~DBcore() {
|
DBcore::~DBcore()
|
||||||
|
{
|
||||||
mysql_close(&mysql);
|
mysql_close(&mysql);
|
||||||
safe_delete_array(pHost);
|
safe_delete_array(pHost);
|
||||||
safe_delete_array(pUser);
|
safe_delete_array(pUser);
|
||||||
@@ -49,7 +54,8 @@ DBcore::~DBcore() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sends the MySQL server a keepalive
|
// Sends the MySQL server a keepalive
|
||||||
void DBcore::ping() {
|
void DBcore::ping()
|
||||||
|
{
|
||||||
if (!MDatabase.trylock()) {
|
if (!MDatabase.trylock()) {
|
||||||
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
|
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
|
||||||
return;
|
return;
|
||||||
@@ -63,34 +69,35 @@ MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureO
|
|||||||
return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
||||||
}
|
}
|
||||||
|
|
||||||
MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce)
|
MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce)
|
||||||
{
|
{
|
||||||
|
BenchTimer timer;
|
||||||
|
timer.reset();
|
||||||
|
|
||||||
LockMutex lock(&MDatabase);
|
LockMutex lock(&MDatabase);
|
||||||
|
|
||||||
// Reconnect if we are not connected before hand.
|
// Reconnect if we are not connected before hand.
|
||||||
if (pStatus != Connected)
|
if (pStatus != Connected) {
|
||||||
Open();
|
Open();
|
||||||
|
}
|
||||||
|
|
||||||
// request query. != 0 indicates some kind of error.
|
// request query. != 0 indicates some kind of error.
|
||||||
if (mysql_real_query(&mysql, query, querylen) != 0)
|
if (mysql_real_query(&mysql, query, querylen) != 0) {
|
||||||
{
|
|
||||||
unsigned int errorNumber = mysql_errno(&mysql);
|
unsigned int errorNumber = mysql_errno(&mysql);
|
||||||
|
|
||||||
if (errorNumber == CR_SERVER_GONE_ERROR)
|
if (errorNumber == CR_SERVER_GONE_ERROR) {
|
||||||
pStatus = Error;
|
pStatus = Error;
|
||||||
|
}
|
||||||
|
|
||||||
// error appears to be a disconnect error, may need to try again.
|
// error appears to be a disconnect error, may need to try again.
|
||||||
if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR)
|
if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR) {
|
||||||
{
|
|
||||||
|
|
||||||
if (retryOnFailureOnce)
|
if (retryOnFailureOnce) {
|
||||||
{
|
LogInfo("Database Error: Lost connection, attempting to recover");
|
||||||
std::cout << "Database Error: Lost connection, attempting to recover...." << std::endl;
|
|
||||||
MySQLRequestResult requestResult = QueryDatabase(query, querylen, false);
|
MySQLRequestResult requestResult = QueryDatabase(query, querylen, false);
|
||||||
|
|
||||||
if (requestResult.Success())
|
if (requestResult.Success()) {
|
||||||
{
|
LogInfo("Reconnection to database successful");
|
||||||
std::cout << "Reconnection to database successful." << std::endl;
|
|
||||||
return requestResult;
|
return requestResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,63 +109,100 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
|||||||
|
|
||||||
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
|
||||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer);
|
return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(&mysql), errorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
||||||
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
|
||||||
/* Implement Logging at the Root */
|
/* Implement Logging at the Root */
|
||||||
if (mysql_errno(&mysql) > 0 && strlen(query) > 0){
|
if (mysql_errno(&mysql) > 0 && strlen(query) > 0) {
|
||||||
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)
|
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)
|
||||||
Log(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
Log(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer);
|
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// successful query. get results.
|
// successful query. get results.
|
||||||
MYSQL_RES* res = mysql_store_result(&mysql);
|
MYSQL_RES *res = mysql_store_result(&mysql);
|
||||||
uint32 rowCount = 0;
|
uint32 rowCount = 0;
|
||||||
|
|
||||||
if (res != nullptr)
|
if (res != nullptr) {
|
||||||
rowCount = (uint32)mysql_num_rows(res);
|
rowCount = (uint32) mysql_num_rows(res);
|
||||||
|
}
|
||||||
|
|
||||||
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
|
MySQLRequestResult requestResult(
|
||||||
|
res,
|
||||||
|
(uint32) mysql_affected_rows(&mysql),
|
||||||
|
rowCount,
|
||||||
|
(uint32) mysql_field_count(&mysql),
|
||||||
|
(uint32) mysql_insert_id(&mysql)
|
||||||
|
);
|
||||||
|
|
||||||
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
|
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) {
|
||||||
{
|
|
||||||
if ((strncasecmp(query, "select", 6) == 0)) {
|
if ((strncasecmp(query, "select", 6) == 0)) {
|
||||||
Log(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s");
|
LogF(
|
||||||
|
Logs::General,
|
||||||
|
Logs::MySQLQuery,
|
||||||
|
"{0} ({1} row{2} returned) ({3}ms)",
|
||||||
|
query,
|
||||||
|
requestResult.RowCount(),
|
||||||
|
requestResult.RowCount() == 1 ? "" : "s",
|
||||||
|
std::to_string(timer.elapsed())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s");
|
LogF(
|
||||||
|
Logs::General,
|
||||||
|
Logs::MySQLQuery,
|
||||||
|
"{0} ({1} row{2} affected) ({3}ms)",
|
||||||
|
query,
|
||||||
|
requestResult.RowsAffected(),
|
||||||
|
requestResult.RowsAffected() == 1 ? "" : "s",
|
||||||
|
std::to_string(timer.elapsed())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestResult;
|
return requestResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBcore::TransactionBegin() {
|
void DBcore::TransactionBegin()
|
||||||
|
{
|
||||||
QueryDatabase("START TRANSACTION");
|
QueryDatabase("START TRANSACTION");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBcore::TransactionCommit() {
|
void DBcore::TransactionCommit()
|
||||||
|
{
|
||||||
QueryDatabase("COMMIT");
|
QueryDatabase("COMMIT");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBcore::TransactionRollback() {
|
void DBcore::TransactionRollback()
|
||||||
|
{
|
||||||
QueryDatabase("ROLLBACK");
|
QueryDatabase("ROLLBACK");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 DBcore::DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen) {
|
uint32 DBcore::DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen)
|
||||||
|
{
|
||||||
// No good reason to lock the DB, we only need it in the first place to check char encoding.
|
// No good reason to lock the DB, we only need it in the first place to check char encoding.
|
||||||
// LockMutex lock(&MDatabase);
|
// LockMutex lock(&MDatabase);
|
||||||
return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen);
|
return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DBcore::Open(const char* iHost, const char* iUser, const char* iPassword, const char* iDatabase,uint32 iPort, uint32* errnum, char* errbuf, bool iCompress, bool iSSL) {
|
bool DBcore::Open(
|
||||||
|
const char *iHost,
|
||||||
|
const char *iUser,
|
||||||
|
const char *iPassword,
|
||||||
|
const char *iDatabase,
|
||||||
|
uint32 iPort,
|
||||||
|
uint32 *errnum,
|
||||||
|
char *errbuf,
|
||||||
|
bool iCompress,
|
||||||
|
bool iSSL
|
||||||
|
)
|
||||||
|
{
|
||||||
LockMutex lock(&MDatabase);
|
LockMutex lock(&MDatabase);
|
||||||
safe_delete(pHost);
|
safe_delete(pHost);
|
||||||
safe_delete(pUser);
|
safe_delete(pUser);
|
||||||
@@ -174,37 +218,45 @@ bool DBcore::Open(const char* iHost, const char* iUser, const char* iPassword, c
|
|||||||
return Open(errnum, errbuf);
|
return Open(errnum, errbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DBcore::Open(uint32* errnum, char* errbuf) {
|
bool DBcore::Open(uint32 *errnum, char *errbuf)
|
||||||
if (errbuf)
|
{
|
||||||
|
if (errbuf) {
|
||||||
errbuf[0] = 0;
|
errbuf[0] = 0;
|
||||||
|
}
|
||||||
LockMutex lock(&MDatabase);
|
LockMutex lock(&MDatabase);
|
||||||
if (GetStatus() == Connected)
|
if (GetStatus() == Connected) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (GetStatus() == Error) {
|
if (GetStatus() == Error) {
|
||||||
mysql_close(&mysql);
|
mysql_close(&mysql);
|
||||||
mysql_init(&mysql); // Initialize structure again
|
mysql_init(&mysql); // Initialize structure again
|
||||||
}
|
}
|
||||||
if (!pHost)
|
if (!pHost) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Added CLIENT_FOUND_ROWS flag to the connect
|
Added CLIENT_FOUND_ROWS flag to the connect
|
||||||
otherwise DB update calls would say 0 rows affected when the value already equalled
|
otherwise DB update calls would say 0 rows affected when the value already equalled
|
||||||
what the function was tring to set it to, therefore the function would think it failed
|
what the function was tring to set it to, therefore the function would think it failed
|
||||||
*/
|
*/
|
||||||
uint32 flags = CLIENT_FOUND_ROWS;
|
uint32 flags = CLIENT_FOUND_ROWS;
|
||||||
if (pCompress)
|
if (pCompress) {
|
||||||
flags |= CLIENT_COMPRESS;
|
flags |= CLIENT_COMPRESS;
|
||||||
if (pSSL)
|
}
|
||||||
|
if (pSSL) {
|
||||||
flags |= CLIENT_SSL;
|
flags |= CLIENT_SSL;
|
||||||
|
}
|
||||||
if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
|
if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
|
||||||
pStatus = Connected;
|
pStatus = Connected;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (errnum)
|
if (errnum) {
|
||||||
*errnum = mysql_errno(&mysql);
|
*errnum = mysql_errno(&mysql);
|
||||||
if (errbuf)
|
}
|
||||||
|
if (errbuf) {
|
||||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
}
|
||||||
pStatus = Error;
|
pStatus = Error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ namespace EQEmu
|
|||||||
|
|
||||||
} // namespace invtype
|
} // namespace invtype
|
||||||
|
|
||||||
|
namespace DevTools {
|
||||||
|
const int32 GM_ACCOUNT_STATUS_LEVEL = 150;
|
||||||
|
}
|
||||||
|
|
||||||
namespace popupresponse {
|
namespace popupresponse {
|
||||||
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
|
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
|
||||||
const int32 MOB_INFO_DISMISS = 2000000001;
|
const int32 MOB_INFO_DISMISS = 2000000001;
|
||||||
@@ -307,6 +311,12 @@ namespace EQEmu
|
|||||||
|
|
||||||
} // namespace bug
|
} // namespace bug
|
||||||
|
|
||||||
|
enum WaypointStatus : int {
|
||||||
|
RoamBoxPauseInProgress = -3,
|
||||||
|
QuestControlNoGrid = -2,
|
||||||
|
QuestControlGrid = -1
|
||||||
|
};
|
||||||
|
|
||||||
} /*EQEmu*/
|
} /*EQEmu*/
|
||||||
|
|
||||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||||
|
|||||||
+132
-191
@@ -87,199 +87,114 @@ typedef enum {
|
|||||||
_eaMaxAppearance
|
_eaMaxAppearance
|
||||||
} EmuAppearance;
|
} EmuAppearance;
|
||||||
|
|
||||||
// msg_type's for custom usercolors
|
namespace Chat {
|
||||||
#define MT_Say 256
|
const uint16 White = 0;
|
||||||
#define MT_Tell 257
|
const uint16 DimGray = 1;
|
||||||
#define MT_Group 258
|
const uint16 Default = 1;
|
||||||
#define MT_Guild 259
|
const uint16 Green = 2;
|
||||||
#define MT_OOC 260
|
const uint16 BrightBlue = 3;
|
||||||
#define MT_Auction 261
|
const uint16 LightBlue = 4;
|
||||||
#define MT_Shout 262
|
const uint16 Magenta = 5;
|
||||||
#define MT_Emote 263
|
const uint16 Gray = 6;
|
||||||
#define MT_Spells 264
|
const uint16 LightGray = 7;
|
||||||
#define MT_YouHitOther 265
|
const uint16 NPCQuestSay = 10;
|
||||||
#define MT_OtherHitsYou 266
|
const uint16 DarkGray = 12;
|
||||||
#define MT_YouMissOther 267
|
const uint16 Red = 13;
|
||||||
#define MT_OtherMissesYou 268
|
const uint16 Lime = 14;
|
||||||
#define MT_Broadcasts 269
|
const uint16 Yellow = 15;
|
||||||
#define MT_Skills 270
|
const uint16 Blue = 16;
|
||||||
#define MT_Disciplines 271
|
const uint16 LightNavy = 17;
|
||||||
#define MT_Unused1 272
|
const uint16 Cyan = 18;
|
||||||
#define MT_DefaultText 273
|
const uint16 Black = 20;
|
||||||
#define MT_Unused2 274
|
|
||||||
#define MT_MerchantOffer 275
|
|
||||||
#define MT_MerchantBuySell 276
|
|
||||||
#define MT_YourDeath 277
|
|
||||||
#define MT_OtherDeath 278
|
|
||||||
#define MT_OtherHits 279
|
|
||||||
#define MT_OtherMisses 280
|
|
||||||
#define MT_Who 281
|
|
||||||
#define MT_YellForHelp 282
|
|
||||||
#define MT_NonMelee 283
|
|
||||||
#define MT_WornOff 284
|
|
||||||
#define MT_MoneySplit 285
|
|
||||||
#define MT_LootMessages 286
|
|
||||||
#define MT_DiceRoll 287
|
|
||||||
#define MT_OtherSpells 288
|
|
||||||
#define MT_SpellFailure 289
|
|
||||||
#define MT_Chat 290
|
|
||||||
#define MT_Channel1 291
|
|
||||||
#define MT_Channel2 292
|
|
||||||
#define MT_Channel3 293
|
|
||||||
#define MT_Channel4 294
|
|
||||||
#define MT_Channel5 295
|
|
||||||
#define MT_Channel6 296
|
|
||||||
#define MT_Channel7 297
|
|
||||||
#define MT_Channel8 298
|
|
||||||
#define MT_Channel9 299
|
|
||||||
#define MT_Channel10 300
|
|
||||||
#define MT_CritMelee 301
|
|
||||||
#define MT_SpellCrits 302
|
|
||||||
#define MT_TooFarAway 303
|
|
||||||
#define MT_NPCRampage 304
|
|
||||||
#define MT_NPCFlurry 305
|
|
||||||
#define MT_NPCEnrage 306
|
|
||||||
#define MT_SayEcho 307
|
|
||||||
#define MT_TellEcho 308
|
|
||||||
#define MT_GroupEcho 309
|
|
||||||
#define MT_GuildEcho 310
|
|
||||||
#define MT_OOCEcho 311
|
|
||||||
#define MT_AuctionEcho 312
|
|
||||||
#define MT_ShoutECho 313
|
|
||||||
#define MT_EmoteEcho 314
|
|
||||||
#define MT_Chat1Echo 315
|
|
||||||
#define MT_Chat2Echo 316
|
|
||||||
#define MT_Chat3Echo 317
|
|
||||||
#define MT_Chat4Echo 318
|
|
||||||
#define MT_Chat5Echo 319
|
|
||||||
#define MT_Chat6Echo 320
|
|
||||||
#define MT_Chat7Echo 321
|
|
||||||
#define MT_Chat8Echo 322
|
|
||||||
#define MT_Chat9Echo 323
|
|
||||||
#define MT_Chat10Echo 324
|
|
||||||
#define MT_DoTDamage 325
|
|
||||||
#define MT_ItemLink 326
|
|
||||||
#define MT_RaidSay 327
|
|
||||||
#define MT_MyPet 328
|
|
||||||
#define MT_DS 329
|
|
||||||
#define MT_Leadership 330
|
|
||||||
#define MT_PetFlurry 331
|
|
||||||
#define MT_PetCrit 332
|
|
||||||
#define MT_FocusEffect 333
|
|
||||||
#define MT_Experience 334
|
|
||||||
#define MT_System 335
|
|
||||||
#define MT_PetSpell 336
|
|
||||||
#define MT_PetResponse 337
|
|
||||||
#define MT_ItemSpeech 338
|
|
||||||
#define MT_StrikeThrough 339
|
|
||||||
#define MT_Stun 340
|
|
||||||
|
|
||||||
// TODO: Really should combine above and below into one
|
/**
|
||||||
|
* User colors
|
||||||
//from showeq
|
|
||||||
enum ChatColor
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
CC_Default = 0,
|
|
||||||
CC_DarkGrey = 1,
|
|
||||||
CC_DarkGreen = 2,
|
|
||||||
CC_DarkBlue = 3,
|
|
||||||
CC_Purple = 5,
|
|
||||||
CC_LightGrey = 6,
|
|
||||||
*/
|
*/
|
||||||
|
const uint16 Say = 256;
|
||||||
CC_WhiteSmoke = 0, // FF|F0F0F0
|
const uint16 Tell = 257;
|
||||||
CC_Green = 2, // FF|008000
|
const uint16 Group = 258;
|
||||||
CC_BrightBlue = 3, // FF|0040FF
|
const uint16 Guild = 259;
|
||||||
CC_Magenta = 5, // FF|F000F0
|
const uint16 OOC = 260;
|
||||||
CC_Gray = 6, // FF|808080
|
const uint16 Auction = 261;
|
||||||
CC_LightGray = 7, // FF|E0E0E0
|
const uint16 Shout = 262;
|
||||||
//CC_WhiteSmoke2 = 10, // FF|F0F0F0
|
const uint16 Emote = 263;
|
||||||
CC_DarkGray = 12, // FF|A0A0A0
|
const uint16 Spells = 264;
|
||||||
CC_Red = 13, // FF|F00000
|
const uint16 YouHitOther = 265;
|
||||||
CC_Lime = 14, // FF|00F000
|
const uint16 OtherHitYou = 266;
|
||||||
CC_Yellow = 15, // FF|F0F000
|
const uint16 YouMissOther = 267;
|
||||||
CC_Blue = 16, // FF|0000F0
|
const uint16 OtherMissYou = 268;
|
||||||
CC_LightNavy = 17, // FF|0000AF
|
const uint16 Broadcasts = 269;
|
||||||
CC_Cyan = 18, // FF|00F0F0
|
const uint16 Skills = 270;
|
||||||
CC_Black = 20, // FF|000000
|
const uint16 Disciplines = 271;
|
||||||
|
const uint16 Unused1 = 272;
|
||||||
// any index <= 255 that is not defined above
|
const uint16 DefaultText = 273;
|
||||||
CC_DimGray = 1, // FF|606060
|
const uint16 Unused2 = 274;
|
||||||
CC_Default = 1,
|
const uint16 MerchantOffer = 275;
|
||||||
|
const uint16 MerchantExchange = 276;
|
||||||
CC_User_Say = 256,
|
const uint16 YourDeath = 277;
|
||||||
CC_User_Tell = 257,
|
const uint16 OtherDeath = 278;
|
||||||
CC_User_Group = 258,
|
const uint16 OtherHitOther = 279;
|
||||||
CC_User_Guild = 259,
|
const uint16 OtherMissOther = 280;
|
||||||
CC_User_OOC = 260,
|
const uint16 Who = 281;
|
||||||
CC_User_Auction = 261,
|
const uint16 YellForHelp = 282;
|
||||||
CC_User_Shout = 262,
|
const uint16 NonMelee = 283;
|
||||||
CC_User_Emote = 263,
|
const uint16 SpellWornOff = 284;
|
||||||
CC_User_Spells = 264,
|
const uint16 MoneySplit = 285;
|
||||||
CC_User_YouHitOther = 265,
|
const uint16 Loot = 286;
|
||||||
CC_User_OtherHitYou = 266,
|
const uint16 DiceRoll = 287;
|
||||||
CC_User_YouMissOther = 267,
|
const uint16 OtherSpells = 288;
|
||||||
CC_User_OtherMissYou = 268,
|
const uint16 SpellFailure = 289;
|
||||||
CC_User_Duels = 269,
|
const uint16 ChatChannel = 290;
|
||||||
CC_User_Skills = 270,
|
const uint16 Chat1 = 291;
|
||||||
CC_User_Disciplines = 271,
|
const uint16 Chat2 = 292;
|
||||||
CC_User_Default = 273,
|
const uint16 Chat3 = 293;
|
||||||
CC_User_MerchantOffer = 275,
|
const uint16 Chat4 = 294;
|
||||||
CC_User_MerchantExchange = 276,
|
const uint16 Chat5 = 295;
|
||||||
CC_User_YourDeath = 277,
|
const uint16 Chat6 = 296;
|
||||||
CC_User_OtherDeath = 278,
|
const uint16 Chat7 = 297;
|
||||||
CC_User_OtherHitOther = 279,
|
const uint16 Chat8 = 298;
|
||||||
CC_User_OtherMissOther = 280,
|
const uint16 Chat9 = 299;
|
||||||
CC_User_Who = 281,
|
const uint16 Chat10 = 300;
|
||||||
CC_User_Yell = 282,
|
const uint16 MeleeCrit = 301;
|
||||||
CC_User_NonMelee = 283,
|
const uint16 SpellCrit = 302;
|
||||||
CC_User_SpellWornOff = 284,
|
const uint16 TooFarAway = 303;
|
||||||
CC_User_MoneySplit = 285,
|
const uint16 NPCRampage = 304;
|
||||||
CC_User_Loot = 286,
|
const uint16 NPCFlurry = 305;
|
||||||
CC_User_Random = 287,
|
const uint16 NPCEnrage = 306;
|
||||||
CC_User_OtherSpells = 288,
|
const uint16 EchoSay = 307;
|
||||||
CC_User_SpellFailure = 289,
|
const uint16 EchoTell = 308;
|
||||||
CC_User_ChatChannel = 290,
|
const uint16 EchoGroup = 309;
|
||||||
CC_User_Chat1 = 291,
|
const uint16 EchoGuild = 310;
|
||||||
CC_User_Chat2 = 292,
|
const uint16 EchoOOC = 311;
|
||||||
CC_User_Chat3 = 293,
|
const uint16 EchoAuction = 312;
|
||||||
CC_User_Chat4 = 294,
|
const uint16 EchoShout = 313;
|
||||||
CC_User_Chat5 = 295,
|
const uint16 EchoEmote = 314;
|
||||||
CC_User_Chat6 = 296,
|
const uint16 EchoChat1 = 315;
|
||||||
CC_User_Chat7 = 297,
|
const uint16 EchoChat2 = 316;
|
||||||
CC_User_Chat8 = 298,
|
const uint16 EchoChat3 = 317;
|
||||||
CC_User_Chat9 = 299,
|
const uint16 EchoChat4 = 318;
|
||||||
CC_User_Chat10 = 300,
|
const uint16 EchoChat5 = 319;
|
||||||
CC_User_MeleeCrit = 301,
|
const uint16 EchoChat6 = 320;
|
||||||
CC_User_SpellCrit = 302,
|
const uint16 EchoChat7 = 321;
|
||||||
CC_User_TooFarAway = 303,
|
const uint16 EchoChat8 = 322;
|
||||||
CC_User_NPCRampage = 304,
|
const uint16 EchoChat9 = 323;
|
||||||
CC_User_NPCFurry = 305,
|
const uint16 EchoChat10 = 324;
|
||||||
CC_User_NPCEnrage = 306,
|
const uint16 DotDamage = 325;
|
||||||
CC_User_EchoSay = 307,
|
const uint16 ItemLink = 326;
|
||||||
CC_User_EchoTell = 308,
|
const uint16 RaidSay = 327;
|
||||||
CC_User_EchoGroup = 309,
|
const uint16 MyPet = 328;
|
||||||
CC_User_EchoGuild = 310,
|
const uint16 DamageShield = 329;
|
||||||
CC_User_EchoOOC = 311,
|
const uint16 LeaderShip = 330;
|
||||||
CC_User_EchoAuction = 312,
|
const uint16 PetFlurry = 331;
|
||||||
CC_User_EchoShout = 313,
|
const uint16 PetCritical = 332;
|
||||||
CC_User_EchoEmote = 314,
|
const uint16 FocusEffect = 333;
|
||||||
CC_User_EchoChat1 = 315,
|
const uint16 Experience = 334;
|
||||||
CC_User_EchoChat2 = 316,
|
const uint16 System = 335;
|
||||||
CC_User_EchoChat3 = 317,
|
const uint16 PetSpell = 336;
|
||||||
CC_User_EchoChat4 = 318,
|
const uint16 PetResponse = 337;
|
||||||
CC_User_EchoChat5 = 319,
|
const uint16 ItemSpeech = 338;
|
||||||
CC_User_EchoChat6 = 320,
|
const uint16 StrikeThrough = 339;
|
||||||
CC_User_EchoChat7 = 321,
|
const uint16 Stun = 340;
|
||||||
CC_User_EchoChat8 = 322,
|
|
||||||
CC_User_EchoChat9 = 323,
|
|
||||||
CC_User_EchoChat10 = 324,
|
|
||||||
CC_User_UnusedAtThisTime = 325,
|
|
||||||
CC_User_ItemTags = 326,
|
|
||||||
CC_User_RaidSay = 327,
|
|
||||||
CC_User_MyPet = 328,
|
|
||||||
CC_User_DamageShield = 329,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//ZoneChange_Struct->success values
|
//ZoneChange_Struct->success values
|
||||||
@@ -523,4 +438,30 @@ static const uint8 SkillDamageTypes[EQEmu::skills::HIGHEST_SKILL + 1] = // chang
|
|||||||
|
|
||||||
static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
|
static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
|
||||||
|
|
||||||
|
enum ChatChannelNames : uint16
|
||||||
|
{
|
||||||
|
ChatChannel_Guild = 0,
|
||||||
|
ChatChannel_Group = 2,
|
||||||
|
ChatChannel_Shout = 3,
|
||||||
|
ChatChannel_Auction = 4,
|
||||||
|
ChatChannel_OOC = 5,
|
||||||
|
ChatChannel_Broadcast = 6,
|
||||||
|
ChatChannel_Tell = 7,
|
||||||
|
ChatChannel_Say = 8,
|
||||||
|
ChatChannel_Petition = 10,
|
||||||
|
ChatChannel_GMSAY = 11,
|
||||||
|
ChatChannel_TellEcho = 14,
|
||||||
|
ChatChannel_Raid = 15,
|
||||||
|
|
||||||
|
ChatChannel_UNKNOWN_Guild = 17,
|
||||||
|
ChatChannel_UNKNOWN_GMSAY = 18,
|
||||||
|
ChatChannel_UCSRelay = 20,
|
||||||
|
ChatChannel_Emotes = 22
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ZoneBlockedSpellTypes {
|
||||||
|
const uint8 ZoneWide = 1;
|
||||||
|
const uint8 Region = 2;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||||
|
|||||||
@@ -1188,6 +1188,20 @@ struct SpecialMesg_Struct
|
|||||||
/*24*/ char message[1]; // What is being said?
|
/*24*/ char message[1]; // What is being said?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SpecialMesgHeader_Struct
|
||||||
|
{
|
||||||
|
/*00*/ char SpeakMode; // 2 shouts, 4 %1 %2, 3 %2, 5 tells group, 0 copy, default says
|
||||||
|
/*01*/ char JournalMode; // 1 and 2 go to journal
|
||||||
|
/*02*/ char language;
|
||||||
|
/*03*/ uint32 msg_type; // Color of text (see MT_*** below)
|
||||||
|
/*07*/ uint32 target_spawn_id; // Who is it being said to?
|
||||||
|
/*11*/ // speaker's name
|
||||||
|
/*xx*/ // unknown, location, client doesn't care
|
||||||
|
/*xx*/ // unknown
|
||||||
|
/*xx*/ // unknown
|
||||||
|
/*xx*/ // message
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** When somebody changes what they're wearing or give a pet a weapon (model changes)
|
** When somebody changes what they're wearing or give a pet a weapon (model changes)
|
||||||
** Length: 19 Bytes
|
** Length: 19 Bytes
|
||||||
|
|||||||
+104
-104
@@ -84,14 +84,14 @@ void EQStream::init(bool resetSession) {
|
|||||||
|
|
||||||
OpMgr = nullptr;
|
OpMgr = nullptr;
|
||||||
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "init Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
LogNetcode(_L "init Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
|
EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
|
||||||
{
|
{
|
||||||
EQRawApplicationPacket *ap=nullptr;
|
EQRawApplicationPacket *ap=nullptr;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, p->size);
|
LogNetcode(_L "Creating new application packet, length [{}]" __L, p->size);
|
||||||
// _raw(NET__APP_CREATE_HEX, 0xFFFF, p);
|
// _raw(NET__APP_CREATE_HEX, 0xFFFF, p);
|
||||||
ap = p->MakeAppPacket();
|
ap = p->MakeAppPacket();
|
||||||
return ap;
|
return ap;
|
||||||
@@ -100,7 +100,7 @@ EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
|
|||||||
EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len)
|
EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len)
|
||||||
{
|
{
|
||||||
EQRawApplicationPacket *ap=nullptr;
|
EQRawApplicationPacket *ap=nullptr;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, len);
|
LogNetcode(_L "Creating new application packet, length [{}]" __L, len);
|
||||||
ap = new EQRawApplicationPacket(buf, len);
|
ap = new EQRawApplicationPacket(buf, len);
|
||||||
return ap;
|
return ap;
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) {
|
if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Session not initialized, packet ignored" __L);
|
LogNetcode(_L "Session not initialized, packet ignored" __L);
|
||||||
// _raw(NET__DEBUG, 0xFFFF, p);
|
// _raw(NET__DEBUG, 0xFFFF, p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
while(processed < p->size) {
|
while(processed < p->size) {
|
||||||
subpacket_length=*(p->pBuffer+processed);
|
subpacket_length=*(p->pBuffer+processed);
|
||||||
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length);
|
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length);
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Extracting combined packet of length %d" __L, subpacket_length);
|
LogNetcode(_L "Extracting combined packet of length [{}]" __L, subpacket_length);
|
||||||
// _raw(NET__NET_CREATE_HEX, 0xFFFF, subp);
|
// _raw(NET__NET_CREATE_HEX, 0xFFFF, subp);
|
||||||
subp->copyInfo(p);
|
subp->copyInfo(p);
|
||||||
ProcessPacket(subp);
|
ProcessPacket(subp);
|
||||||
@@ -156,12 +156,12 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
while(processed<p->size) {
|
while(processed<p->size) {
|
||||||
EQRawApplicationPacket *ap=nullptr;
|
EQRawApplicationPacket *ap=nullptr;
|
||||||
if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) {
|
if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length);
|
LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length);
|
||||||
ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length);
|
ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length);
|
||||||
processed+=subpacket_length+1;
|
processed+=subpacket_length+1;
|
||||||
} else {
|
} else {
|
||||||
subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1));
|
subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1));
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length);
|
LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length);
|
||||||
ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length);
|
ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length);
|
||||||
processed+=subpacket_length+3;
|
processed+=subpacket_length+3;
|
||||||
}
|
}
|
||||||
@@ -176,29 +176,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
case OP_Packet: {
|
case OP_Packet: {
|
||||||
if(!p->pBuffer || (p->Size() < 4))
|
if(!p->pBuffer || (p->Size() < 4))
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_Packet that was of malformed size" __L);
|
LogNetcode(_L "Received OP_Packet that was of malformed size" __L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
||||||
SeqOrder check=CompareSequence(NextInSeq,seq);
|
SeqOrder check=CompareSequence(NextInSeq,seq);
|
||||||
if (check == SeqFuture) {
|
if (check == SeqFuture) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Future OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
|
LogNetcode(_L "Future OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq);
|
||||||
// _raw(NET__DEBUG, seq, p);
|
// _raw(NET__DEBUG, seq, p);
|
||||||
|
|
||||||
PacketQueue[seq]=p->Copy();
|
PacketQueue[seq]=p->Copy();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size());
|
LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size());
|
||||||
|
|
||||||
//SendOutOfOrderAck(seq);
|
//SendOutOfOrderAck(seq);
|
||||||
|
|
||||||
} else if (check == SeqPast) {
|
} else if (check == SeqPast) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Duplicate OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
|
LogNetcode(_L "Duplicate OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq);
|
||||||
// _raw(NET__DEBUG, seq, p);
|
// _raw(NET__DEBUG, seq, p);
|
||||||
SendOutOfOrderAck(seq); //we already got this packet but it was out of order
|
SendOutOfOrderAck(seq); //we already got this packet but it was out of order
|
||||||
} else {
|
} else {
|
||||||
// In case we did queue one before as well.
|
// In case we did queue one before as well.
|
||||||
EQProtocolPacket *qp=RemoveQueue(seq);
|
EQProtocolPacket *qp=RemoveQueue(seq);
|
||||||
if (qp) {
|
if (qp) {
|
||||||
Log(Logs::General, Logs::Netcode, "[NET_TRACE] OP_Packet: Removing older queued packet with sequence %d", seq);
|
LogNetcode("[NET_TRACE] OP_Packet: Removing older queued packet with sequence [{}]", seq);
|
||||||
delete qp;
|
delete qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
// Check for an embedded OP_AppCombinded (protocol level 0x19)
|
// Check for an embedded OP_AppCombinded (protocol level 0x19)
|
||||||
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
|
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
|
||||||
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2);
|
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2);
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "seq %d, Extracting combined packet of length %d" __L, seq, subp->size);
|
LogNetcode(_L "seq [{}], Extracting combined packet of length [{}]" __L, seq, subp->size);
|
||||||
// _raw(NET__NET_CREATE_HEX, seq, subp);
|
// _raw(NET__NET_CREATE_HEX, seq, subp);
|
||||||
subp->copyInfo(p);
|
subp->copyInfo(p);
|
||||||
ProcessPacket(subp);
|
ProcessPacket(subp);
|
||||||
@@ -226,29 +226,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
case OP_Fragment: {
|
case OP_Fragment: {
|
||||||
if(!p->pBuffer || (p->Size() < 4))
|
if(!p->pBuffer || (p->Size() < 4))
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_Fragment that was of malformed size" __L);
|
LogNetcode(_L "Received OP_Fragment that was of malformed size" __L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
||||||
SeqOrder check=CompareSequence(NextInSeq,seq);
|
SeqOrder check=CompareSequence(NextInSeq,seq);
|
||||||
if (check == SeqFuture) {
|
if (check == SeqFuture) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Future OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
|
LogNetcode(_L "Future OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq);
|
||||||
// _raw(NET__DEBUG, seq, p);
|
// _raw(NET__DEBUG, seq, p);
|
||||||
|
|
||||||
PacketQueue[seq]=p->Copy();
|
PacketQueue[seq]=p->Copy();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "OP_Fragment Queue size=%d" __L, PacketQueue.size());
|
LogNetcode(_L "OP_Fragment Queue size=[{}]" __L, PacketQueue.size());
|
||||||
|
|
||||||
//SendOutOfOrderAck(seq);
|
//SendOutOfOrderAck(seq);
|
||||||
|
|
||||||
} else if (check == SeqPast) {
|
} else if (check == SeqPast) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Duplicate OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
|
LogNetcode(_L "Duplicate OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq);
|
||||||
// _raw(NET__DEBUG, seq, p);
|
// _raw(NET__DEBUG, seq, p);
|
||||||
SendOutOfOrderAck(seq);
|
SendOutOfOrderAck(seq);
|
||||||
} else {
|
} else {
|
||||||
// In case we did queue one before as well.
|
// In case we did queue one before as well.
|
||||||
EQProtocolPacket *qp=RemoveQueue(seq);
|
EQProtocolPacket *qp=RemoveQueue(seq);
|
||||||
if (qp) {
|
if (qp) {
|
||||||
Log(Logs::General, Logs::Netcode, "[NET_TRACE] OP_Fragment: Removing older queued packet with sequence %d", seq);
|
LogNetcode("[NET_TRACE] OP_Fragment: Removing older queued packet with sequence [{}]", seq);
|
||||||
delete qp;
|
delete qp;
|
||||||
}
|
}
|
||||||
SetNextAckToSend(seq);
|
SetNextAckToSend(seq);
|
||||||
@@ -256,18 +256,18 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
if (oversize_buffer) {
|
if (oversize_buffer) {
|
||||||
memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2);
|
memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2);
|
||||||
oversize_offset+=p->size-2;
|
oversize_offset+=p->size-2;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Fragment of oversized of length %d, seq %d: now at %d/%d" __L, p->size-2, seq, oversize_offset, oversize_length);
|
LogNetcode(_L "Fragment of oversized of length [{}], seq [{}]: now at [{}]/[{}]" __L, p->size-2, seq, oversize_offset, oversize_length);
|
||||||
if (oversize_offset==oversize_length) {
|
if (oversize_offset==oversize_length) {
|
||||||
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
|
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
|
||||||
EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset);
|
EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset);
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "seq %d, Extracting combined oversize packet of length %d" __L, seq, subp->size);
|
LogNetcode(_L "seq [{}], Extracting combined oversize packet of length [{}]" __L, seq, subp->size);
|
||||||
//// _raw(NET__NET_CREATE_HEX, subp);
|
//// _raw(NET__NET_CREATE_HEX, subp);
|
||||||
subp->copyInfo(p);
|
subp->copyInfo(p);
|
||||||
ProcessPacket(subp);
|
ProcessPacket(subp);
|
||||||
delete subp;
|
delete subp;
|
||||||
} else {
|
} else {
|
||||||
EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset);
|
EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset);
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "seq %d, completed combined oversize packet of length %d" __L, seq, ap->size);
|
LogNetcode(_L "seq [{}], completed combined oversize packet of length [{}]" __L, seq, ap->size);
|
||||||
if (ap) {
|
if (ap) {
|
||||||
ap->copyInfo(p);
|
ap->copyInfo(p);
|
||||||
InboundQueuePush(ap);
|
InboundQueuePush(ap);
|
||||||
@@ -282,20 +282,20 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
oversize_buffer=new unsigned char[oversize_length];
|
oversize_buffer=new unsigned char[oversize_length];
|
||||||
memcpy(oversize_buffer,p->pBuffer+6,p->size-6);
|
memcpy(oversize_buffer,p->pBuffer+6,p->size-6);
|
||||||
oversize_offset=p->size-6;
|
oversize_offset=p->size-6;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "First fragment of oversized of seq %d: now at %d/%d" __L, seq, oversize_offset, oversize_length);
|
LogNetcode(_L "First fragment of oversized of seq [{}]: now at [{}]/[{}]" __L, seq, oversize_offset, oversize_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_KeepAlive: {
|
case OP_KeepAlive: {
|
||||||
NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size));
|
NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size));
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received and queued reply to keep alive" __L);
|
LogNetcode(_L "Received and queued reply to keep alive" __L);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_Ack: {
|
case OP_Ack: {
|
||||||
if(!p->pBuffer || (p->Size() < 4))
|
if(!p->pBuffer || (p->Size() < 4))
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_Ack that was of malformed size" __L);
|
LogNetcode(_L "Received OP_Ack that was of malformed size" __L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
||||||
@@ -309,11 +309,11 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
case OP_SessionRequest: {
|
case OP_SessionRequest: {
|
||||||
if(p->Size() < sizeof(SessionRequest))
|
if(p->Size() < sizeof(SessionRequest))
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest that was of malformed size" __L);
|
LogNetcode(_L "Received OP_SessionRequest that was of malformed size" __L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (GetState()==ESTABLISHED) {
|
if (GetState()==ESTABLISHED) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest in ESTABLISHED state (%d) streamactive (%i) attempt (%i)" __L, GetState(),streamactive,sessionAttempts);
|
LogNetcode(_L "Received OP_SessionRequest in ESTABLISHED state ([{}]) streamactive ([{}]) attempt ([{}])" __L, GetState(),streamactive,sessionAttempts);
|
||||||
|
|
||||||
// client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case
|
// client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case
|
||||||
// streamactive means we identified the opcode for the stream, we cannot re-establish this connection
|
// streamactive means we identified the opcode for the stream, we cannot re-establish this connection
|
||||||
@@ -331,7 +331,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
SessionRequest *Request=(SessionRequest *)p->pBuffer;
|
SessionRequest *Request=(SessionRequest *)p->pBuffer;
|
||||||
Session=ntohl(Request->Session);
|
Session=ntohl(Request->Session);
|
||||||
SetMaxLen(ntohl(Request->MaxLength));
|
SetMaxLen(ntohl(Request->MaxLength));
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest: session %lu, maxlen %d" __L, (unsigned long)Session, MaxLen);
|
LogNetcode(_L "Received OP_SessionRequest: session [{}], maxlen [{}]" __L, (unsigned long)Session, MaxLen);
|
||||||
SetState(ESTABLISHED);
|
SetState(ESTABLISHED);
|
||||||
Key=0x11223344;
|
Key=0x11223344;
|
||||||
SendSessionResponse();
|
SendSessionResponse();
|
||||||
@@ -340,7 +340,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
case OP_SessionResponse: {
|
case OP_SessionResponse: {
|
||||||
if(p->Size() < sizeof(SessionResponse))
|
if(p->Size() < sizeof(SessionResponse))
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionResponse that was of malformed size" __L);
|
LogNetcode(_L "Received OP_SessionResponse that was of malformed size" __L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +356,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
compressed=(Response->Format&FLAG_COMPRESSED);
|
compressed=(Response->Format&FLAG_COMPRESSED);
|
||||||
encoded=(Response->Format&FLAG_ENCODED);
|
encoded=(Response->Format&FLAG_ENCODED);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionResponse: session %lu, maxlen %d, key %lu, compressed? %s, encoded? %s" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no");
|
LogNetcode(_L "Received OP_SessionResponse: session [{}], maxlen [{}], key [{}], compressed? [{}], encoded? [{}]" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no");
|
||||||
|
|
||||||
// Kinda kludgy, but trie for now
|
// Kinda kludgy, but trie for now
|
||||||
if (StreamType==UnknownStream) {
|
if (StreamType==UnknownStream) {
|
||||||
@@ -379,17 +379,17 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
EQStreamState state = GetState();
|
EQStreamState state = GetState();
|
||||||
if(state == ESTABLISHED) {
|
if(state == ESTABLISHED) {
|
||||||
//client initiated disconnect?
|
//client initiated disconnect?
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect." __L);
|
LogNetcode(_L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect" __L);
|
||||||
_SendDisconnect();
|
_SendDisconnect();
|
||||||
SetState(CLOSED);
|
SetState(CLOSED);
|
||||||
} else if(state == CLOSING) {
|
} else if(state == CLOSING) {
|
||||||
//we were waiting for this anyways, ignore pending messages, send the reply and be closed.
|
//we were waiting for this anyways, ignore pending messages, send the reply and be closed.
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though." __L);
|
LogNetcode(_L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though" __L);
|
||||||
_SendDisconnect();
|
_SendDisconnect();
|
||||||
SetState(CLOSED);
|
SetState(CLOSED);
|
||||||
} else {
|
} else {
|
||||||
//we are expecting this (or have already gotten it, but dont care either way)
|
//we are expecting this (or have already gotten it, but dont care either way)
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received expected OP_SessionDisconnect. Moving to closed state." __L);
|
LogNetcode(_L "Received expected OP_SessionDisconnect. Moving to closed state" __L);
|
||||||
SetState(CLOSED);
|
SetState(CLOSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,14 +397,14 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
case OP_OutOfOrderAck: {
|
case OP_OutOfOrderAck: {
|
||||||
if(!p->pBuffer || (p->Size() < 4))
|
if(!p->pBuffer || (p->Size() < 4))
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck that was of malformed size" __L);
|
LogNetcode(_L "Received OP_OutOfOrderAck that was of malformed size" __L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
|
||||||
MOutboundQueue.lock();
|
MOutboundQueue.lock();
|
||||||
|
|
||||||
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Pre-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
LogNetcode(_L "Pre-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if the packet they got out of order is between our last acked packet and the last sent packet, then its valid.
|
//if the packet they got out of order is between our last acked packet and the last sent packet, then its valid.
|
||||||
@@ -414,7 +414,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
|
|
||||||
uint16 sqsize = SequencedQueue.size();
|
uint16 sqsize = SequencedQueue.size();
|
||||||
uint16 index = seq - SequencedBase;
|
uint16 index = seq - SequencedBase;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize);
|
LogNetcode(_L "OP_OutOfOrderAck marking packet acked in queue (queue index = [{}], queue size = [{}])" __L, index, sqsize);
|
||||||
if (index < sqsize) {
|
if (index < sqsize) {
|
||||||
SequencedQueue[index]->acked = true;
|
SequencedQueue[index]->acked = true;
|
||||||
// flag packets for a resend
|
// flag packets for a resend
|
||||||
@@ -423,7 +423,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) {
|
for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) {
|
||||||
if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) {
|
if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) {
|
||||||
(*sitr)->sent_time = 0;
|
(*sitr)->sent_time = 0;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck Flagging packet %d for retransmission" __L, SequencedBase + count);
|
LogNetcode(_L "OP_OutOfOrderAck Flagging packet [{}] for retransmission" __L, SequencedBase + count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,11 +432,11 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
retransmittimer = Timer::GetCurrentTime();
|
retransmittimer = Timer::GetCurrentTime();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for out-of-window %d. Window (%d->%d)." __L, seq, SequencedBase, NextOutSeq);
|
LogNetcode(_L "Received OP_OutOfOrderAck for out-of-window [{}]. Window ([{}]->[{}])" __L, seq, SequencedBase, NextOutSeq);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Post-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
LogNetcode(_L "Post-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
||||||
}
|
}
|
||||||
|
|
||||||
MOutboundQueue.unlock();
|
MOutboundQueue.unlock();
|
||||||
@@ -445,7 +445,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
case OP_SessionStatRequest: {
|
case OP_SessionStatRequest: {
|
||||||
if(p->Size() < sizeof(ClientSessionStats))
|
if(p->Size() < sizeof(ClientSessionStats))
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatRequest that was of malformed size" __L);
|
LogNetcode(_L "Received OP_SessionStatRequest that was of malformed size" __L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer;
|
ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer;
|
||||||
@@ -468,7 +468,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
retransmittimeout += 300;
|
retransmittimeout += 300;
|
||||||
if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX)
|
if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX)
|
||||||
retransmittimeout = RETRANSMIT_TIMEOUT_MAX;
|
retransmittimeout = RETRANSMIT_TIMEOUT_MAX;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout);
|
LogNetcode(_L "Retransmit timeout recalculated to [{}]ms" __L, retransmittimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,11 +485,11 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_SessionStatResponse: {
|
case OP_SessionStatResponse: {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatResponse. Ignoring." __L);
|
LogNetcode(_L "Received OP_SessionStatResponse. Ignoring" __L);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_OutOfSession: {
|
case OP_OutOfSession: {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfSession. Ignoring." __L);
|
LogNetcode(_L "Received OP_OutOfSession. Ignoring" __L);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -520,7 +520,7 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if(OpMgr == nullptr || *OpMgr == nullptr) {
|
if(OpMgr == nullptr || *OpMgr == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Packet enqueued into a stream with no opcode manager, dropping." __L);
|
LogNetcode(_L "Packet enqueued into a stream with no opcode manager, dropping" __L);
|
||||||
delete pack;
|
delete pack;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -559,18 +559,18 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
|||||||
|
|
||||||
// Convert the EQApplicationPacket to 1 or more EQProtocolPackets
|
// Convert the EQApplicationPacket to 1 or more EQProtocolPackets
|
||||||
if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2)
|
if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2)
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->Size());
|
LogNetcode(_L "Making oversized packet, len [{}]" __L, p->Size());
|
||||||
|
|
||||||
auto tmpbuff = new unsigned char[p->size + 3];
|
auto tmpbuff = new unsigned char[p->size + 3];
|
||||||
length=p->serialize(opcode, tmpbuff);
|
length=p->serialize(opcode, tmpbuff);
|
||||||
if (length != p->Size())
|
if (length != p->Size())
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Packet adjustment, len %d to %d" __L, p->Size(), length);
|
LogNetcode(_L "Packet adjustment, len [{}] to [{}]" __L, p->Size(), length);
|
||||||
|
|
||||||
auto out = new EQProtocolPacket(OP_Fragment, nullptr, MaxLen - 4);
|
auto out = new EQProtocolPacket(OP_Fragment, nullptr, MaxLen - 4);
|
||||||
*(uint32 *)(out->pBuffer+2)=htonl(length);
|
*(uint32 *)(out->pBuffer+2)=htonl(length);
|
||||||
used=MaxLen-10;
|
used=MaxLen-10;
|
||||||
memcpy(out->pBuffer+6,tmpbuff,used);
|
memcpy(out->pBuffer+6,tmpbuff,used);
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Payload size %d in the packet" __L, used, length, p->size);
|
LogNetcode(_L "First fragment: used [{}]/[{}]. Payload size [{}] in the packet" __L, used, length, p->size);
|
||||||
SequencedPush(out);
|
SequencedPush(out);
|
||||||
|
|
||||||
|
|
||||||
@@ -581,7 +581,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
|
|||||||
out->size=chunksize+2;
|
out->size=chunksize+2;
|
||||||
SequencedPush(out);
|
SequencedPush(out);
|
||||||
used+=chunksize;
|
used+=chunksize;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, length);
|
LogNetcode(_L "Subsequent fragment: len [{}], used [{}]/[{}]" __L, chunksize, used, length);
|
||||||
}
|
}
|
||||||
delete p;
|
delete p;
|
||||||
delete[] tmpbuff;
|
delete[] tmpbuff;
|
||||||
@@ -623,7 +623,7 @@ void EQStream::SequencedPush(EQProtocolPacket *p)
|
|||||||
void EQStream::NonSequencedPush(EQProtocolPacket *p)
|
void EQStream::NonSequencedPush(EQProtocolPacket *p)
|
||||||
{
|
{
|
||||||
MOutboundQueue.lock();
|
MOutboundQueue.lock();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Pushing non-sequenced packet of length %d" __L, p->size);
|
LogNetcode(_L "Pushing non-sequenced packet of length [{}]" __L, p->size);
|
||||||
NonSequencedQueue.push(p);
|
NonSequencedQueue.push(p);
|
||||||
MOutboundQueue.unlock();
|
MOutboundQueue.unlock();
|
||||||
}
|
}
|
||||||
@@ -631,14 +631,14 @@ void EQStream::NonSequencedPush(EQProtocolPacket *p)
|
|||||||
void EQStream::SendAck(uint16 seq)
|
void EQStream::SendAck(uint16 seq)
|
||||||
{
|
{
|
||||||
uint16 Seq=htons(seq);
|
uint16 Seq=htons(seq);
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Sending ack with sequence %d" __L, seq);
|
LogNetcode(_L "Sending ack with sequence [{}]" __L, seq);
|
||||||
SetLastAckSent(seq);
|
SetLastAckSent(seq);
|
||||||
NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16)));
|
NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQStream::SendOutOfOrderAck(uint16 seq)
|
void EQStream::SendOutOfOrderAck(uint16 seq)
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Sending out of order ack with sequence %d" __L, seq);
|
LogNetcode(_L "Sending out of order ack with sequence [{}]" __L, seq);
|
||||||
uint16 Seq=htons(seq);
|
uint16 Seq=htons(seq);
|
||||||
NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16)));
|
NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16)));
|
||||||
}
|
}
|
||||||
@@ -688,24 +688,24 @@ void EQStream::Write(int eq_fd)
|
|||||||
// If we don't have a packet to try to combine into, use this one as the base
|
// If we don't have a packet to try to combine into, use this one as the base
|
||||||
// And remove it form the queue
|
// And remove it form the queue
|
||||||
p = NonSequencedQueue.front();
|
p = NonSequencedQueue.front();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Starting combined packet with non-seq packet of len %d" __L, p->size);
|
LogNetcode(_L "Starting combined packet with non-seq packet of len [{}]" __L, p->size);
|
||||||
NonSequencedQueue.pop();
|
NonSequencedQueue.pop();
|
||||||
} else if (!p->combine(NonSequencedQueue.front())) {
|
} else if (!p->combine(NonSequencedQueue.front())) {
|
||||||
// Trying to combine this packet with the base didn't work (too big maybe)
|
// Trying to combine this packet with the base didn't work (too big maybe)
|
||||||
// So just send the base packet (we'll try this packet again later)
|
// So just send the base packet (we'll try this packet again later)
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next non-seq packet is len %d" __L, p->size, (NonSequencedQueue.front())->size);
|
LogNetcode(_L "Combined packet full at len [{}], next non-seq packet is len [{}]" __L, p->size, (NonSequencedQueue.front())->size);
|
||||||
ReadyToSend.push(p);
|
ReadyToSend.push(p);
|
||||||
BytesWritten+=p->size;
|
BytesWritten+=p->size;
|
||||||
p=nullptr;
|
p=nullptr;
|
||||||
|
|
||||||
if (BytesWritten > threshold) {
|
if (BytesWritten > threshold) {
|
||||||
// Sent enough this round, lets stop to be fair
|
// Sent enough this round, lets stop to be fair
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in nonseq (%d > %d)" __L, BytesWritten, threshold);
|
LogNetcode(_L "Exceeded write threshold in nonseq ([{}] > [{}])" __L, BytesWritten, threshold);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Combine worked, so just remove this packet and it's spot in the queue
|
// Combine worked, so just remove this packet and it's spot in the queue
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Combined non-seq packet of len %d, yeilding %d combined." __L, (NonSequencedQueue.front())->size, p->size);
|
LogNetcode(_L "Combined non-seq packet of len [{}], yeilding [{}] combined" __L, (NonSequencedQueue.front())->size, p->size);
|
||||||
delete NonSequencedQueue.front();
|
delete NonSequencedQueue.front();
|
||||||
NonSequencedQueue.pop();
|
NonSequencedQueue.pop();
|
||||||
}
|
}
|
||||||
@@ -718,7 +718,7 @@ void EQStream::Write(int eq_fd)
|
|||||||
uint16 seq_send = SequencedBase + count; //just for logging...
|
uint16 seq_send = SequencedBase + count; //just for logging...
|
||||||
|
|
||||||
if(SequencedQueue.empty()) {
|
if(SequencedQueue.empty()) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq);
|
LogNetcode(_L "Tried to write a packet with an empty queue ([{}] is past next out [{}])" __L, seq_send, NextOutSeq);
|
||||||
SeqEmpty=true;
|
SeqEmpty=true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -728,35 +728,35 @@ void EQStream::Write(int eq_fd)
|
|||||||
++sitr;
|
++sitr;
|
||||||
++count;
|
++count;
|
||||||
if (p) {
|
if (p) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size);
|
LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size);
|
||||||
ReadyToSend.push(p);
|
ReadyToSend.push(p);
|
||||||
BytesWritten += p->size;
|
BytesWritten += p->size;
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
}
|
}
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Not retransmitting seq packet %d because already marked as acked" __L, seq_send);
|
LogNetcode(_L "Not retransmitting seq packet [{}] because already marked as acked" __L, seq_send);
|
||||||
} else if (!p) {
|
} else if (!p) {
|
||||||
// If we don't have a packet to try to combine into, use this one as the base
|
// If we don't have a packet to try to combine into, use this one as the base
|
||||||
// Copy it first as it will still live until it is acked
|
// Copy it first as it will still live until it is acked
|
||||||
p=(*sitr)->Copy();
|
p=(*sitr)->Copy();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size);
|
LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size);
|
||||||
(*sitr)->sent_time = Timer::GetCurrentTime();
|
(*sitr)->sent_time = Timer::GetCurrentTime();
|
||||||
++sitr;
|
++sitr;
|
||||||
++count;
|
++count;
|
||||||
} else if (!p->combine(*sitr)) {
|
} else if (!p->combine(*sitr)) {
|
||||||
// Trying to combine this packet with the base didn't work (too big maybe)
|
// Trying to combine this packet with the base didn't work (too big maybe)
|
||||||
// So just send the base packet (we'll try this packet again later)
|
// So just send the base packet (we'll try this packet again later)
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send + 1, (*sitr)->size);
|
LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send + 1, (*sitr)->size);
|
||||||
ReadyToSend.push(p);
|
ReadyToSend.push(p);
|
||||||
BytesWritten+=p->size;
|
BytesWritten+=p->size;
|
||||||
p=nullptr;
|
p=nullptr;
|
||||||
if ((*sitr)->opcode != OP_Fragment && BytesWritten > threshold) {
|
if ((*sitr)->opcode != OP_Fragment && BytesWritten > threshold) {
|
||||||
// Sent enough this round, lets stop to be fair
|
// Sent enough this round, lets stop to be fair
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold);
|
LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Combine worked
|
// Combine worked
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size);
|
LogNetcode(_L "Combined seq packet [{}] of len [{}], yeilding [{}] combined" __L, seq_send, (*sitr)->size, p->size);
|
||||||
(*sitr)->sent_time = Timer::GetCurrentTime();
|
(*sitr)->sent_time = Timer::GetCurrentTime();
|
||||||
++sitr;
|
++sitr;
|
||||||
++count;
|
++count;
|
||||||
@@ -766,7 +766,7 @@ void EQStream::Write(int eq_fd)
|
|||||||
++sitr;
|
++sitr;
|
||||||
++count;
|
++count;
|
||||||
if (p) {
|
if (p) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size);
|
LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size);
|
||||||
ReadyToSend.push(p);
|
ReadyToSend.push(p);
|
||||||
BytesWritten += p->size;
|
BytesWritten += p->size;
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
@@ -776,25 +776,25 @@ void EQStream::Write(int eq_fd)
|
|||||||
// Copy it first as it will still live until it is acked
|
// Copy it first as it will still live until it is acked
|
||||||
p=(*sitr)->Copy();
|
p=(*sitr)->Copy();
|
||||||
(*sitr)->sent_time = Timer::GetCurrentTime();
|
(*sitr)->sent_time = Timer::GetCurrentTime();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size);
|
LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size);
|
||||||
++sitr;
|
++sitr;
|
||||||
++count;
|
++count;
|
||||||
} else if (!p->combine(*sitr)) {
|
} else if (!p->combine(*sitr)) {
|
||||||
// Trying to combine this packet with the base didn't work (too big maybe)
|
// Trying to combine this packet with the base didn't work (too big maybe)
|
||||||
// So just send the base packet (we'll try this packet again later)
|
// So just send the base packet (we'll try this packet again later)
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size);
|
LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send, (*sitr)->size);
|
||||||
ReadyToSend.push(p);
|
ReadyToSend.push(p);
|
||||||
BytesWritten+=p->size;
|
BytesWritten+=p->size;
|
||||||
p=nullptr;
|
p=nullptr;
|
||||||
|
|
||||||
if (BytesWritten > threshold) {
|
if (BytesWritten > threshold) {
|
||||||
// Sent enough this round, lets stop to be fair
|
// Sent enough this round, lets stop to be fair
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold);
|
LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Combine worked
|
// Combine worked
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yielding %d combined." __L, seq_send, (*sitr)->size, p->size);
|
LogNetcode(_L "Combined seq packet [{}] of len [{}], yielding [{}] combined" __L, seq_send, (*sitr)->size, p->size);
|
||||||
(*sitr)->sent_time = Timer::GetCurrentTime();
|
(*sitr)->sent_time = Timer::GetCurrentTime();
|
||||||
++sitr;
|
++sitr;
|
||||||
++count;
|
++count;
|
||||||
@@ -802,7 +802,7 @@ void EQStream::Write(int eq_fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Post send Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
LogNetcode(_L "Post send Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No more sequenced packets
|
// No more sequenced packets
|
||||||
@@ -814,7 +814,7 @@ void EQStream::Write(int eq_fd)
|
|||||||
|
|
||||||
// We have a packet still, must have run out of both seq and non-seq, so send it
|
// We have a packet still, must have run out of both seq and non-seq, so send it
|
||||||
if (p) {
|
if (p) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size);
|
LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size);
|
||||||
ReadyToSend.push(p);
|
ReadyToSend.push(p);
|
||||||
BytesWritten+=p->size;
|
BytesWritten+=p->size;
|
||||||
}
|
}
|
||||||
@@ -831,7 +831,7 @@ void EQStream::Write(int eq_fd)
|
|||||||
if(SeqEmpty && NonSeqEmpty) {
|
if(SeqEmpty && NonSeqEmpty) {
|
||||||
//no more data to send
|
//no more data to send
|
||||||
if(CheckState(CLOSING)) {
|
if(CheckState(CLOSING)) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "All outgoing data flushed, closing stream." __L );
|
LogNetcode(_L "All outgoing data flushed, closing stream" __L );
|
||||||
//we are waiting for the queues to empty, now we can do our disconnect.
|
//we are waiting for the queues to empty, now we can do our disconnect.
|
||||||
//this packet will not actually go out until the next call to Write().
|
//this packet will not actually go out until the next call to Write().
|
||||||
_SendDisconnect();
|
_SendDisconnect();
|
||||||
@@ -910,7 +910,7 @@ void EQStream::SendSessionRequest()
|
|||||||
Request->Session=htonl(time(nullptr));
|
Request->Session=htonl(time(nullptr));
|
||||||
Request->MaxLength=htonl(512);
|
Request->MaxLength=htonl(512);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionRequest: session %lu, maxlen=%d" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength));
|
LogNetcode(_L "Sending OP_SessionRequest: session [{}], maxlen=[{}]" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength));
|
||||||
|
|
||||||
NonSequencedPush(out);
|
NonSequencedPush(out);
|
||||||
}
|
}
|
||||||
@@ -924,7 +924,7 @@ void EQStream::_SendDisconnect()
|
|||||||
*(uint32 *)out->pBuffer=htonl(Session);
|
*(uint32 *)out->pBuffer=htonl(Session);
|
||||||
NonSequencedPush(out);
|
NonSequencedPush(out);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionDisconnect: session %lu" __L, (unsigned long)Session);
|
LogNetcode(_L "Sending OP_SessionDisconnect: session [{}]" __L, (unsigned long)Session);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQStream::InboundQueuePush(EQRawApplicationPacket *p)
|
void EQStream::InboundQueuePush(EQRawApplicationPacket *p)
|
||||||
@@ -976,7 +976,7 @@ EQRawApplicationPacket *p=nullptr;
|
|||||||
if(OpMgr != nullptr && *OpMgr != nullptr) {
|
if(OpMgr != nullptr && *OpMgr != nullptr) {
|
||||||
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
|
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
|
||||||
if(emu_op == OP_Unknown) {
|
if(emu_op == OP_Unknown) {
|
||||||
Log(Logs::General, Logs::Netcode, "Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode);
|
LogNetcode("Unable to convert EQ opcode {:#04x} to an Application opcode", p->opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
p->SetOpcode(emu_op);
|
p->SetOpcode(emu_op);
|
||||||
@@ -1004,7 +1004,7 @@ void EQStream::InboundQueueClear()
|
|||||||
{
|
{
|
||||||
EQApplicationPacket *p=nullptr;
|
EQApplicationPacket *p=nullptr;
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Clearing inbound queue" __L);
|
LogNetcode(_L "Clearing inbound queue" __L);
|
||||||
|
|
||||||
MInboundQueue.lock();
|
MInboundQueue.lock();
|
||||||
if (!InboundQueue.empty()) {
|
if (!InboundQueue.empty()) {
|
||||||
@@ -1047,7 +1047,7 @@ void EQStream::OutboundQueueClear()
|
|||||||
{
|
{
|
||||||
EQProtocolPacket *p=nullptr;
|
EQProtocolPacket *p=nullptr;
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Clearing outbound queue" __L);
|
LogNetcode(_L "Clearing outbound queue" __L);
|
||||||
|
|
||||||
MOutboundQueue.lock();
|
MOutboundQueue.lock();
|
||||||
while(!NonSequencedQueue.empty()) {
|
while(!NonSequencedQueue.empty()) {
|
||||||
@@ -1069,7 +1069,7 @@ void EQStream::PacketQueueClear()
|
|||||||
{
|
{
|
||||||
EQProtocolPacket *p=nullptr;
|
EQProtocolPacket *p=nullptr;
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Clearing future packet queue" __L);
|
LogNetcode(_L "Clearing future packet queue" __L);
|
||||||
|
|
||||||
if(!PacketQueue.empty()) {
|
if(!PacketQueue.empty()) {
|
||||||
std::map<unsigned short,EQProtocolPacket *>::iterator itr;
|
std::map<unsigned short,EQProtocolPacket *>::iterator itr;
|
||||||
@@ -1101,7 +1101,7 @@ void EQStream::Process(const unsigned char *buffer, const uint32 length)
|
|||||||
delete p;
|
delete p;
|
||||||
ProcessQueue();
|
ProcessQueue();
|
||||||
} else {
|
} else {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Incoming packet failed checksum" __L);
|
LogNetcode(_L "Incoming packet failed checksum" __L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1132,23 +1132,23 @@ std::deque<EQProtocolPacket *>::iterator itr, tmp;
|
|||||||
SeqOrder ord = CompareSequence(SequencedBase, seq);
|
SeqOrder ord = CompareSequence(SequencedBase, seq);
|
||||||
if(ord == SeqInOrder) {
|
if(ord == SeqInOrder) {
|
||||||
//they are not acking anything new...
|
//they are not acking anything new...
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received an ack with no window advancement (seq %d)." __L, seq);
|
LogNetcode(_L "Received an ack with no window advancement (seq [{}])" __L, seq);
|
||||||
} else if(ord == SeqPast) {
|
} else if(ord == SeqPast) {
|
||||||
//they are nacking blocks going back before our buffer, wtf?
|
//they are nacking blocks going back before our buffer, wtf?
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received an ack with backward window advancement (they gave %d, our window starts at %d). This is bad." __L, seq, SequencedBase);
|
LogNetcode(_L "Received an ack with backward window advancement (they gave [{}], our window starts at [{}]). This is bad" __L, seq, SequencedBase);
|
||||||
} else {
|
} else {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Received an ack up through sequence %d. Our base is %d." __L, seq, SequencedBase);
|
LogNetcode(_L "Received an ack up through sequence [{}]. Our base is [{}]" __L, seq, SequencedBase);
|
||||||
|
|
||||||
|
|
||||||
//this is a good ack, we get to ack some blocks.
|
//this is a good ack, we get to ack some blocks.
|
||||||
seq++; //we stop at the block right after their ack, counting on the wrap of both numbers.
|
seq++; //we stop at the block right after their ack, counting on the wrap of both numbers.
|
||||||
while(SequencedBase != seq) {
|
while(SequencedBase != seq) {
|
||||||
if(SequencedQueue.empty()) {
|
if(SequencedQueue.empty()) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, SequencedQueue.size());
|
LogNetcode(_L "OUT OF PACKETS acked packet with sequence [{}]. Next send is [{}] before this" __L, (unsigned long)SequencedBase, SequencedQueue.size());
|
||||||
SequencedBase = NextOutSeq;
|
SequencedBase = NextOutSeq;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Removing acked packet with sequence %lu." __L, (unsigned long)SequencedBase);
|
LogNetcode(_L "Removing acked packet with sequence [{}]" __L, (unsigned long)SequencedBase);
|
||||||
//clean out the acked packet
|
//clean out the acked packet
|
||||||
delete SequencedQueue.front();
|
delete SequencedQueue.front();
|
||||||
SequencedQueue.pop_front();
|
SequencedQueue.pop_front();
|
||||||
@@ -1156,7 +1156,7 @@ std::deque<EQProtocolPacket *>::iterator itr, tmp;
|
|||||||
SequencedBase++;
|
SequencedBase++;
|
||||||
}
|
}
|
||||||
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Post-Ack on %d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
LogNetcode(_L "Post-Ack on [{}] Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,7 +1166,7 @@ std::deque<EQProtocolPacket *>::iterator itr, tmp;
|
|||||||
void EQStream::SetNextAckToSend(uint32 seq)
|
void EQStream::SetNextAckToSend(uint32 seq)
|
||||||
{
|
{
|
||||||
MAcks.lock();
|
MAcks.lock();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Set Next Ack To Send to %lu" __L, (unsigned long)seq);
|
LogNetcode(_L "Set Next Ack To Send to [{}]" __L, (unsigned long)seq);
|
||||||
NextAckToSend=seq;
|
NextAckToSend=seq;
|
||||||
MAcks.unlock();
|
MAcks.unlock();
|
||||||
}
|
}
|
||||||
@@ -1174,7 +1174,7 @@ void EQStream::SetNextAckToSend(uint32 seq)
|
|||||||
void EQStream::SetLastAckSent(uint32 seq)
|
void EQStream::SetLastAckSent(uint32 seq)
|
||||||
{
|
{
|
||||||
MAcks.lock();
|
MAcks.lock();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Set Last Ack Sent to %lu" __L, (unsigned long)seq);
|
LogNetcode(_L "Set Last Ack Sent to [{}]" __L, (unsigned long)seq);
|
||||||
LastAckSent=seq;
|
LastAckSent=seq;
|
||||||
MAcks.unlock();
|
MAcks.unlock();
|
||||||
}
|
}
|
||||||
@@ -1187,10 +1187,10 @@ void EQStream::ProcessQueue()
|
|||||||
|
|
||||||
EQProtocolPacket *qp=nullptr;
|
EQProtocolPacket *qp=nullptr;
|
||||||
while((qp=RemoveQueue(NextInSeq))!=nullptr) {
|
while((qp=RemoveQueue(NextInSeq))!=nullptr) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Processing Queued Packet: Seq=%d" __L, NextInSeq);
|
LogNetcode(_L "Processing Queued Packet: Seq=[{}]" __L, NextInSeq);
|
||||||
ProcessPacket(qp);
|
ProcessPacket(qp);
|
||||||
delete qp;
|
delete qp;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size());
|
LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1201,21 +1201,21 @@ EQProtocolPacket *qp=nullptr;
|
|||||||
if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) {
|
if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) {
|
||||||
qp=itr->second;
|
qp=itr->second;
|
||||||
PacketQueue.erase(itr);
|
PacketQueue.erase(itr);
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size());
|
LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size());
|
||||||
}
|
}
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQStream::SetStreamType(EQStreamType type)
|
void EQStream::SetStreamType(EQStreamType type)
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Changing stream type from %s to %s" __L, StreamTypeString(StreamType), StreamTypeString(type));
|
LogNetcode(_L "Changing stream type from [{}] to [{}]" __L, StreamTypeString(StreamType), StreamTypeString(type));
|
||||||
StreamType=type;
|
StreamType=type;
|
||||||
switch (StreamType) {
|
switch (StreamType) {
|
||||||
case LoginStream:
|
case LoginStream:
|
||||||
app_opcode_size=1;
|
app_opcode_size=1;
|
||||||
compressed=false;
|
compressed=false;
|
||||||
encoded=false;
|
encoded=false;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Login stream has app opcode size %d, is not compressed or encoded." __L, app_opcode_size);
|
LogNetcode(_L "Login stream has app opcode size [{}], is not compressed or encoded" __L, app_opcode_size);
|
||||||
break;
|
break;
|
||||||
case ChatOrMailStream:
|
case ChatOrMailStream:
|
||||||
case ChatStream:
|
case ChatStream:
|
||||||
@@ -1223,7 +1223,7 @@ void EQStream::SetStreamType(EQStreamType type)
|
|||||||
app_opcode_size=1;
|
app_opcode_size=1;
|
||||||
compressed=false;
|
compressed=false;
|
||||||
encoded=true;
|
encoded=true;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Chat/Mail stream has app opcode size %d, is not compressed, and is encoded." __L, app_opcode_size);
|
LogNetcode(_L "Chat/Mail stream has app opcode size [{}], is not compressed, and is encoded" __L, app_opcode_size);
|
||||||
break;
|
break;
|
||||||
case ZoneStream:
|
case ZoneStream:
|
||||||
case WorldStream:
|
case WorldStream:
|
||||||
@@ -1231,7 +1231,7 @@ void EQStream::SetStreamType(EQStreamType type)
|
|||||||
app_opcode_size=2;
|
app_opcode_size=2;
|
||||||
compressed=true;
|
compressed=true;
|
||||||
encoded=false;
|
encoded=false;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "World/Zone stream has app opcode size %d, is compressed, and is not encoded." __L, app_opcode_size);
|
LogNetcode(_L "World/Zone stream has app opcode size [{}], is compressed, and is not encoded" __L, app_opcode_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1281,7 +1281,7 @@ EQStream::SeqOrder EQStream::CompareSequence(uint16 expected_seq , uint16 seq)
|
|||||||
|
|
||||||
void EQStream::SetState(EQStreamState state) {
|
void EQStream::SetState(EQStreamState state) {
|
||||||
MState.lock();
|
MState.lock();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Changing state from %d to %d" __L, State, state);
|
LogNetcode(_L "Changing state from [{}] to [{}]" __L, State, state);
|
||||||
State=state;
|
State=state;
|
||||||
MState.unlock();
|
MState.unlock();
|
||||||
}
|
}
|
||||||
@@ -1293,29 +1293,29 @@ void EQStream::CheckTimeout(uint32 now, uint32 timeout) {
|
|||||||
|
|
||||||
EQStreamState orig_state = GetState();
|
EQStreamState orig_state = GetState();
|
||||||
if (orig_state == CLOSING && !outgoing_data) {
|
if (orig_state == CLOSING && !outgoing_data) {
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Out of data in closing state, disconnecting." __L);
|
LogNetcode(_L "Out of data in closing state, disconnecting" __L);
|
||||||
_SendDisconnect();
|
_SendDisconnect();
|
||||||
SetState(DISCONNECTING);
|
SetState(DISCONNECTING);
|
||||||
} else if (LastPacket && (now-LastPacket) > timeout) {
|
} else if (LastPacket && (now-LastPacket) > timeout) {
|
||||||
switch(orig_state) {
|
switch(orig_state) {
|
||||||
case CLOSING:
|
case CLOSING:
|
||||||
//if we time out in the closing state, they are not acking us, just give up
|
//if we time out in the closing state, they are not acking us, just give up
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in closing state. Moving to closed state." __L);
|
LogNetcode(_L "Timeout expired in closing state. Moving to closed state" __L);
|
||||||
_SendDisconnect();
|
_SendDisconnect();
|
||||||
SetState(CLOSED);
|
SetState(CLOSED);
|
||||||
break;
|
break;
|
||||||
case DISCONNECTING:
|
case DISCONNECTING:
|
||||||
//we timed out waiting for them to send us the disconnect reply, just give up.
|
//we timed out waiting for them to send us the disconnect reply, just give up.
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in disconnecting state. Moving to closed state." __L);
|
LogNetcode(_L "Timeout expired in disconnecting state. Moving to closed state" __L);
|
||||||
SetState(CLOSED);
|
SetState(CLOSED);
|
||||||
break;
|
break;
|
||||||
case CLOSED:
|
case CLOSED:
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in closed state??" __L);
|
LogNetcode(_L "Timeout expired in closed state??" __L);
|
||||||
break;
|
break;
|
||||||
case ESTABLISHED:
|
case ESTABLISHED:
|
||||||
//we timed out during normal operation. Try to be nice about it.
|
//we timed out during normal operation. Try to be nice about it.
|
||||||
//we will almost certainly time out again waiting for the disconnect reply, but oh well.
|
//we will almost certainly time out again waiting for the disconnect reply, but oh well.
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in established state. Closing connection." __L);
|
LogNetcode(_L "Timeout expired in established state. Closing connection" __L);
|
||||||
_SendDisconnect();
|
_SendDisconnect();
|
||||||
SetState(DISCONNECTING);
|
SetState(DISCONNECTING);
|
||||||
break;
|
break;
|
||||||
@@ -1342,7 +1342,7 @@ void EQStream::Decay()
|
|||||||
for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); ++sitr, count++) {
|
for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); ++sitr, count++) {
|
||||||
if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) {
|
if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) {
|
||||||
(*sitr)->sent_time = 0;
|
(*sitr)->sent_time = 0;
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Timeout exceeded for seq %d. Flagging packet for retransmission" __L, SequencedBase + count);
|
LogNetcode(_L "Timeout exceeded for seq [{}]. Flagging packet for retransmission" __L, SequencedBase + count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MOutboundQueue.unlock();
|
MOutboundQueue.unlock();
|
||||||
@@ -1384,12 +1384,12 @@ void EQStream::AdjustRates(uint32 average_delta)
|
|||||||
void EQStream::Close() {
|
void EQStream::Close() {
|
||||||
if(HasOutgoingData()) {
|
if(HasOutgoingData()) {
|
||||||
//there is pending data, wait for it to go out.
|
//there is pending data, wait for it to go out.
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Stream requested to Close(), but there is pending data, waiting for it." __L);
|
LogNetcode(_L "Stream requested to Close(), but there is pending data, waiting for it" __L);
|
||||||
SetState(CLOSING);
|
SetState(CLOSING);
|
||||||
} else {
|
} else {
|
||||||
//otherwise, we are done, we can drop immediately.
|
//otherwise, we are done, we can drop immediately.
|
||||||
_SendDisconnect();
|
_SendDisconnect();
|
||||||
Log(Logs::Detail, Logs::Netcode, _L "Stream closing immediate due to Close()" __L);
|
LogNetcode(_L "Stream closing immediate due to Close()" __L);
|
||||||
SetState(DISCONNECTING);
|
SetState(DISCONNECTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1417,19 +1417,19 @@ EQStream::MatchState EQStream::CheckSignature(const Signature *sig) {
|
|||||||
} else if(p->opcode == sig->first_eq_opcode) {
|
} else if(p->opcode == sig->first_eq_opcode) {
|
||||||
//opcode matches, check length..
|
//opcode matches, check length..
|
||||||
if(p->size == sig->first_length) {
|
if(p->size == sig->first_length) {
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x and length matched %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size);
|
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length matched [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size);
|
||||||
res = MatchSuccessful;
|
res = MatchSuccessful;
|
||||||
} else if(sig->first_length == 0) {
|
} else if(sig->first_length == 0) {
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x and length (%d) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size);
|
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length ([{}]) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size);
|
||||||
res = MatchSuccessful;
|
res = MatchSuccessful;
|
||||||
} else {
|
} else {
|
||||||
//opcode matched but length did not.
|
//opcode matched but length did not.
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x, but length %d did not match expected %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length);
|
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x}, but length [{}] did not match expected [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length);
|
||||||
res = MatchFailed;
|
res = MatchFailed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//first opcode did not match..
|
//first opcode did not match..
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode 0x%x did not match expected 0x%x", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode);
|
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode {:#04x} did not match expected {:#04x}", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode);
|
||||||
res = MatchFailed;
|
res = MatchFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -46,7 +46,7 @@ void EQStreamIdentifier::Process() {
|
|||||||
|
|
||||||
//first see if this stream has expired
|
//first see if this stream has expired
|
||||||
if(r.expire.Check(false)) {
|
if(r.expire.Check(false)) {
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d before timeout.", r.stream->GetRemoteAddr().c_str(), ntohs(r.stream->GetRemotePort()));
|
LogNetcode("[StreamIdentify] Unable to identify stream from [{}:{}] before timeout", r.stream->GetRemoteAddr().c_str(), ntohs(r.stream->GetRemotePort()));
|
||||||
r.stream->Close();
|
r.stream->Close();
|
||||||
|
|
||||||
cur = m_streams.erase(cur);
|
cur = m_streams.erase(cur);
|
||||||
@@ -62,23 +62,23 @@ void EQStreamIdentifier::Process() {
|
|||||||
}
|
}
|
||||||
if(r.stream->GetState() != ESTABLISHED) {
|
if(r.stream->GetState() != ESTABLISHED) {
|
||||||
//the stream closed before it was identified.
|
//the stream closed before it was identified.
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d before it closed.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()));
|
LogNetcode("[StreamIdentify] Unable to identify stream from [{}:{}] before it closed", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()));
|
||||||
switch(r.stream->GetState())
|
switch(r.stream->GetState())
|
||||||
{
|
{
|
||||||
case ESTABLISHED:
|
case ESTABLISHED:
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Established");
|
LogNetcode("[StreamIdentify] Stream state was Established");
|
||||||
break;
|
break;
|
||||||
case CLOSING:
|
case CLOSING:
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closing");
|
LogNetcode("[StreamIdentify] Stream state was Closing");
|
||||||
break;
|
break;
|
||||||
case DISCONNECTING:
|
case DISCONNECTING:
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Disconnecting");
|
LogNetcode("[StreamIdentify] Stream state was Disconnecting");
|
||||||
break;
|
break;
|
||||||
case CLOSED:
|
case CLOSED:
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closed");
|
LogNetcode("[StreamIdentify] Stream state was Closed");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Unestablished or unknown");
|
LogNetcode("[StreamIdentify] Stream state was Unestablished or unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
r.stream->ReleaseFromUse();
|
r.stream->ReleaseFromUse();
|
||||||
@@ -102,13 +102,13 @@ void EQStreamIdentifier::Process() {
|
|||||||
switch(res) {
|
switch(res) {
|
||||||
case EQStreamInterface::MatchNotReady:
|
case EQStreamInterface::MatchNotReady:
|
||||||
//the stream has not received enough packets to compare with this signature
|
//the stream has not received enough packets to compare with this signature
|
||||||
// Log.LogDebugType(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: Tried patch %s, but stream is not ready for it.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
|
// Log.LogDebugType(Logs::General, Logs::Netcode, "[StreamIdentify] %s:%d: Tried patch %s, but stream is not ready for it.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
|
||||||
all_ready = false;
|
all_ready = false;
|
||||||
break;
|
break;
|
||||||
case EQStreamInterface::MatchSuccessful: {
|
case EQStreamInterface::MatchSuccessful: {
|
||||||
//yay, a match.
|
//yay, a match.
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Identified stream %s:%d with signature %s", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
|
LogNetcode("[StreamIdentify] Identified stream [{}:{}] with signature [{}]", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
|
||||||
|
|
||||||
// before we assign the eqstream to an interface, let the stream recognize it is in use and the session should not be reset any further
|
// before we assign the eqstream to an interface, let the stream recognize it is in use and the session should not be reset any further
|
||||||
r.stream->SetActive(true);
|
r.stream->SetActive(true);
|
||||||
@@ -122,7 +122,7 @@ void EQStreamIdentifier::Process() {
|
|||||||
}
|
}
|
||||||
case EQStreamInterface::MatchFailed:
|
case EQStreamInterface::MatchFailed:
|
||||||
//do nothing...
|
//do nothing...
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: Tried patch %s, and it did not match.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
|
LogNetcode("[StreamIdentify] [{}:{}] Tried patch [{}] and it did not match", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ void EQStreamIdentifier::Process() {
|
|||||||
//if we checked all patches and did not find a match.
|
//if we checked all patches and did not find a match.
|
||||||
if(all_ready && !found_one) {
|
if(all_ready && !found_one) {
|
||||||
//the stream cannot be identified.
|
//the stream cannot be identified.
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d, no match found.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()));
|
LogNetcode("[StreamIdentify] Unable to identify stream from [{}:{}], no match found", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()));
|
||||||
r.stream->ReleaseFromUse();
|
r.stream->ReleaseFromUse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ struct EQStreamManagerInterfaceOptions
|
|||||||
|
|
||||||
EQStreamManagerInterfaceOptions(int port, bool encoded, bool compressed) {
|
EQStreamManagerInterfaceOptions(int port, bool encoded, bool compressed) {
|
||||||
opcode_size = 2;
|
opcode_size = 2;
|
||||||
track_opcode_stats = false;
|
|
||||||
|
|
||||||
//World seems to support both compression and xor zone supports one or the others.
|
//World seems to support both compression and xor zone supports one or the others.
|
||||||
//Enforce one or the other in the convienence construct
|
//Enforce one or the other in the convienence construct
|
||||||
@@ -54,8 +53,9 @@ public:
|
|||||||
EQStreamManagerInterface(const EQStreamManagerInterfaceOptions &options) { m_options = options; }
|
EQStreamManagerInterface(const EQStreamManagerInterfaceOptions &options) { m_options = options; }
|
||||||
virtual ~EQStreamManagerInterface() { };
|
virtual ~EQStreamManagerInterface() { };
|
||||||
|
|
||||||
|
EQStreamManagerInterfaceOptions GetOptions() { return m_options; }
|
||||||
const EQStreamManagerInterfaceOptions& GetOptions() const { return m_options; }
|
const EQStreamManagerInterfaceOptions& GetOptions() const { return m_options; }
|
||||||
EQStreamManagerInterfaceOptions& MutateOptions() { return m_options; }
|
virtual void SetOptions(const EQStreamManagerInterfaceOptions& options) = 0;
|
||||||
protected:
|
protected:
|
||||||
EQStreamManagerInterfaceOptions m_options;
|
EQStreamManagerInterfaceOptions m_options;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (p->GetOpcode() != OP_SpecialMesg) {
|
if (p->GetOpcode() != OP_SpecialMesg) {
|
||||||
Log(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
|
Log(Logs::General, Logs::PacketServerClient, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
|
||||||
Log(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
|
Log(Logs::General, Logs::PacketServerClientWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket *newp = p->Copy();
|
EQApplicationPacket *newp = p->Copy();
|
||||||
|
|||||||
+43
-9
@@ -26,7 +26,8 @@
|
|||||||
std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
|
std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
|
||||||
EQEmuConfig *EQEmuConfig::_config = nullptr;
|
EQEmuConfig *EQEmuConfig::_config = nullptr;
|
||||||
|
|
||||||
void EQEmuConfig::parse_config() {
|
void EQEmuConfig::parse_config()
|
||||||
|
{
|
||||||
|
|
||||||
ShortName = _root["server"]["world"].get("shortname", "").asString();
|
ShortName = _root["server"]["world"].get("shortname", "").asString();
|
||||||
LongName = _root["server"]["world"].get("longname", "").asString();
|
LongName = _root["server"]["world"].get("longname", "").asString();
|
||||||
@@ -40,10 +41,11 @@ void EQEmuConfig::parse_config() {
|
|||||||
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
|
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
|
||||||
LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
|
LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
|
||||||
LoginLegacy = false;
|
LoginLegacy = false;
|
||||||
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") LoginLegacy = true;
|
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; }
|
||||||
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
|
||||||
LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString();
|
LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
char str[32];
|
char str[32];
|
||||||
loginlist.Clear();
|
loginlist.Clear();
|
||||||
do {
|
do {
|
||||||
@@ -59,7 +61,7 @@ void EQEmuConfig::parse_config() {
|
|||||||
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
|
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
|
||||||
|
|
||||||
loginconfig->LoginLegacy = false;
|
loginconfig->LoginLegacy = false;
|
||||||
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") loginconfig->LoginLegacy = true;
|
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") { loginconfig->LoginLegacy = true; }
|
||||||
loginlist.Insert(loginconfig);
|
loginlist.Insert(loginconfig);
|
||||||
} while (LoginCount < 100);
|
} while (LoginCount < 100);
|
||||||
}
|
}
|
||||||
@@ -68,46 +70,67 @@ void EQEmuConfig::parse_config() {
|
|||||||
//<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
|
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
|
||||||
Locked = false;
|
Locked = false;
|
||||||
if (_root["server"]["world"].get("locked", "false").asString() == "true") Locked = true;
|
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; }
|
||||||
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
|
||||||
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
|
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
|
||||||
|
|
||||||
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
|
||||||
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
|
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
|
||||||
TelnetEnabled = false;
|
TelnetEnabled = false;
|
||||||
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") TelnetEnabled = true;
|
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; }
|
||||||
|
|
||||||
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
|
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
|
||||||
WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
|
WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
|
||||||
WorldHTTPEnabled = false;
|
WorldHTTPEnabled = false;
|
||||||
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") WorldHTTPEnabled = true;
|
|
||||||
|
|
||||||
|
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
|
||||||
|
WorldHTTPEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UCS
|
||||||
|
*/
|
||||||
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
||||||
ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
|
ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
|
||||||
|
|
||||||
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
||||||
MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
|
MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database
|
||||||
|
*/
|
||||||
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
|
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
|
||||||
DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
|
DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
|
||||||
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
|
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
|
||||||
DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
|
DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
|
||||||
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
|
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QS
|
||||||
|
*/
|
||||||
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
|
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
|
||||||
QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
|
QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
|
||||||
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
|
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
|
||||||
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
|
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
|
||||||
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zones
|
||||||
|
*/
|
||||||
DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
|
DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
|
||||||
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
|
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
|
||||||
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
|
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Files
|
||||||
|
*/
|
||||||
SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString();
|
SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString();
|
||||||
OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString();
|
OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString();
|
||||||
|
MailOpCodesFile = _root["server"]["files"].get("mail_opcodes", "mail_opcodes.conf").asString();
|
||||||
PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString();
|
PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directories
|
||||||
|
*/
|
||||||
MapDir = _root["server"]["directories"].get("maps", "Maps/").asString();
|
MapDir = _root["server"]["directories"].get("maps", "Maps/").asString();
|
||||||
QuestDir = _root["server"]["directories"].get("quests", "quests/").asString();
|
QuestDir = _root["server"]["directories"].get("quests", "quests/").asString();
|
||||||
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
|
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
|
||||||
@@ -116,8 +139,15 @@ void EQEmuConfig::parse_config() {
|
|||||||
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
|
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
|
||||||
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
|
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs
|
||||||
|
*/
|
||||||
LogPrefix = _root["server"]["launcher"].get("logprefix", "logs/zone-").asString();
|
LogPrefix = _root["server"]["launcher"].get("logprefix", "logs/zone-").asString();
|
||||||
LogSuffix = _root["server"]["launcher"].get("logsuffix", ".log").asString();
|
LogSuffix = _root["server"]["launcher"].get("logsuffix", ".log").asString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launcher
|
||||||
|
*/
|
||||||
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
|
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
|
||||||
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
|
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
|
||||||
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
|
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
|
||||||
@@ -230,6 +260,9 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
|||||||
if (var_name == "OpCodesFile") {
|
if (var_name == "OpCodesFile") {
|
||||||
return (OpCodesFile);
|
return (OpCodesFile);
|
||||||
}
|
}
|
||||||
|
if (var_name == "MailOpCodesFile") {
|
||||||
|
return (MailOpCodesFile);
|
||||||
|
}
|
||||||
if (var_name == "PluginPlFile") {
|
if (var_name == "PluginPlFile") {
|
||||||
return (PluginPlFile);
|
return (PluginPlFile);
|
||||||
}
|
}
|
||||||
@@ -312,6 +345,7 @@ void EQEmuConfig::Dump() const
|
|||||||
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
|
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
|
||||||
std::cout << "SpellsFile = " << SpellsFile << std::endl;
|
std::cout << "SpellsFile = " << SpellsFile << std::endl;
|
||||||
std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
|
std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
|
||||||
|
std::cout << "MailOpcodesFile = " << MailOpCodesFile << std::endl;
|
||||||
std::cout << "PluginPlFile = " << PluginPlFile << std::endl;
|
std::cout << "PluginPlFile = " << PluginPlFile << std::endl;
|
||||||
std::cout << "MapDir = " << MapDir << std::endl;
|
std::cout << "MapDir = " << MapDir << std::endl;
|
||||||
std::cout << "QuestDir = " << QuestDir << std::endl;
|
std::cout << "QuestDir = " << QuestDir << std::endl;
|
||||||
@@ -322,6 +356,6 @@ void EQEmuConfig::Dump() const
|
|||||||
std::cout << "LogDir = " << LogDir << std::endl;
|
std::cout << "LogDir = " << LogDir << std::endl;
|
||||||
std::cout << "ZonePortLow = " << ZonePortLow << std::endl;
|
std::cout << "ZonePortLow = " << ZonePortLow << std::endl;
|
||||||
std::cout << "ZonePortHigh = " << ZonePortHigh << std::endl;
|
std::cout << "ZonePortHigh = " << ZonePortHigh << std::endl;
|
||||||
std::cout << "DefaultStatus = " << (int)DefaultStatus << std::endl;
|
std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl;
|
||||||
// std::cout << "DynamicCount = " << DynamicCount << std::endl;
|
// std::cout << "DynamicCount = " << DynamicCount << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class EQEmuConfig
|
|||||||
// From <files/>
|
// From <files/>
|
||||||
std::string SpellsFile;
|
std::string SpellsFile;
|
||||||
std::string OpCodesFile;
|
std::string OpCodesFile;
|
||||||
|
std::string MailOpCodesFile;
|
||||||
std::string PluginPlFile;
|
std::string PluginPlFile;
|
||||||
|
|
||||||
// From <directories/>
|
// From <directories/>
|
||||||
|
|||||||
+129
-56
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eqemu_logsys.h"
|
#include "eqemu_logsys.h"
|
||||||
|
#include "rulesys.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
@@ -81,30 +82,19 @@ namespace Console {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GameChatColor {
|
|
||||||
yellow = 15,
|
|
||||||
red = 13,
|
|
||||||
light_green = 14,
|
|
||||||
light_cyan = 258,
|
|
||||||
light_purple = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EQEmuLogSys Constructor
|
* EQEmuLogSys Constructor
|
||||||
*/
|
*/
|
||||||
EQEmuLogSys::EQEmuLogSys()
|
EQEmuLogSys::EQEmuLogSys()
|
||||||
{
|
{
|
||||||
on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
|
on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
|
||||||
bool file_logs_enabled = false;
|
on_log_console_hook = [](uint16 debug_level, uint16 log_type, const std::string &) {};
|
||||||
int log_platform = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EQEmuLogSys Deconstructor
|
* EQEmuLogSys Deconstructor
|
||||||
*/
|
*/
|
||||||
EQEmuLogSys::~EQEmuLogSys()
|
EQEmuLogSys::~EQEmuLogSys() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EQEmuLogSys::LoadLogSettingsDefaults()
|
void EQEmuLogSys::LoadLogSettingsDefaults()
|
||||||
{
|
{
|
||||||
@@ -125,15 +115,26 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
|||||||
/**
|
/**
|
||||||
* Set Defaults
|
* Set Defaults
|
||||||
*/
|
*/
|
||||||
log_settings[Logs::World_Server].log_to_console = Logs::General;
|
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::Zone_Server].log_to_console = Logs::General;
|
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::QS_Server].log_to_console = Logs::General;
|
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::UCS_Server].log_to_console = Logs::General;
|
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::Crash].log_to_console = Logs::General;
|
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::MySQLError].log_to_console = Logs::General;
|
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::Login_Server].log_to_console = Logs::General;
|
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::Headless_Client].log_to_console = Logs::General;
|
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
log_settings[Logs::NPCScaling].log_to_gmsay = Logs::General;
|
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC 5424
|
||||||
|
*/
|
||||||
|
log_settings[Logs::Emergency].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::Alert].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::Critical].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::Notice].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Category enabled status on defaults
|
* Set Category enabled status on defaults
|
||||||
@@ -174,20 +175,41 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param log_category
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
log_category == Logs::Emergency ||
|
||||||
|
log_category == Logs::Alert ||
|
||||||
|
log_category == Logs::Critical ||
|
||||||
|
log_category == Logs::Error ||
|
||||||
|
log_category == Logs::Warning ||
|
||||||
|
log_category == Logs::Notice ||
|
||||||
|
log_category == Logs::Info ||
|
||||||
|
log_category == Logs::Debug
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param log_category
|
* @param log_category
|
||||||
* @param in_message
|
* @param in_message
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message)
|
std::string EQEmuLogSys::FormatOutMessageString(
|
||||||
|
uint16 log_category,
|
||||||
|
const std::string &in_message
|
||||||
|
)
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string return_string;
|
||||||
ret.push_back('[');
|
|
||||||
ret.append(Logs::LogCategoryName[log_category]);
|
if (IsRfc5424LogCategory(log_category)) {
|
||||||
ret.push_back(']');
|
return_string = "[" + GetPlatformName() + "] ";
|
||||||
ret.push_back(' ');
|
}
|
||||||
ret.append(in_message);
|
|
||||||
return ret;
|
return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,7 +217,11 @@ std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::
|
|||||||
* @param log_category
|
* @param log_category
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message)
|
void EQEmuLogSys::ProcessGMSay(
|
||||||
|
uint16 debug_level,
|
||||||
|
uint16 log_category,
|
||||||
|
const std::string &message
|
||||||
|
)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
|
* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
|
||||||
@@ -217,7 +243,11 @@ void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const st
|
|||||||
* @param log_category
|
* @param log_category
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message)
|
void EQEmuLogSys::ProcessLogWrite(
|
||||||
|
uint16 debug_level,
|
||||||
|
uint16 log_category,
|
||||||
|
const std::string &message
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (log_category == Logs::Crash) {
|
if (log_category == Logs::Crash) {
|
||||||
char time_stamp[80];
|
char time_stamp[80];
|
||||||
@@ -279,6 +309,8 @@ std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
|
|||||||
case Logs::Normal:
|
case Logs::Normal:
|
||||||
return LC_YELLOW;
|
return LC_YELLOW;
|
||||||
case Logs::MySQLError:
|
case Logs::MySQLError:
|
||||||
|
case Logs::Warning:
|
||||||
|
case Logs::Critical:
|
||||||
case Logs::Error:
|
case Logs::Error:
|
||||||
return LC_RED;
|
return LC_RED;
|
||||||
case Logs::MySQLQuery:
|
case Logs::MySQLQuery:
|
||||||
@@ -305,22 +337,22 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
|
|||||||
switch (log_category) {
|
switch (log_category) {
|
||||||
case Logs::Status:
|
case Logs::Status:
|
||||||
case Logs::Normal:
|
case Logs::Normal:
|
||||||
return GameChatColor::yellow;
|
return Chat::Yellow;
|
||||||
case Logs::MySQLError:
|
case Logs::MySQLError:
|
||||||
case Logs::Error:
|
case Logs::Error:
|
||||||
return GameChatColor::red;
|
return Chat::Red;
|
||||||
case Logs::MySQLQuery:
|
case Logs::MySQLQuery:
|
||||||
case Logs::Debug:
|
case Logs::Debug:
|
||||||
return GameChatColor::light_green;
|
return Chat::Lime;
|
||||||
case Logs::Quests:
|
case Logs::Quests:
|
||||||
return GameChatColor::light_cyan;
|
return Chat::Group;
|
||||||
case Logs::Commands:
|
case Logs::Commands:
|
||||||
case Logs::Mercenaries:
|
case Logs::Mercenaries:
|
||||||
return GameChatColor::light_purple;
|
return Chat::Magenta;
|
||||||
case Logs::Crash:
|
case Logs::Crash:
|
||||||
return GameChatColor::red;
|
return Chat::Red;
|
||||||
default:
|
default:
|
||||||
return GameChatColor::yellow;
|
return Chat::Yellow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,6 +378,44 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
|
|||||||
#else
|
#else
|
||||||
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
|
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
on_log_console_hook(debug_level, log_category, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param str
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
constexpr const char *str_end(const char *str)
|
||||||
|
{
|
||||||
|
return *str ? str_end(str + 1) : str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param str
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
constexpr bool str_slant(const char *str)
|
||||||
|
{
|
||||||
|
return *str == '/' ? true : (*str ? str_slant(str + 1) : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param str
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
constexpr const char *r_slant(const char *str)
|
||||||
|
{
|
||||||
|
return *str == '/' ? (str + 1) : r_slant(str - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param str
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
constexpr const char *base_file_name(const char *str)
|
||||||
|
{
|
||||||
|
return str_slant(str) ? r_slant(str_end(str)) : str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -356,7 +426,15 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
|
|||||||
* @param message
|
* @param message
|
||||||
* @param ...
|
* @param ...
|
||||||
*/
|
*/
|
||||||
void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...)
|
void EQEmuLogSys::Out(
|
||||||
|
Logs::DebugLevel debug_level,
|
||||||
|
uint16 log_category,
|
||||||
|
const char *file,
|
||||||
|
const char *func,
|
||||||
|
int line,
|
||||||
|
const char *message,
|
||||||
|
...
|
||||||
|
)
|
||||||
{
|
{
|
||||||
bool log_to_console = true;
|
bool log_to_console = true;
|
||||||
if (log_settings[log_category].log_to_console < debug_level) {
|
if (log_settings[log_category].log_to_console < debug_level) {
|
||||||
@@ -378,12 +456,18 @@ void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::st
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string prefix;
|
||||||
|
|
||||||
|
if (RuleB(Logging, PrintFileFunctionAndLine)) {
|
||||||
|
prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
|
||||||
|
}
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
std::string output_message = vStringFormat(message.c_str(), args);
|
std::string output_message = vStringFormat(message, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, output_message);
|
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message);
|
||||||
|
|
||||||
if (log_to_console) {
|
if (log_to_console) {
|
||||||
EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
|
EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
|
||||||
@@ -419,7 +503,7 @@ void EQEmuLogSys::MakeDirectory(const std::string &directory_name)
|
|||||||
return;
|
return;
|
||||||
_mkdir(directory_name.c_str());
|
_mkdir(directory_name.c_str());
|
||||||
#else
|
#else
|
||||||
struct stat st;
|
struct stat st{};
|
||||||
if (stat(directory_name.c_str(), &st) == 0) { // exists
|
if (stat(directory_name.c_str(), &st) == 0) { // exists
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -460,12 +544,7 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQEmuLogSys::Out(
|
LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid());
|
||||||
Logs::General,
|
|
||||||
Logs::Status,
|
|
||||||
"Starting File Log 'logs/%s_%i.log'",
|
|
||||||
platform_file_name.c_str(),
|
|
||||||
getpid());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make directory if not exists
|
* Make directory if not exists
|
||||||
@@ -485,17 +564,11 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name)
|
|||||||
/**
|
/**
|
||||||
* All other processes
|
* All other processes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (platform_file_name.empty()) {
|
if (platform_file_name.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQEmuLogSys::Out(
|
LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid());
|
||||||
Logs::General,
|
|
||||||
Logs::Status,
|
|
||||||
"Starting File Log 'logs/%s_%i.log'",
|
|
||||||
platform_file_name.c_str(),
|
|
||||||
getpid());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open file pointer
|
* Open file pointer
|
||||||
|
|||||||
+115
-30
@@ -25,6 +25,14 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef utf16_to_utf8
|
||||||
|
#undef utf16_to_utf8
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
namespace Logs {
|
namespace Logs {
|
||||||
@@ -45,7 +53,7 @@ namespace Logs {
|
|||||||
AI,
|
AI,
|
||||||
Aggro,
|
Aggro,
|
||||||
Attack,
|
Attack,
|
||||||
Client_Server_Packet,
|
PacketClientServer,
|
||||||
Combat,
|
Combat,
|
||||||
Commands,
|
Commands,
|
||||||
Crash,
|
Crash,
|
||||||
@@ -59,40 +67,46 @@ namespace Logs {
|
|||||||
Normal,
|
Normal,
|
||||||
Object,
|
Object,
|
||||||
Pathing,
|
Pathing,
|
||||||
QS_Server,
|
QSServer,
|
||||||
Quests,
|
Quests,
|
||||||
Rules,
|
Rules,
|
||||||
Skills,
|
Skills,
|
||||||
Spawns,
|
Spawns,
|
||||||
Spells,
|
Spells,
|
||||||
Status,
|
Status,
|
||||||
TCP_Connection,
|
TCPConnection,
|
||||||
Tasks,
|
Tasks,
|
||||||
Tradeskills,
|
Tradeskills,
|
||||||
Trading,
|
Trading,
|
||||||
Tribute,
|
Tribute,
|
||||||
UCS_Server,
|
UCSServer,
|
||||||
WebInterface_Server,
|
WebInterfaceServer,
|
||||||
World_Server,
|
WorldServer,
|
||||||
Zone_Server,
|
ZoneServer,
|
||||||
MySQLError,
|
MySQLError,
|
||||||
MySQLQuery,
|
MySQLQuery,
|
||||||
Mercenaries,
|
Mercenaries,
|
||||||
QuestDebug,
|
QuestDebug,
|
||||||
Server_Client_Packet,
|
PacketServerClient,
|
||||||
Client_Server_Packet_Unhandled,
|
PacketClientServerUnhandled,
|
||||||
Server_Client_Packet_With_Dump,
|
PacketServerClientWithDump,
|
||||||
Client_Server_Packet_With_Dump,
|
PacketClientServerWithDump,
|
||||||
Login_Server,
|
Loginserver,
|
||||||
Client_Login,
|
ClientLogin,
|
||||||
Headless_Client,
|
HeadlessClient,
|
||||||
HP_Update,
|
HPUpdate,
|
||||||
FixZ,
|
FixZ,
|
||||||
Food,
|
Food,
|
||||||
Traps,
|
Traps,
|
||||||
NPCRoamBox,
|
NPCRoamBox,
|
||||||
NPCScaling,
|
NPCScaling,
|
||||||
MobAppearance,
|
MobAppearance,
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Critical,
|
||||||
|
Emergency,
|
||||||
|
Alert,
|
||||||
|
Notice,
|
||||||
MaxCategoryID /* Don't Remove this */
|
MaxCategoryID /* Don't Remove this */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,19 +166,17 @@ namespace Logs {
|
|||||||
"Traps",
|
"Traps",
|
||||||
"NPC Roam Box",
|
"NPC Roam Box",
|
||||||
"NPC Scaling",
|
"NPC Scaling",
|
||||||
"Mob Appearance"
|
"Mob Appearance",
|
||||||
|
"Info",
|
||||||
|
"Warning",
|
||||||
|
"Critical",
|
||||||
|
"Emergency",
|
||||||
|
"Alert",
|
||||||
|
"Notice"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Log(debug_level, log_category, message, ...) do {\
|
#include "eqemu_logsys_log_aliases.h"
|
||||||
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
|
||||||
LogSys.Out(debug_level, log_category, message, ##__VA_ARGS__);\
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LogF(debug_level, log_category, message, ...) do {\
|
|
||||||
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
|
||||||
OutF(LogSys, debug_level, log_category, message, ##__VA_ARGS__);\
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
class EQEmuLogSys {
|
class EQEmuLogSys {
|
||||||
public:
|
public:
|
||||||
@@ -177,6 +189,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void CloseFileLogs();
|
void CloseFileLogs();
|
||||||
void LoadLogSettingsDefaults();
|
void LoadLogSettingsDefaults();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param directory_name
|
||||||
|
*/
|
||||||
void MakeDirectory(const std::string &directory_name);
|
void MakeDirectory(const std::string &directory_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,12 +204,25 @@ public:
|
|||||||
* - This would pipe the same category and debug level to all output formats, but the internal memory reference of log_settings would
|
* - This would pipe the same category and debug level to all output formats, but the internal memory reference of log_settings would
|
||||||
* be checked against to see if that piped output is set to actually process it for the category and debug level
|
* be checked against to see if that piped output is set to actually process it for the category and debug level
|
||||||
*/
|
*/
|
||||||
void Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...);
|
void Out(
|
||||||
|
Logs::DebugLevel debug_level,
|
||||||
|
uint16 log_category,
|
||||||
|
const char *file,
|
||||||
|
const char *func,
|
||||||
|
int line,
|
||||||
|
const char *message,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used in file logs to prepend a timestamp entry for logs
|
* Used in file logs to prepend a timestamp entry for logs
|
||||||
|
* @param time_stamp
|
||||||
*/
|
*/
|
||||||
void SetCurrentTimeStamp(char* time_stamp);
|
void SetCurrentTimeStamp(char* time_stamp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param log_name
|
||||||
|
*/
|
||||||
void StartFileLogs(const std::string &log_name = "");
|
void StartFileLogs(const std::string &log_name = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,14 +247,14 @@ public:
|
|||||||
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
|
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
|
||||||
* Database loaded via Database::LoadLogSettings(log_settings)
|
* Database loaded via Database::LoadLogSettings(log_settings)
|
||||||
*/
|
*/
|
||||||
LogSettings log_settings[Logs::LogCategory::MaxCategoryID];
|
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
|
||||||
|
|
||||||
bool file_logs_enabled;
|
bool file_logs_enabled = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets Executable platform (Zone/World/UCS) etc.
|
* Sets Executable platform (Zone/World/UCS) etc.
|
||||||
*/
|
*/
|
||||||
int log_platform;
|
int log_platform = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File name used in writing logs
|
* File name used in writing logs
|
||||||
@@ -240,7 +269,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
uint16 GetGMSayColorFromCategory(uint16 log_category);
|
uint16 GetGMSayColorFromCategory(uint16 log_category);
|
||||||
|
|
||||||
void OnLogHookCallBackZone(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
|
/**
|
||||||
|
* @param f
|
||||||
|
*/
|
||||||
|
void SetGMSayHandler(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param f
|
||||||
|
*/
|
||||||
|
void SetConsoleHandler(std::function<void(uint16 debug_level, uint16 log_type, const std::string&)> f) { on_log_console_hook = f; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -248,6 +285,7 @@ private:
|
|||||||
* Callback pointer to zone process for hooking logs to zone using GMSay
|
* Callback pointer to zone process for hooking logs to zone using GMSay
|
||||||
*/
|
*/
|
||||||
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook;
|
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook;
|
||||||
|
std::function<void(uint16 debug_level, uint16 log_category, const std::string&)> on_log_console_hook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats log messages like '[Category] This is a log message'
|
* Formats log messages like '[Category] This is a log message'
|
||||||
@@ -256,6 +294,7 @@ private:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Linux console color messages mapped by category
|
* Linux console color messages mapped by category
|
||||||
|
*
|
||||||
* @param log_category
|
* @param log_category
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -266,11 +305,57 @@ private:
|
|||||||
*/
|
*/
|
||||||
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
|
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param debug_level
|
||||||
|
* @param log_category
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message);
|
void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param debug_level
|
||||||
|
* @param log_category
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
|
void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param debug_level
|
||||||
|
* @param log_category
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
|
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param log_category
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool IsRfc5424LogCategory(uint16 log_category);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EQEmuLogSys LogSys;
|
extern EQEmuLogSys LogSys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
template<typename... Args>
|
||||||
|
void OutF(
|
||||||
|
EQEmuLogSys &ls,
|
||||||
|
Logs::DebugLevel debug_level,
|
||||||
|
uint16 log_category,
|
||||||
|
const char *file,
|
||||||
|
const char *func,
|
||||||
|
int line,
|
||||||
|
const char *fmt,
|
||||||
|
const Args &... args
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string log_str = fmt::format(fmt, args...);
|
||||||
|
ls.Out(debug_level, log_category, file, func, line, log_str.c_str());
|
||||||
|
}
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define OutF(ls, debug_level, log_category, file, func, line, formatStr, ...) \
|
||||||
|
do { \
|
||||||
|
ls.Out(debug_level, log_category, file, func, line, fmt::format(formatStr, ##__VA_ARGS__).c_str()); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,507 @@
|
|||||||
|
/**
|
||||||
|
* 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_EQEMU_LOGSYS_LOG_ALIASES_H
|
||||||
|
#define EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC 5424
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LogEmergency(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Emergency].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Emergency, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAlert(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Alert].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Alert, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogCritical(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Critical].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Critical, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogError(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Error].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogWarning(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Warning].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNotice(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Notice].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Notice, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogInfo(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Info].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogDebug(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Debug].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Debug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Category
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LogAA(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::AA].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAADetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::AA].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAI(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::AI].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAIDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::AI].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAggro(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Aggro].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAggroDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Aggro].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAttack(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Attack].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogAttackDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Attack].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogPacketClientServer(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogPacketClientServerDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogCombat(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Combat].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogCombatDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Combat].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogCommands(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Commands].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogCommandsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Commands].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogCrash(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Crash].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogCrashDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Crash].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogDoors(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Doors].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogDoorsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Doors].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogGuilds(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogGuildsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogInventory(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Inventory].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogInventoryDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Inventory].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogLauncher(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Launcher].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogLauncherDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Launcher].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNetcode(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Netcode].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNetcodeDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Netcode].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNormal(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Normal].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNormalDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Normal].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogObject(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Object].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogObjectDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Object].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogPathing(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Pathing].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogPathingDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Pathing].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogQSServer(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::QSServer].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogQSServerDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::QSServer].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogQuests(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Quests].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogQuestsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Quests].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogRules(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Rules].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogRulesDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Rules].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogSkills(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Skills].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogSkillsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Skills].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogSpawns(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Spawns].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogSpawnsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Spawns].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogSpells(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Spells].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogSpellsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Spells].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTCPConnection(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::TCPConnection].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTCPConnectionDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::TCPConnection].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTasks(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Tasks].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTasksDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Tasks].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTradeskills(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Tradeskills].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTradeskillsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Tradeskills].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTrading(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Trading].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTradingDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Trading].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTribute(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Tribute].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTributeDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Tribute].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMySQLError(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMySQLErrorDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMySQLQuery(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMySQLQueryDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMercenaries(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Mercenaries].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMercenariesDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Mercenaries].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogQuestDebug(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::QuestDebug].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogQuestDebugDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::QuestDebug].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogLoginserver(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Loginserver].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogLoginserverDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Loginserver].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogClientLogin(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::ClientLogin].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogClientLoginDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::ClientLogin].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogHeadlessClient(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::HeadlessClient].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogHeadlessClientDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::HeadlessClient].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogHPUpdate(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::HPUpdate].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogHPUpdateDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::HPUpdate].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogFixZ(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::FixZ].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogFixZDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::FixZ].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogFood(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Food].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogFoodDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Food].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTraps(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Traps].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogTrapsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Traps].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNPCRoamBox(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::NPCRoamBox].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNPCRoamBoxDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::NPCRoamBox].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNPCScaling(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogNPCScalingDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMobAppearance(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::MobAppearance].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogMobAppearanceDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::MobAppearance].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogStatus(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Status].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Status, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogStatusDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Status].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Status, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Misc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogF(debug_level, log_category, message, ...) do {\
|
||||||
|
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <functional>
|
||||||
|
#include <queue>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Event
|
||||||
|
{
|
||||||
|
class TaskScheduler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int DefaultThreadCount = 4;
|
||||||
|
|
||||||
|
TaskScheduler() : _running(false)
|
||||||
|
{
|
||||||
|
Start(DefaultThreadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskScheduler(size_t threads) : _running(false)
|
||||||
|
{
|
||||||
|
Start(threads);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TaskScheduler() {
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start(size_t threads) {
|
||||||
|
if (true == _running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_running = true;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < threads; ++i) {
|
||||||
|
_threads.push_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stop() {
|
||||||
|
if (false == _running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cv.notify_all();
|
||||||
|
|
||||||
|
for (auto &t : _threads) {
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Fn, typename... Args>
|
||||||
|
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
|
||||||
|
using return_type = typename std::result_of<Fn(Args...)>::type;
|
||||||
|
|
||||||
|
auto task = std::make_shared<std::packaged_task<return_type()>>(
|
||||||
|
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
|
||||||
|
);
|
||||||
|
|
||||||
|
std::future<return_type> res = task->get_future();
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
|
||||||
|
if (false == _running) {
|
||||||
|
throw std::runtime_error("Enqueue on stopped scheduler.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_tasks.emplace([task]() { (*task)(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
_cv.notify_one();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ProcessWork() {
|
||||||
|
for (;;) {
|
||||||
|
std::function<void()> work;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
_cv.wait(lock, [this] { return !_running || !_tasks.empty(); });
|
||||||
|
|
||||||
|
if (false == _running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
work = std::move(_tasks.front());
|
||||||
|
_tasks.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
work();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _running = true;
|
||||||
|
std::vector<std::thread> _threads;
|
||||||
|
std::mutex _lock;
|
||||||
|
std::condition_variable _cv;
|
||||||
|
std::queue<std::function<void()>> _tasks;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-11
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "faction.h"
|
#include "faction.h"
|
||||||
#include "races.h"
|
#include "races.h"
|
||||||
|
#include "rulesys.h"
|
||||||
|
|
||||||
const char *FactionValueToString(FACTION_VALUE fv)
|
const char *FactionValueToString(FACTION_VALUE fv)
|
||||||
{
|
{
|
||||||
@@ -59,34 +60,31 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
|
|||||||
if (fm) {
|
if (fm) {
|
||||||
character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod;
|
character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod;
|
||||||
}
|
}
|
||||||
if (character_value >= 1100) {
|
if (character_value >= RuleI(Faction, AllyFactionMinimum)) {
|
||||||
return FACTION_ALLY;
|
return FACTION_ALLY;
|
||||||
}
|
}
|
||||||
if (character_value >= 750 && character_value <= 1099) {
|
if (character_value >= RuleI(Faction, WarmlyFactionMinimum)) {
|
||||||
return FACTION_WARMLY;
|
return FACTION_WARMLY;
|
||||||
}
|
}
|
||||||
if (character_value >= 500 && character_value <= 749) {
|
if (character_value >= RuleI(Faction, KindlyFactionMinimum)) {
|
||||||
return FACTION_KINDLY;
|
return FACTION_KINDLY;
|
||||||
}
|
}
|
||||||
if (character_value >= 100 && character_value <= 499) {
|
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) {
|
||||||
return FACTION_AMIABLE;
|
return FACTION_AMIABLE;
|
||||||
}
|
}
|
||||||
if (character_value >= 0 && character_value <= 99) {
|
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) {
|
||||||
return FACTION_INDIFFERENT;
|
return FACTION_INDIFFERENT;
|
||||||
}
|
}
|
||||||
if (character_value >= -100 && character_value <= -1) {
|
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) {
|
||||||
return FACTION_APPREHENSIVE;
|
return FACTION_APPREHENSIVE;
|
||||||
}
|
}
|
||||||
if (character_value >= -500 && character_value <= -101) {
|
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) {
|
||||||
return FACTION_DUBIOUS;
|
return FACTION_DUBIOUS;
|
||||||
}
|
}
|
||||||
if (character_value >= -750 && character_value <= -501) {
|
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) {
|
||||||
return FACTION_THREATENLY;
|
return FACTION_THREATENLY;
|
||||||
}
|
}
|
||||||
if (character_value <= -751) {
|
|
||||||
return FACTION_SCOWLS;
|
return FACTION_SCOWLS;
|
||||||
}
|
|
||||||
return FACTION_INDIFFERENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function should check if some races have more than one race define
|
// this function should check if some races have more than one race define
|
||||||
|
|||||||
+43
-43
@@ -46,7 +46,7 @@ bool BaseGuildManager::LoadGuilds() {
|
|||||||
ClearGuilds();
|
ClearGuilds();
|
||||||
|
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to load guilds when we have no database object.");
|
LogGuilds("Requested to load guilds when we have no database object");
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,13 +77,13 @@ bool BaseGuildManager::LoadGuilds() {
|
|||||||
uint8 rankn = atoi(row[1]);
|
uint8 rankn = atoi(row[1]);
|
||||||
|
|
||||||
if(rankn > GUILD_MAX_RANK) {
|
if(rankn > GUILD_MAX_RANK) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Found invalid (too high) rank %d for guild %d, skipping.", rankn, guild_id);
|
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = m_guilds.find(guild_id);
|
res = m_guilds.find(guild_id);
|
||||||
if(res == m_guilds.end()) {
|
if(res == m_guilds.end()) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Found rank %d for non-existent guild %d, skipping.", rankn, guild_id);
|
LogGuilds("Found rank [{}] for non-existent guild [{}], skipping", rankn, guild_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ bool BaseGuildManager::LoadGuilds() {
|
|||||||
|
|
||||||
bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to refresh guild %d when we have no database object.", guild_id);
|
LogGuilds("Requested to refresh guild [{}] when we have no database object", guild_id);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
|||||||
|
|
||||||
if (results.RowCount() == 0)
|
if (results.RowCount() == 0)
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Guilds, "Unable to find guild %d in the database.", guild_id);
|
LogGuilds("Unable to find guild [{}] in the database", guild_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
|||||||
uint8 rankn = atoi(row[1]);
|
uint8 rankn = atoi(row[1]);
|
||||||
|
|
||||||
if(rankn > GUILD_MAX_RANK) {
|
if(rankn > GUILD_MAX_RANK) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Found invalid (too high) rank %d for guild %d, skipping.", rankn, guild_id);
|
LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) {
|
|||||||
rank.permissions[GUILD_WARPEACE] = (row[10][0] == '1') ? true: false;
|
rank.permissions[GUILD_WARPEACE] = (row[10][0] == '1') ? true: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Successfully refreshed guild %d from the database.", guild_id);
|
LogGuilds("Successfully refreshed guild [{}] from the database", guild_id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -214,14 +214,14 @@ BaseGuildManager::GuildInfo *BaseGuildManager::_CreateGuild(uint32 guild_id, con
|
|||||||
|
|
||||||
bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
|
bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to store guild %d when we have no database object.", guild_id);
|
LogGuilds("Requested to store guild [{}] when we have no database object", guild_id);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||||
res = m_guilds.find(guild_id);
|
res = m_guilds.find(guild_id);
|
||||||
if(res == m_guilds.end()) {
|
if(res == m_guilds.end()) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to store non-existent guild %d", guild_id);
|
LogGuilds("Requested to store non-existent guild [{}]", guild_id);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
GuildInfo *info = res->second;
|
GuildInfo *info = res->second;
|
||||||
@@ -289,14 +289,14 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) {
|
|||||||
safe_delete_array(title_esc);
|
safe_delete_array(title_esc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Stored guild %d in the database", guild_id);
|
LogGuilds("Stored guild [{}] in the database", guild_id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 BaseGuildManager::_GetFreeGuildID() {
|
uint32 BaseGuildManager::_GetFreeGuildID() {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested find a free guild ID when we have no database object.");
|
LogGuilds("Requested find a free guild ID when we have no database object");
|
||||||
return(GUILD_NONE);
|
return(GUILD_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,12 +330,12 @@ uint32 BaseGuildManager::_GetFreeGuildID() {
|
|||||||
|
|
||||||
if (results.RowCount() == 0)
|
if (results.RowCount() == 0)
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Guilds, "Located free guild ID %d in the database", index);
|
LogGuilds("Located free guild ID [{}] in the database", index);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Unable to find a free guild ID when requested.");
|
LogGuilds("Unable to find a free guild ID when requested");
|
||||||
return GUILD_NONE;
|
return GUILD_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,11 +505,11 @@ uint32 BaseGuildManager::DBCreateGuild(const char* name, uint32 leader) {
|
|||||||
|
|
||||||
//now store the resulting guild setup into the DB.
|
//now store the resulting guild setup into the DB.
|
||||||
if(!_StoreGuildDB(new_id)) {
|
if(!_StoreGuildDB(new_id)) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Error storing new guild. It may have been partially created which may need manual removal.");
|
LogGuilds("Error storing new guild. It may have been partially created which may need manual removal");
|
||||||
return(GUILD_NONE);
|
return(GUILD_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Created guild %d in the database.", new_id);
|
LogGuilds("Created guild [{}] in the database", new_id);
|
||||||
|
|
||||||
return(new_id);
|
return(new_id);
|
||||||
}
|
}
|
||||||
@@ -525,7 +525,7 @@ bool BaseGuildManager::DBDeleteGuild(uint32 guild_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to delete guild %d when we have no database object.", guild_id);
|
LogGuilds("Requested to delete guild [{}] when we have no database object", guild_id);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,14 +545,14 @@ bool BaseGuildManager::DBDeleteGuild(uint32 guild_id) {
|
|||||||
query = StringFormat("DELETE FROM guild_bank WHERE guildid=%lu", (unsigned long)guild_id);
|
query = StringFormat("DELETE FROM guild_bank WHERE guildid=%lu", (unsigned long)guild_id);
|
||||||
QueryWithLogging(query, "deleting guild bank");
|
QueryWithLogging(query, "deleting guild bank");
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Deleted guild %d from the database.", guild_id);
|
LogGuilds("Deleted guild [{}] from the database", guild_id);
|
||||||
|
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseGuildManager::DBRenameGuild(uint32 guild_id, const char* name) {
|
bool BaseGuildManager::DBRenameGuild(uint32 guild_id, const char* name) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to rename guild %d when we have no database object.", guild_id);
|
LogGuilds("Requested to rename guild [{}] when we have no database object", guild_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,13 +573,13 @@ bool BaseGuildManager::DBRenameGuild(uint32 guild_id, const char* name) {
|
|||||||
|
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Guilds, "Error renaming guild %d '%s': %s", guild_id, query.c_str(), results.Success());
|
LogGuilds("Error renaming guild [{}] [{}]: [{}]", guild_id, query.c_str(), results.Success());
|
||||||
safe_delete_array(esc);
|
safe_delete_array(esc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
safe_delete_array(esc);
|
safe_delete_array(esc);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Renamed guild %s (%d) to %s in database.", info->name.c_str(), guild_id, name);
|
LogGuilds("Renamed guild [{}] ([{}]) to [{}] in database", info->name.c_str(), guild_id, name);
|
||||||
|
|
||||||
info->name = name; //update our local record.
|
info->name = name; //update our local record.
|
||||||
|
|
||||||
@@ -588,7 +588,7 @@ bool BaseGuildManager::DBRenameGuild(uint32 guild_id, const char* name) {
|
|||||||
|
|
||||||
bool BaseGuildManager::DBSetGuildLeader(uint32 guild_id, uint32 leader) {
|
bool BaseGuildManager::DBSetGuildLeader(uint32 guild_id, uint32 leader) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to set the leader for guild %d when we have no database object.", guild_id);
|
LogGuilds("Requested to set the leader for guild [{}] when we have no database object", guild_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,7 +614,7 @@ bool BaseGuildManager::DBSetGuildLeader(uint32 guild_id, uint32 leader) {
|
|||||||
if(!DBSetGuildRank(leader, GUILD_LEADER))
|
if(!DBSetGuildRank(leader, GUILD_LEADER))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Set guild leader for guild %d to %d in the database", guild_id, leader);
|
LogGuilds("Set guild leader for guild [{}] to [{}] in the database", guild_id, leader);
|
||||||
|
|
||||||
info->leader_char_id = leader; //update our local record.
|
info->leader_char_id = leader; //update our local record.
|
||||||
|
|
||||||
@@ -623,7 +623,7 @@ bool BaseGuildManager::DBSetGuildLeader(uint32 guild_id, uint32 leader) {
|
|||||||
|
|
||||||
bool BaseGuildManager::DBSetGuildMOTD(uint32 guild_id, const char* motd, const char *setter) {
|
bool BaseGuildManager::DBSetGuildMOTD(uint32 guild_id, const char* motd, const char *setter) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to set the MOTD for guild %d when we have no database object.", guild_id);
|
LogGuilds("Requested to set the MOTD for guild [{}] when we have no database object", guild_id);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,7 +654,7 @@ bool BaseGuildManager::DBSetGuildMOTD(uint32 guild_id, const char* motd, const c
|
|||||||
safe_delete_array(esc);
|
safe_delete_array(esc);
|
||||||
safe_delete_array(esc_set);
|
safe_delete_array(esc_set);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Set MOTD for guild %d in the database", guild_id);
|
LogGuilds("Set MOTD for guild [{}] in the database", guild_id);
|
||||||
|
|
||||||
info->motd = motd; //update our local record.
|
info->motd = motd; //update our local record.
|
||||||
info->motd_setter = setter; //update our local record.
|
info->motd_setter = setter; //update our local record.
|
||||||
@@ -688,7 +688,7 @@ bool BaseGuildManager::DBSetGuildURL(uint32 GuildID, const char* URL)
|
|||||||
}
|
}
|
||||||
safe_delete_array(esc);
|
safe_delete_array(esc);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Set URL for guild %d in the database", GuildID);
|
LogGuilds("Set URL for guild [{}] in the database", GuildID);
|
||||||
|
|
||||||
info->url = URL; //update our local record.
|
info->url = URL; //update our local record.
|
||||||
|
|
||||||
@@ -722,7 +722,7 @@ bool BaseGuildManager::DBSetGuildChannel(uint32 GuildID, const char* Channel)
|
|||||||
}
|
}
|
||||||
safe_delete_array(esc);
|
safe_delete_array(esc);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Set Channel for guild %d in the database", GuildID);
|
LogGuilds("Set Channel for guild [{}] in the database", GuildID);
|
||||||
|
|
||||||
info->channel = Channel; //update our local record.
|
info->channel = Channel; //update our local record.
|
||||||
|
|
||||||
@@ -731,7 +731,7 @@ bool BaseGuildManager::DBSetGuildChannel(uint32 GuildID, const char* Channel)
|
|||||||
|
|
||||||
bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested to set char to guild %d when we have no database object.", guild_id);
|
LogGuilds("Requested to set char to guild [{}] when we have no database object", guild_id);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,7 +753,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log(Logs::Detail, Logs::Guilds, "Set char %d to guild %d and rank %d in the database.", charid, guild_id, rank);
|
LogGuilds("Set char [{}] to guild [{}] and rank [{}] in the database", charid, guild_id, rank);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,7 +845,7 @@ bool BaseGuildManager::DBSetPublicNote(uint32 charid, const char* note) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Set public not for char %d", charid);
|
LogGuilds("Set public not for char [{}]", charid);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -924,14 +924,14 @@ bool BaseGuildManager::GetEntireGuild(uint32 guild_id, std::vector<CharGuildInfo
|
|||||||
members.push_back(ci);
|
members.push_back(ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Retreived entire guild member list for guild %d from the database", guild_id);
|
LogGuilds("Retreived entire guild member list for guild [{}] from the database", guild_id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) {
|
bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested char info on %s when we have no database object.", char_name);
|
LogGuilds("Requested char info on [{}] when we have no database object", char_name);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -953,7 +953,7 @@ bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) {
|
|||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
ProcessGuildMember(row, into);
|
ProcessGuildMember(row, into);
|
||||||
Log(Logs::Detail, Logs::Guilds, "Retreived guild member info for char %s from the database", char_name);
|
LogGuilds("Retreived guild member info for char [{}] from the database", char_name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -962,7 +962,7 @@ bool BaseGuildManager::GetCharInfo(const char *char_name, CharGuildInfo &into) {
|
|||||||
|
|
||||||
bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
|
bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
|
||||||
if(m_db == nullptr) {
|
if(m_db == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Requested char info on %d when we have no database object.", char_id);
|
LogGuilds("Requested char info on [{}] when we have no database object", char_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,7 +983,7 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
|
|||||||
|
|
||||||
auto row = results.begin();
|
auto row = results.begin();
|
||||||
ProcessGuildMember(row, into);
|
ProcessGuildMember(row, into);
|
||||||
Log(Logs::Detail, Logs::Guilds, "Retreived guild member info for char %d", char_id);
|
LogGuilds("Retreived guild member info for char [{}]", char_id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -1098,16 +1098,16 @@ bool BaseGuildManager::GuildExists(uint32 guild_id) const {
|
|||||||
|
|
||||||
bool BaseGuildManager::IsGuildLeader(uint32 guild_id, uint32 char_id) const {
|
bool BaseGuildManager::IsGuildLeader(uint32 guild_id, uint32 char_id) const {
|
||||||
if(guild_id == GUILD_NONE) {
|
if(guild_id == GUILD_NONE) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check leader for char %d: not a guild.", char_id);
|
LogGuilds("Check leader for char [{}]: not a guild", char_id);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||||
res = m_guilds.find(guild_id);
|
res = m_guilds.find(guild_id);
|
||||||
if(res == m_guilds.end()) {
|
if(res == m_guilds.end()) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check leader for char %d: invalid guild.", char_id);
|
LogGuilds("Check leader for char [{}]: invalid guild", char_id);
|
||||||
return(false); //invalid guild
|
return(false); //invalid guild
|
||||||
}
|
}
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check leader for guild %d, char %d: leader id=%d", guild_id, char_id, res->second->leader_char_id);
|
LogGuilds("Check leader for guild [{}], char [{}]: leader id=[{}]", guild_id, char_id, res->second->leader_char_id);
|
||||||
return(char_id == res->second->leader_char_id);
|
return(char_id == res->second->leader_char_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1137,20 +1137,20 @@ uint8 BaseGuildManager::GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 cha
|
|||||||
|
|
||||||
bool BaseGuildManager::CheckGMStatus(uint32 guild_id, uint8 status) const {
|
bool BaseGuildManager::CheckGMStatus(uint32 guild_id, uint8 status) const {
|
||||||
if(status >= 250) {
|
if(status >= 250) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check permission on guild %d with user status %d > 250, granted.", guild_id, status);
|
LogGuilds("Check permission on guild [{}] with user status [{}] > 250, granted", guild_id, status);
|
||||||
return(true); //250+ as allowed anything
|
return(true); //250+ as allowed anything
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||||
res = m_guilds.find(guild_id);
|
res = m_guilds.find(guild_id);
|
||||||
if(res == m_guilds.end()) {
|
if(res == m_guilds.end()) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check permission on guild %d with user status %d, no such guild, denied.", guild_id, status);
|
LogGuilds("Check permission on guild [{}] with user status [{}], no such guild, denied", guild_id, status);
|
||||||
return(false); //invalid guild
|
return(false); //invalid guild
|
||||||
}
|
}
|
||||||
|
|
||||||
bool granted = (res->second->minstatus <= status);
|
bool granted = (res->second->minstatus <= status);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check permission on guild %s (%d) with user status %d. Min status %d: %s",
|
LogGuilds("Check permission on guild [{}] ([{}]) with user status [{}]. Min status [{}]: [{}]",
|
||||||
res->second->name.c_str(), guild_id, status, res->second->minstatus, granted?"granted":"denied");
|
res->second->name.c_str(), guild_id, status, res->second->minstatus, granted?"granted":"denied");
|
||||||
|
|
||||||
return(granted);
|
return(granted);
|
||||||
@@ -1158,21 +1158,21 @@ bool BaseGuildManager::CheckGMStatus(uint32 guild_id, uint8 status) const {
|
|||||||
|
|
||||||
bool BaseGuildManager::CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const {
|
bool BaseGuildManager::CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const {
|
||||||
if(rank > GUILD_MAX_RANK) {
|
if(rank > GUILD_MAX_RANK) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check permission on guild %d and rank %d for action %s (%d): Invalid rank, denied.",
|
LogGuilds("Check permission on guild [{}] and rank [{}] for action [{}] ([{}]): Invalid rank, denied",
|
||||||
guild_id, rank, GuildActionNames[act], act);
|
guild_id, rank, GuildActionNames[act], act);
|
||||||
return(false); //invalid rank
|
return(false); //invalid rank
|
||||||
}
|
}
|
||||||
std::map<uint32, GuildInfo *>::const_iterator res;
|
std::map<uint32, GuildInfo *>::const_iterator res;
|
||||||
res = m_guilds.find(guild_id);
|
res = m_guilds.find(guild_id);
|
||||||
if(res == m_guilds.end()) {
|
if(res == m_guilds.end()) {
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check permission on guild %d and rank %d for action %s (%d): Invalid guild, denied.",
|
LogGuilds("Check permission on guild [{}] and rank [{}] for action [{}] ([{}]): Invalid guild, denied",
|
||||||
guild_id, rank, GuildActionNames[act], act);
|
guild_id, rank, GuildActionNames[act], act);
|
||||||
return(false); //invalid guild
|
return(false); //invalid guild
|
||||||
}
|
}
|
||||||
|
|
||||||
bool granted = res->second->ranks[rank].permissions[act];
|
bool granted = res->second->ranks[rank].permissions[act];
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Guilds, "Check permission on guild %s (%d) and rank %s (%d) for action %s (%d): %s",
|
LogGuilds("Check permission on guild [{}] ([{}]) and rank [{}] ([{}]) for action [{}] ([{}]): [{}]",
|
||||||
res->second->name.c_str(), guild_id,
|
res->second->name.c_str(), guild_id,
|
||||||
res->second->ranks[rank].name.c_str(), rank,
|
res->second->ranks[rank].name.c_str(), rank,
|
||||||
GuildActionNames[act], act,
|
GuildActionNames[act], act,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1381,7 +1381,7 @@ int16 EQEmu::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == INVALID_INDEX) {
|
if (result == INVALID_INDEX) {
|
||||||
Log(Logs::General, Logs::Error, "InventoryProfile::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot);
|
LogError("InventoryProfile::_PutItem: Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot);
|
||||||
InventoryProfile::MarkDirty(inst); // Slot not found, clean up
|
InventoryProfile::MarkDirty(inst); // Slot not found, clean up
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* 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 "ip_util.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ip
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint32_t IpUtil::IPToUInt(const std::string &ip)
|
||||||
|
{
|
||||||
|
int a, b, c, d;
|
||||||
|
uint32_t addr = 0;
|
||||||
|
|
||||||
|
if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = a << 24;
|
||||||
|
addr |= b << 16;
|
||||||
|
addr |= c << 8;
|
||||||
|
addr |= d;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ip
|
||||||
|
* @param network
|
||||||
|
* @param mask
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask)
|
||||||
|
{
|
||||||
|
uint32_t ip_addr = IpUtil::IPToUInt(ip);
|
||||||
|
uint32_t network_addr = IpUtil::IPToUInt(network);
|
||||||
|
uint32_t mask_addr = IpUtil::IPToUInt(mask);
|
||||||
|
|
||||||
|
uint32_t net_lower = (network_addr & mask_addr);
|
||||||
|
uint32_t net_upper = (net_lower | (~mask_addr));
|
||||||
|
|
||||||
|
return ip_addr >= net_lower && ip_addr <= net_upper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ip
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
IpUtil::IsIpInRange(ip, "10.0.0.0", "255.0.0.0") ||
|
||||||
|
IpUtil::IsIpInRange(ip, "172.16.0.0", "255.240.0.0") ||
|
||||||
|
IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0")
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -18,15 +18,19 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_API_ZONE_DATA_SERVICE_H
|
#ifndef EQEMU_IP_UTIL_H
|
||||||
#define EQEMU_API_ZONE_DATA_SERVICE_H
|
#define EQEMU_IP_UTIL_H
|
||||||
|
|
||||||
#include "../common/json/json.h"
|
#include "types.h"
|
||||||
|
#include "iostream"
|
||||||
|
|
||||||
class EQEmuApiZoneDataService {
|
class IpUtil {
|
||||||
public:
|
public:
|
||||||
static void get(Json::Value &response, const std::vector<std::string> &args);
|
|
||||||
|
static uint32_t IPToUInt(const std::string &ip);
|
||||||
|
static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask);
|
||||||
|
static bool IsIpInPrivateRfc1918(const std::string &ip);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_IP_UTIL_H
|
||||||
#endif //EQEMU_API_ZONE_DATA_SERVICE_H
|
|
||||||
+1
-1
@@ -413,7 +413,7 @@ namespace EQEmu
|
|||||||
int32 SkillModMax; // Max skill point modification
|
int32 SkillModMax; // Max skill point modification
|
||||||
uint32 SkillModType; // Type of skill for SkillModValue to apply to
|
uint32 SkillModType; // Type of skill for SkillModValue to apply to
|
||||||
uint32 BaneDmgRace; // Bane Damage Race
|
uint32 BaneDmgRace; // Bane Damage Race
|
||||||
int8 BaneDmgAmt; // Bane Damage Body Amount
|
int32 BaneDmgAmt; // Bane Damage Body Amount
|
||||||
uint32 BaneDmgBody; // Bane Damage Body
|
uint32 BaneDmgBody; // Bane Damage Body
|
||||||
bool Magic; // True=Magic Item, False=not
|
bool Magic; // True=Magic Item, False=not
|
||||||
int32 CastTime_;
|
int32 CastTime_;
|
||||||
|
|||||||
+84
-12
@@ -1,26 +1,29 @@
|
|||||||
#include "json_config.h"
|
#include "json_config.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
EQ::JsonConfigFile::JsonConfigFile()
|
EQ::JsonConfigFile::JsonConfigFile() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EQ::JsonConfigFile::JsonConfigFile(const Json::Value &value)
|
EQ::JsonConfigFile::JsonConfigFile(const Json::Value &value)
|
||||||
{
|
{
|
||||||
m_root = value;
|
m_root = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQ::JsonConfigFile::~JsonConfigFile()
|
EQ::JsonConfigFile::~JsonConfigFile() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EQ::JsonConfigFile EQ::JsonConfigFile::Load(const std::string &filename)
|
/**
|
||||||
|
* @param file_name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
EQ::JsonConfigFile EQ::JsonConfigFile::Load(
|
||||||
|
const std::string &file_name
|
||||||
|
)
|
||||||
{
|
{
|
||||||
JsonConfigFile ret;
|
JsonConfigFile ret;
|
||||||
ret.m_root = Json::Value();
|
ret.m_root = Json::Value();
|
||||||
|
|
||||||
std::ifstream ifs;
|
std::ifstream ifs;
|
||||||
ifs.open(filename, std::ifstream::in);
|
ifs.open(file_name, std::ifstream::in);
|
||||||
|
|
||||||
if (!ifs.good()) {
|
if (!ifs.good()) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -36,7 +39,43 @@ EQ::JsonConfigFile EQ::JsonConfigFile::Load(const std::string &filename)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EQ::JsonConfigFile::GetVariableString(const std::string &title, const std::string ¶meter, const std::string &default_value) {
|
/**
|
||||||
|
* @param file_name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
void EQ::JsonConfigFile::Save(
|
||||||
|
const std::string &file_name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::ofstream opened_config_file;
|
||||||
|
opened_config_file.open(file_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab and build config contents
|
||||||
|
*/
|
||||||
|
Json::StreamWriterBuilder write_builder;
|
||||||
|
write_builder["indentation"] = " ";
|
||||||
|
std::string document = Json::writeString(write_builder, m_root);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write current contents and close
|
||||||
|
*/
|
||||||
|
opened_config_file << document;
|
||||||
|
opened_config_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param title
|
||||||
|
* @param parameter
|
||||||
|
* @param default_value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string EQ::JsonConfigFile::GetVariableString(
|
||||||
|
const std::string &title,
|
||||||
|
const std::string ¶meter,
|
||||||
|
const std::string &default_value
|
||||||
|
)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
||||||
return m_root[title][parameter].asString();
|
return m_root[title][parameter].asString();
|
||||||
@@ -49,7 +88,18 @@ std::string EQ::JsonConfigFile::GetVariableString(const std::string &title, cons
|
|||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EQ::JsonConfigFile::GetVariableInt(const std::string &title, const std::string ¶meter, const int default_value) {
|
/**
|
||||||
|
* @param title
|
||||||
|
* @param parameter
|
||||||
|
* @param default_value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int EQ::JsonConfigFile::GetVariableInt(
|
||||||
|
const std::string &title,
|
||||||
|
const std::string ¶meter,
|
||||||
|
const int default_value
|
||||||
|
)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
||||||
return m_root[title][parameter].asInt();
|
return m_root[title][parameter].asInt();
|
||||||
@@ -62,7 +112,18 @@ int EQ::JsonConfigFile::GetVariableInt(const std::string &title, const std::stri
|
|||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EQ::JsonConfigFile::GetVariableBool(const std::string &title, const std::string ¶meter, const bool default_value) {
|
/**
|
||||||
|
* @param title
|
||||||
|
* @param parameter
|
||||||
|
* @param default_value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool EQ::JsonConfigFile::GetVariableBool(
|
||||||
|
const std::string &title,
|
||||||
|
const std::string ¶meter,
|
||||||
|
const bool default_value
|
||||||
|
)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
||||||
return m_root[title][parameter].asBool();
|
return m_root[title][parameter].asBool();
|
||||||
@@ -75,7 +136,18 @@ bool EQ::JsonConfigFile::GetVariableBool(const std::string &title, const std::st
|
|||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double EQ::JsonConfigFile::GetVariableDouble(const std::string &title, const std::string ¶meter, const double default_value) {
|
/**
|
||||||
|
* @param title
|
||||||
|
* @param parameter
|
||||||
|
* @param default_value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
double EQ::JsonConfigFile::GetVariableDouble(
|
||||||
|
const std::string &title,
|
||||||
|
const std::string ¶meter,
|
||||||
|
const double default_value
|
||||||
|
)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
if (m_root.isMember(title) && m_root[title].isMember(parameter)) {
|
||||||
return m_root[title][parameter].asDouble();
|
return m_root[title][parameter].asDouble();
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ namespace EQ
|
|||||||
class JsonConfigFile
|
class JsonConfigFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
JsonConfigFile();
|
||||||
JsonConfigFile(const Json::Value &value);
|
JsonConfigFile(const Json::Value &value);
|
||||||
~JsonConfigFile();
|
~JsonConfigFile();
|
||||||
|
|
||||||
static JsonConfigFile Load(const std::string &filename);
|
static JsonConfigFile Load(const std::string &file_name);
|
||||||
|
void Save(const std::string &file_name);
|
||||||
|
|
||||||
std::string GetVariableString(const std::string &title, const std::string ¶meter, const std::string &default_value);
|
std::string GetVariableString(const std::string &title, const std::string ¶meter, const std::string &default_value);
|
||||||
int GetVariableInt(const std::string &title, const std::string ¶meter, const int default_value);
|
int GetVariableInt(const std::string &title, const std::string ¶meter, const int default_value);
|
||||||
@@ -19,7 +21,6 @@ namespace EQ
|
|||||||
|
|
||||||
Json::Value& RawHandle() { return m_root; }
|
Json::Value& RawHandle() { return m_root; }
|
||||||
private:
|
private:
|
||||||
JsonConfigFile();
|
|
||||||
Json::Value m_root;
|
Json::Value m_root;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,15 +32,15 @@
|
|||||||
//
|
//
|
||||||
#define VARSTRUCT_DECODE_TYPE(Type, Buffer) *(Type *)Buffer; Buffer += sizeof(Type);
|
#define VARSTRUCT_DECODE_TYPE(Type, Buffer) *(Type *)Buffer; Buffer += sizeof(Type);
|
||||||
#define VARSTRUCT_DECODE_STRING(String, Buffer) strcpy(String, Buffer); Buffer += strlen(String)+1;
|
#define VARSTRUCT_DECODE_STRING(String, Buffer) strcpy(String, Buffer); Buffer += strlen(String)+1;
|
||||||
#define VARSTRUCT_ENCODE_STRING(Buffer, String) { sprintf(Buffer, "%s", String); Buffer += strlen(String) + 1; }
|
#define VARSTRUCT_ENCODE_STRING(Buffer, String) { int length = sprintf(Buffer, "%s", String); Buffer += length + 1; }
|
||||||
#define VARSTRUCT_ENCODE_INTSTRING(Buffer, Number) { sprintf(Buffer, "%i", Number); Buffer += strlen(Buffer) + 1; }
|
#define VARSTRUCT_ENCODE_INTSTRING(Buffer, Number) { int length = sprintf(Buffer, "%i", Number); Buffer += length + 1; }
|
||||||
#define VARSTRUCT_ENCODE_TYPE(Type, Buffer, Value) { *(Type *)Buffer = Value; Buffer += sizeof(Type); }
|
#define VARSTRUCT_ENCODE_TYPE(Type, Buffer, Value) { *(Type *)Buffer = Value; Buffer += sizeof(Type); }
|
||||||
#define VARSTRUCT_SKIP_TYPE(Type, Buffer) Buffer += sizeof(Type);
|
#define VARSTRUCT_SKIP_TYPE(Type, Buffer) Buffer += sizeof(Type);
|
||||||
|
|
||||||
#define VERIFY_PACKET_LENGTH(OPCode, Packet, StructName) \
|
#define VERIFY_PACKET_LENGTH(OPCode, Packet, StructName) \
|
||||||
if(Packet->size != sizeof(StructName)) \
|
if(Packet->size != sizeof(StructName)) \
|
||||||
{ \
|
{ \
|
||||||
Log(Logs::Detail, Logs::Netcode, "Size mismatch in " #OPCode " expected %i got %i", sizeof(StructName), Packet->size); \
|
LogNetcode("Size mismatch in " #OPCode " expected [{}] got [{}]", sizeof(StructName), Packet->size); \
|
||||||
DumpPacket(Packet); \
|
DumpPacket(Packet); \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -368,6 +368,7 @@ void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream, bool reliab
|
|||||||
packet.PutUInt8(0, 0);
|
packet.PutUInt8(0, 0);
|
||||||
packet.PutPacket(1, p);
|
packet.PutPacket(1, p);
|
||||||
InternalQueuePacket(packet, stream, reliable);
|
InternalQueuePacket(packet, stream, reliable);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalQueuePacket(p, stream, reliable);
|
InternalQueuePacket(p, stream, reliable);
|
||||||
@@ -384,7 +385,7 @@ EQ::Net::DaybreakConnectionStats EQ::Net::DaybreakConnection::GetStats()
|
|||||||
|
|
||||||
void EQ::Net::DaybreakConnection::ResetStats()
|
void EQ::Net::DaybreakConnection::ResetStats()
|
||||||
{
|
{
|
||||||
m_stats = DaybreakConnectionStats();
|
m_stats.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::Net::DaybreakConnection::Process()
|
void EQ::Net::DaybreakConnection::Process()
|
||||||
@@ -417,6 +418,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
|||||||
|
|
||||||
auto opcode = p.GetInt8(1);
|
auto opcode = p.GetInt8(1);
|
||||||
if (p.GetInt8(0) == 0 && (opcode == OP_KeepAlive || opcode == OP_OutboundPing)) {
|
if (p.GetInt8(0) == 0 && (opcode == OP_KeepAlive || opcode == OP_OutboundPing)) {
|
||||||
|
m_stats.bytes_after_decode += p.Length();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,6 +427,8 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
|||||||
if (m_owner->m_on_error_message) {
|
if (m_owner->m_on_error_message) {
|
||||||
m_owner->m_on_error_message(fmt::format("Tossed packet that failed CRC of type {0:#x}", p.Length() >= 2 ? p.GetInt8(1) : 0));
|
m_owner->m_on_error_message(fmt::format("Tossed packet that failed CRC of type {0:#x}", p.Length() >= 2 ? p.GetInt8(1) : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_stats.bytes_after_decode += p.Length();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,6 +457,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_stats.bytes_after_decode += temp.Length();
|
||||||
ProcessDecodedPacket(StaticPacket(temp.Data(), temp.Length()));
|
ProcessDecodedPacket(StaticPacket(temp.Data(), temp.Length()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -471,10 +476,12 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_stats.bytes_after_decode += temp.Length();
|
||||||
ProcessDecodedPacket(StaticPacket(temp.Data(), temp.Length()));
|
ProcessDecodedPacket(StaticPacket(temp.Data(), temp.Length()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
m_stats.bytes_after_decode += p.Length();
|
||||||
ProcessDecodedPacket(p);
|
ProcessDecodedPacket(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -993,7 +1000,7 @@ uint32_t Deflate(const uint8_t* in, uint32_t in_len, uint8_t* out, uint32_t out_
|
|||||||
zstream.avail_in = in_len;
|
zstream.avail_in = in_len;
|
||||||
zstream.opaque = Z_NULL;
|
zstream.opaque = Z_NULL;
|
||||||
|
|
||||||
deflateInit(&zstream, Z_FINISH);
|
deflateInit(&zstream, Z_BEST_SPEED);
|
||||||
zstream.next_out = out;
|
zstream.next_out = out;
|
||||||
zstream.avail_out = out_len;
|
zstream.avail_out = out_len;
|
||||||
|
|
||||||
@@ -1285,6 +1292,9 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (PacketCanBeEncoded(p)) {
|
if (PacketCanBeEncoded(p)) {
|
||||||
|
|
||||||
|
m_stats.bytes_before_encode += p.Length();
|
||||||
|
|
||||||
DynamicPacket out;
|
DynamicPacket out;
|
||||||
out.PutPacket(0, p);
|
out.PutPacket(0, p);
|
||||||
|
|
||||||
@@ -1332,6 +1342,8 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_stats.bytes_before_encode += p.Length();
|
||||||
|
|
||||||
uv_udp_send_t *send_req = new uv_udp_send_t;
|
uv_udp_send_t *send_req = new uv_udp_send_t;
|
||||||
sockaddr_in send_addr;
|
sockaddr_in send_addr;
|
||||||
uv_ip4_addr(m_endpoint.c_str(), m_port, &send_addr);
|
uv_ip4_addr(m_endpoint.c_str(), m_port, &send_addr);
|
||||||
|
|||||||
@@ -91,6 +91,24 @@ namespace EQ
|
|||||||
resent_fragments = 0;
|
resent_fragments = 0;
|
||||||
resent_full = 0;
|
resent_full = 0;
|
||||||
datarate_remaining = 0.0;
|
datarate_remaining = 0.0;
|
||||||
|
bytes_after_decode = 0;
|
||||||
|
bytes_before_encode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset() {
|
||||||
|
recv_bytes = 0;
|
||||||
|
sent_bytes = 0;
|
||||||
|
min_ping = 0xFFFFFFFFFFFFFFFFUL;
|
||||||
|
max_ping = 0;
|
||||||
|
avg_ping = 0;
|
||||||
|
created = Clock::now();
|
||||||
|
dropped_datarate_packets = 0;
|
||||||
|
resent_packets = 0;
|
||||||
|
resent_fragments = 0;
|
||||||
|
resent_full = 0;
|
||||||
|
datarate_remaining = 0.0;
|
||||||
|
bytes_after_decode = 0;
|
||||||
|
bytes_before_encode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t recv_bytes;
|
uint64_t recv_bytes;
|
||||||
@@ -111,6 +129,8 @@ namespace EQ
|
|||||||
uint64_t resent_fragments;
|
uint64_t resent_fragments;
|
||||||
uint64_t resent_full;
|
uint64_t resent_full;
|
||||||
double datarate_remaining;
|
double datarate_remaining;
|
||||||
|
uint64_t bytes_after_decode;
|
||||||
|
uint64_t bytes_before_encode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DaybreakConnectionManager;
|
class DaybreakConnectionManager;
|
||||||
@@ -237,7 +257,7 @@ namespace EQ
|
|||||||
resend_delay_min = 150;
|
resend_delay_min = 150;
|
||||||
resend_delay_max = 5000;
|
resend_delay_max = 5000;
|
||||||
connect_delay_ms = 500;
|
connect_delay_ms = 500;
|
||||||
stale_connection_ms = 90000;
|
stale_connection_ms = 60000;
|
||||||
connect_stale_ms = 5000;
|
connect_stale_ms = 5000;
|
||||||
crc_length = 2;
|
crc_length = 2;
|
||||||
max_packet_size = 512;
|
max_packet_size = 512;
|
||||||
@@ -249,7 +269,7 @@ namespace EQ
|
|||||||
simulated_in_packet_loss = 0;
|
simulated_in_packet_loss = 0;
|
||||||
simulated_out_packet_loss = 0;
|
simulated_out_packet_loss = 0;
|
||||||
tic_rate_hertz = 60.0;
|
tic_rate_hertz = 60.0;
|
||||||
resend_timeout = 90000;
|
resend_timeout = 30000;
|
||||||
connection_close_time = 2000;
|
connection_close_time = 2000;
|
||||||
outgoing_data_rate = 0.0;
|
outgoing_data_rate = 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-11
@@ -1,6 +1,5 @@
|
|||||||
#include "eqstream.h"
|
#include "eqstream.h"
|
||||||
#include "../eqemu_logsys.h"
|
#include "../eqemu_logsys.h"
|
||||||
#include "../eqemu_logsys_fmt.h"
|
|
||||||
|
|
||||||
EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_daybreak(options.daybreak_options)
|
EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_daybreak(options.daybreak_options)
|
||||||
{
|
{
|
||||||
@@ -13,6 +12,13 @@ EQ::Net::EQStreamManager::~EQStreamManager()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStreamManager::SetOptions(const EQStreamManagerInterfaceOptions &options)
|
||||||
|
{
|
||||||
|
m_options = options;
|
||||||
|
auto &opts = m_daybreak.GetOptions();
|
||||||
|
opts = options.daybreak_options;
|
||||||
|
}
|
||||||
|
|
||||||
void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection)
|
void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection)
|
||||||
{
|
{
|
||||||
std::shared_ptr<EQStream> stream(new EQStream(this, connection));
|
std::shared_ptr<EQStream> stream(new EQStream(this, connection));
|
||||||
@@ -65,9 +71,7 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
|
|||||||
opcode = p->GetOpcodeBypass();
|
opcode = p->GetOpcodeBypass();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (m_owner->GetOptions().track_opcode_stats) {
|
m_packet_sent_count[static_cast<int>(p->GetOpcode())]++; //Wont bother with bypass tracking of these since those are rare for testing anyway
|
||||||
m_packet_sent_count[p->GetOpcode()]++; //Wont bother with bypass tracking of these since those are rare for testing anyway
|
|
||||||
}
|
|
||||||
opcode = (*m_opcode_manager)->EmuToEQ(p->GetOpcode());
|
opcode = (*m_opcode_manager)->EmuToEQ(p->GetOpcode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,9 +121,7 @@ EQApplicationPacket *EQ::Net::EQStream::PopPacket() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode);
|
EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode);
|
||||||
if (m_owner->GetOptions().track_opcode_stats) {
|
m_packet_recv_count[static_cast<int>(emu_op)]++;
|
||||||
m_packet_recv_count[emu_op]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->GetOptions().opcode_size, p->Length() - m_owner->GetOptions().opcode_size);
|
EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->GetOptions().opcode_size, p->Length() - m_owner->GetOptions().opcode_size);
|
||||||
ret->SetProtocolOpcode(opcode);
|
ret->SetProtocolOpcode(opcode);
|
||||||
@@ -182,23 +184,23 @@ EQStreamInterface::MatchState EQ::Net::EQStream::CheckSignature(const Signature
|
|||||||
|
|
||||||
if (opcode == sig->first_eq_opcode) {
|
if (opcode == sig->first_eq_opcode) {
|
||||||
if (length == sig->first_length) {
|
if (length == sig->first_length) {
|
||||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length matched {3}",
|
LogF(Logs::General, Logs::Netcode, "[StreamIdentify] {0}:{1}: First opcode matched {2:#x} and length matched {3}",
|
||||||
m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length);
|
m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length);
|
||||||
return MatchSuccessful;
|
return MatchSuccessful;
|
||||||
}
|
}
|
||||||
else if (length == 0) {
|
else if (length == 0) {
|
||||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length is ignored.",
|
LogF(Logs::General, Logs::Netcode, "[StreamIdentify] {0}:{1}: First opcode matched {2:#x} and length is ignored.",
|
||||||
m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode);
|
m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode);
|
||||||
return MatchSuccessful;
|
return MatchSuccessful;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} but length {3} did not match expected {4}",
|
LogF(Logs::General, Logs::Netcode, "[StreamIdentify] {0}:{1}: First opcode matched {2:#x} but length {3} did not match expected {4}",
|
||||||
m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length, sig->first_length);
|
m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length, sig->first_length);
|
||||||
return MatchFailed;
|
return MatchFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode {1:#x} did not match expected {2:#x}",
|
LogF(Logs::General, Logs::Netcode, "[StreamIdentify] {0}:{1}: First opcode {1:#x} did not match expected {2:#x}",
|
||||||
m_connection->RemoteEndpoint(), m_connection->RemotePort(), opcode, sig->first_eq_opcode);
|
m_connection->RemoteEndpoint(), m_connection->RemotePort(), opcode, sig->first_eq_opcode);
|
||||||
return MatchFailed;
|
return MatchFailed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace EQ
|
|||||||
EQStreamManager(const EQStreamManagerInterfaceOptions &options);
|
EQStreamManager(const EQStreamManagerInterfaceOptions &options);
|
||||||
~EQStreamManager();
|
~EQStreamManager();
|
||||||
|
|
||||||
|
virtual void SetOptions(const EQStreamManagerInterfaceOptions& options);
|
||||||
void OnNewConnection(std::function<void(std::shared_ptr<EQStream>)> func) { m_on_new_connection = func; }
|
void OnNewConnection(std::function<void(std::shared_ptr<EQStream>)> func) { m_on_new_connection = func; }
|
||||||
void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
|
void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
|
||||||
private:
|
private:
|
||||||
@@ -65,8 +66,8 @@ namespace EQ
|
|||||||
std::shared_ptr<DaybreakConnection> m_connection;
|
std::shared_ptr<DaybreakConnection> m_connection;
|
||||||
OpcodeManager **m_opcode_manager;
|
OpcodeManager **m_opcode_manager;
|
||||||
std::deque<std::unique_ptr<EQ::Net::Packet>> m_packet_queue;
|
std::deque<std::unique_ptr<EQ::Net::Packet>> m_packet_queue;
|
||||||
std::unordered_map<EmuOpcode, int> m_packet_recv_count;
|
std::unordered_map<int, int> m_packet_recv_count;
|
||||||
std::unordered_map<EmuOpcode, int> m_packet_sent_count;
|
std::unordered_map<int, int> m_packet_sent_count;
|
||||||
friend class EQStreamManager;
|
friend class EQStreamManager;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "servertalk_client_connection.h"
|
#include "servertalk_client_connection.h"
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "../eqemu_logsys.h"
|
#include "../eqemu_logsys.h"
|
||||||
#include "../eqemu_logsys_fmt.h"
|
|
||||||
|
|
||||||
EQ::Net::ServertalkClient::ServertalkClient(const std::string &addr, int port, bool ipv6, const std::string &identifier, const std::string &credentials)
|
EQ::Net::ServertalkClient::ServertalkClient(const std::string &addr, int port, bool ipv6, const std::string &identifier, const std::string &credentials)
|
||||||
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkClient::Connect, this))))
|
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkClient::Connect, this))))
|
||||||
@@ -79,15 +78,15 @@ void EQ::Net::ServertalkClient::Connect()
|
|||||||
m_connecting = true;
|
m_connecting = true;
|
||||||
EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||||
if (connection == nullptr) {
|
if (connection == nullptr) {
|
||||||
LogF(Logs::General, Logs::TCP_Connection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
LogF(Logs::General, Logs::TCPConnection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogF(Logs::General, Logs::TCP_Connection, "Connected to {0}:{1}", m_addr, m_port);
|
LogF(Logs::General, Logs::TCPConnection, "Connected to {0}:{1}", m_addr, m_port);
|
||||||
m_connection = connection;
|
m_connection = connection;
|
||||||
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
|
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
|
||||||
LogF(Logs::General, Logs::TCP_Connection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
LogF(Logs::General, Logs::TCPConnection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||||
m_encrypted = false;
|
m_encrypted = false;
|
||||||
m_connection.reset();
|
m_connection.reset();
|
||||||
});
|
});
|
||||||
@@ -214,7 +213,7 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogF(Logs::General, Logs::Error, "Could not process hello, size != {0}", 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
|
LogError("Could not process hello, size != {0}", 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -226,7 +225,7 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
LogF(Logs::General, Logs::Error, "Error parsing hello from server: {0}", ex.what());
|
LogError("Error parsing hello from server: {0}", ex.what());
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
|
|
||||||
if (m_on_connect_cb) {
|
if (m_on_connect_cb) {
|
||||||
@@ -253,7 +252,7 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
LogF(Logs::General, Logs::Error, "Error parsing hello from server: {0}", ex.what());
|
LogError("Error parsing hello from server: {0}", ex.what());
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
|
|
||||||
if (m_on_connect_cb) {
|
if (m_on_connect_cb) {
|
||||||
@@ -276,7 +275,7 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
|
|||||||
std::unique_ptr<unsigned char[]> decrypted_text(new unsigned char[message_len]);
|
std::unique_ptr<unsigned char[]> decrypted_text(new unsigned char[message_len]);
|
||||||
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key))
|
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key))
|
||||||
{
|
{
|
||||||
LogF(Logs::General, Logs::Error, "Error decrypting message from server");
|
LogError("Error decrypting message from server");
|
||||||
(*(uint64_t*)&m_nonce_theirs[0])++;
|
(*(uint64_t*)&m_nonce_theirs[0])++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -324,7 +323,7 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
LogF(Logs::General, Logs::Error, "Error parsing message from server: {0}", ex.what());
|
LogError("Error parsing message from server: {0}", ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "servertalk_legacy_client_connection.h"
|
#include "servertalk_legacy_client_connection.h"
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "../eqemu_logsys.h"
|
#include "../eqemu_logsys.h"
|
||||||
#include "../eqemu_logsys_fmt.h"
|
|
||||||
|
|
||||||
EQ::Net::ServertalkLegacyClient::ServertalkLegacyClient(const std::string &addr, int port, bool ipv6)
|
EQ::Net::ServertalkLegacyClient::ServertalkLegacyClient(const std::string &addr, int port, bool ipv6)
|
||||||
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkLegacyClient::Connect, this))))
|
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkLegacyClient::Connect, this))))
|
||||||
@@ -59,15 +58,15 @@ void EQ::Net::ServertalkLegacyClient::Connect()
|
|||||||
m_connecting = true;
|
m_connecting = true;
|
||||||
EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||||
if (connection == nullptr) {
|
if (connection == nullptr) {
|
||||||
LogF(Logs::General, Logs::TCP_Connection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
LogF(Logs::General, Logs::TCPConnection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogF(Logs::General, Logs::TCP_Connection, "Connected to {0}:{1}", m_addr, m_port);
|
LogF(Logs::General, Logs::TCPConnection, "Connected to {0}:{1}", m_addr, m_port);
|
||||||
m_connection = connection;
|
m_connection = connection;
|
||||||
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
|
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
|
||||||
LogF(Logs::General, Logs::TCP_Connection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
LogF(Logs::General, Logs::TCPConnection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||||
m_connection.reset();
|
m_connection.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "servertalk_server_connection.h"
|
#include "servertalk_server_connection.h"
|
||||||
#include "servertalk_server.h"
|
#include "servertalk_server.h"
|
||||||
#include "../eqemu_logsys.h"
|
#include "../eqemu_logsys.h"
|
||||||
#include "../eqemu_logsys_fmt.h"
|
|
||||||
#include "../util/uuid.h"
|
#include "../util/uuid.h"
|
||||||
|
|
||||||
EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, EQ::Net::ServertalkServer *parent, bool encrypted, bool allow_downgrade)
|
EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, EQ::Net::ServertalkServer *parent, bool encrypted, bool allow_downgrade)
|
||||||
@@ -202,7 +201,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
{
|
{
|
||||||
#ifdef ENABLE_SECURITY
|
#ifdef ENABLE_SECURITY
|
||||||
if (downgrade_security && m_allow_downgrade && m_encrypted) {
|
if (downgrade_security && m_allow_downgrade && m_encrypted) {
|
||||||
LogF(Logs::General, Logs::TCP_Connection, "Downgraded encrypted connection to plaintext because otherside didn't support encryption {0}:{1}",
|
LogF(Logs::General, Logs::TCPConnection, "Downgraded encrypted connection to plaintext because otherside didn't support encryption {0}:{1}",
|
||||||
m_connection->RemoteIP(), m_connection->RemotePort());
|
m_connection->RemoteIP(), m_connection->RemotePort());
|
||||||
m_encrypted = false;
|
m_encrypted = false;
|
||||||
}
|
}
|
||||||
@@ -221,7 +220,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
|
|
||||||
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)p.Data() + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, cipher_len, m_nonce_theirs, m_shared_key))
|
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)p.Data() + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, cipher_len, m_nonce_theirs, m_shared_key))
|
||||||
{
|
{
|
||||||
LogF(Logs::General, Logs::Error, "Error decrypting handshake from client, dropping connection.");
|
LogError("Error decrypting handshake from client, dropping connection.");
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -230,7 +229,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
std::string credentials = (const char*)&decrypted_text[0] + (m_identifier.length() + 1);
|
std::string credentials = (const char*)&decrypted_text[0] + (m_identifier.length() + 1);
|
||||||
|
|
||||||
if (!m_parent->CheckCredentials(credentials)) {
|
if (!m_parent->CheckCredentials(credentials)) {
|
||||||
LogF(Logs::General, Logs::Error, "Got incoming connection with invalid credentials during handshake, dropping connection.");
|
LogError("Got incoming connection with invalid credentials during handshake, dropping connection.");
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -240,7 +239,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
LogF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what());
|
LogError("Error parsing handshake from client: {0}", ex.what());
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +249,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
auto credentials = p.GetCString(m_identifier.length() + 1);
|
auto credentials = p.GetCString(m_identifier.length() + 1);
|
||||||
|
|
||||||
if (!m_parent->CheckCredentials(credentials)) {
|
if (!m_parent->CheckCredentials(credentials)) {
|
||||||
LogF(Logs::General, Logs::Error, "Got incoming connection with invalid credentials during handshake, dropping connection.");
|
LogError("Got incoming connection with invalid credentials during handshake, dropping connection.");
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -258,7 +257,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
m_parent->ConnectionIdentified(this);
|
m_parent->ConnectionIdentified(this);
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
LogF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what());
|
LogError("Error parsing handshake from client: {0}", ex.what());
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,7 +267,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
auto credentials = p.GetCString(m_identifier.length() + 1);
|
auto credentials = p.GetCString(m_identifier.length() + 1);
|
||||||
|
|
||||||
if (!m_parent->CheckCredentials(credentials)) {
|
if (!m_parent->CheckCredentials(credentials)) {
|
||||||
LogF(Logs::General, Logs::Error, "Got incoming connection with invalid credentials during handshake, dropping connection.");
|
LogError("Got incoming connection with invalid credentials during handshake, dropping connection.");
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -276,7 +275,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b
|
|||||||
m_parent->ConnectionIdentified(this);
|
m_parent->ConnectionIdentified(this);
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
LogF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what());
|
LogError("Error parsing handshake from client: {0}", ex.what());
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -296,7 +295,7 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
|
|||||||
|
|
||||||
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key))
|
if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key))
|
||||||
{
|
{
|
||||||
LogF(Logs::General, Logs::Error, "Error decrypting message from client");
|
LogError("Error decrypting message from client");
|
||||||
(*(uint64_t*)&m_nonce_theirs[0])++;
|
(*(uint64_t*)&m_nonce_theirs[0])++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -344,6 +343,6 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
LogF(Logs::General, Logs::Error, "Error parsing message from client: {0}", ex.what());
|
LogError("Error parsing message from client: {0}", ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,265 @@
|
|||||||
|
#include "websocket_server.h"
|
||||||
|
#include "../event/event_loop.h"
|
||||||
|
#include "../event/timer.h"
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
struct MethodHandlerEntry
|
||||||
|
{
|
||||||
|
MethodHandlerEntry() {
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHandlerEntry(EQ::Net::WebsocketServer::MethodHandler h, int s) {
|
||||||
|
handler = h;
|
||||||
|
status = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Net::WebsocketServer::MethodHandler handler;
|
||||||
|
int status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EQ::Net::WebsocketServer::Impl
|
||||||
|
{
|
||||||
|
std::unique_ptr<TCPServer> server;
|
||||||
|
std::unique_ptr<EQ::Timer> ping_timer;
|
||||||
|
std::map<std::shared_ptr<websocket_connection>, std::unique_ptr<WebsocketServerConnection>> connections;
|
||||||
|
std::map<std::string, MethodHandlerEntry> methods;
|
||||||
|
websocket_server ws_server;
|
||||||
|
LoginHandler login_handler;
|
||||||
|
std::array<std::unordered_set<WebsocketServerConnection*>, SubscriptionEventMax> subscriptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
EQ::Net::WebsocketServer::WebsocketServer(const std::string &addr, int port)
|
||||||
|
{
|
||||||
|
_impl.reset(new Impl());
|
||||||
|
_impl->server.reset(new EQ::Net::TCPServer());
|
||||||
|
_impl->server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||||
|
auto wsc = _impl->ws_server.get_connection();
|
||||||
|
WebsocketServerConnection *c = new WebsocketServerConnection(this, connection, wsc);
|
||||||
|
_impl->connections.insert(std::make_pair(wsc, std::unique_ptr<WebsocketServerConnection>(c)));
|
||||||
|
});
|
||||||
|
|
||||||
|
_impl->ws_server.set_write_handler(
|
||||||
|
[this](websocketpp::connection_hdl hdl, char const *data, size_t size) -> websocketpp::lib::error_code {
|
||||||
|
auto c = _impl->ws_server.get_con_from_hdl(hdl);
|
||||||
|
auto iter = _impl->connections.find(c);
|
||||||
|
if (iter != _impl->connections.end()) {
|
||||||
|
iter->second->GetTCPConnection()->Write(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return websocketpp::lib::error_code();
|
||||||
|
});
|
||||||
|
|
||||||
|
_impl->ping_timer.reset(new EQ::Timer(5000, true, [this](EQ::Timer *t) {
|
||||||
|
auto iter = _impl->connections.begin();
|
||||||
|
|
||||||
|
while (iter != _impl->connections.end()) {
|
||||||
|
try {
|
||||||
|
auto &connection = iter->second;
|
||||||
|
connection->GetWebsocketConnection()->ping("keepalive");
|
||||||
|
}
|
||||||
|
catch (std::exception) {
|
||||||
|
iter->second->GetTCPConnection()->Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
_impl->methods.insert(std::make_pair("login", MethodHandlerEntry(std::bind(&WebsocketServer::Login, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||||
|
_impl->methods.insert(std::make_pair("subscribe", MethodHandlerEntry(std::bind(&WebsocketServer::Subscribe, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||||
|
_impl->methods.insert(std::make_pair("unsubscribe", MethodHandlerEntry(std::bind(&WebsocketServer::Unsubscribe, this, std::placeholders::_1, std::placeholders::_2), 0)));
|
||||||
|
_impl->login_handler = [](const WebsocketServerConnection* connection, const std::string& user, const std::string& pass) {
|
||||||
|
WebsocketLoginStatus ret;
|
||||||
|
ret.account_name = "admin";
|
||||||
|
|
||||||
|
if (connection->RemoteIP() == "127.0.0.1" || connection->RemoteIP() == "::") {
|
||||||
|
ret.logged_in = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.logged_in = false;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
_impl->ws_server.clear_access_channels(websocketpp::log::alevel::all);
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Net::WebsocketServer::~WebsocketServer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServer::ReleaseConnection(WebsocketServerConnection *connection)
|
||||||
|
{
|
||||||
|
UnsubscribeAll(connection);
|
||||||
|
|
||||||
|
_impl->connections.erase(connection->GetWebsocketConnection());
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value EQ::Net::WebsocketServer::HandleRequest(WebsocketServerConnection *connection, const std::string &method, const Json::Value ¶ms)
|
||||||
|
{
|
||||||
|
Json::Value err;
|
||||||
|
if (method != "login") {
|
||||||
|
if (!connection->IsAuthorized()) {
|
||||||
|
throw WebsocketException("Not logged in");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = _impl->methods.find(method);
|
||||||
|
if (iter != _impl->methods.end()) {
|
||||||
|
auto &s = iter->second;
|
||||||
|
if (s.status > connection->GetStatus()) {
|
||||||
|
throw WebsocketException("Status too low");
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.handler(connection, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw WebsocketException("Unknown Method");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServer::SetMethodHandler(const std::string &method, MethodHandler handler, int required_status)
|
||||||
|
{
|
||||||
|
//Reserved method names
|
||||||
|
if (method == "subscribe" ||
|
||||||
|
method == "unsubscribe" ||
|
||||||
|
method == "login") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_impl->methods[method] = MethodHandlerEntry(handler, required_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServer::SetLoginHandler(LoginHandler handler)
|
||||||
|
{
|
||||||
|
_impl->login_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServer::DispatchEvent(WebsocketSubscriptionEvent evt, Json::Value data, int required_status)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Json::Value event_obj;
|
||||||
|
event_obj["type"] = "event";
|
||||||
|
event_obj["event"] = (int)evt;
|
||||||
|
event_obj["data"] = data;
|
||||||
|
|
||||||
|
std::stringstream payload;
|
||||||
|
payload << event_obj;
|
||||||
|
|
||||||
|
for (auto &iter : _impl->connections) {
|
||||||
|
auto &c = iter.second;
|
||||||
|
|
||||||
|
if (c->GetStatus() >= required_status && IsSubscribed(c.get(), evt)) {
|
||||||
|
c->GetWebsocketConnection()->send(payload.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connection, const Json::Value ¶ms)
|
||||||
|
{
|
||||||
|
Json::Value ret;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Json::Value ret;
|
||||||
|
|
||||||
|
auto user = params[0].asString();
|
||||||
|
auto pass = params[1].asString();
|
||||||
|
|
||||||
|
auto r = _impl->login_handler(connection, user, pass);
|
||||||
|
|
||||||
|
if (r.logged_in) {
|
||||||
|
connection->SetAuthorized(true, r.account_name, r.account_id, 255);
|
||||||
|
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);
|
||||||
|
ret["status"] = "Ok";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
connection->SetAuthorized(false, "", 0, 0);
|
||||||
|
ret["status"] = "Not Authorized";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (std::exception) {
|
||||||
|
throw WebsocketException("Unable to process login request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value EQ::Net::WebsocketServer::Subscribe(WebsocketServerConnection *connection, const Json::Value ¶ms)
|
||||||
|
{
|
||||||
|
Json::Value ret;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto evt = params[0].asInt();
|
||||||
|
if (evt < 0 || evt >= SubscriptionEventMax) {
|
||||||
|
throw WebsocketException("Not a valid subscription");
|
||||||
|
}
|
||||||
|
|
||||||
|
DoSubscribe(connection, (WebsocketSubscriptionEvent)evt);
|
||||||
|
ret["status"] = "Ok";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (WebsocketException &ex) {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
catch (std::exception) {
|
||||||
|
throw WebsocketException("Unable to process unsubscribe request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value EQ::Net::WebsocketServer::Unsubscribe(WebsocketServerConnection *connection, const Json::Value ¶ms)
|
||||||
|
{
|
||||||
|
Json::Value ret;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto evt = params[0].asInt();
|
||||||
|
if (evt < 0 || evt >= SubscriptionEventMax) {
|
||||||
|
throw WebsocketException("Not a valid subscription");
|
||||||
|
}
|
||||||
|
|
||||||
|
DoUnsubscribe(connection, (WebsocketSubscriptionEvent)evt);
|
||||||
|
ret["status"] = "Ok";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (WebsocketException &ex) {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
catch (std::exception) {
|
||||||
|
throw WebsocketException("Unable to process unsubscribe request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServer::DoSubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub) {
|
||||||
|
auto &s = _impl->subscriptions[sub];
|
||||||
|
|
||||||
|
auto iter = s.find(connection);
|
||||||
|
if (iter == s.end()) {
|
||||||
|
s.insert(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServer::DoUnsubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub) {
|
||||||
|
auto &s = _impl->subscriptions[sub];
|
||||||
|
s.erase(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EQ::Net::WebsocketServer::IsSubscribed(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub) {
|
||||||
|
auto &s = _impl->subscriptions[sub];
|
||||||
|
return s.count(connection) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServer::UnsubscribeAll(WebsocketServerConnection *connection) {
|
||||||
|
for (auto i = 0; i < SubscriptionEventMax; ++i) {
|
||||||
|
DoUnsubscribe(connection, (WebsocketSubscriptionEvent)i);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "websocket_server_connection.h"
|
||||||
|
|
||||||
|
#include "../json/json.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Net
|
||||||
|
{
|
||||||
|
enum WebsocketSubscriptionEvent : int
|
||||||
|
{
|
||||||
|
SubscriptionEventNone,
|
||||||
|
SubscriptionEventLog,
|
||||||
|
SubscriptionEventMax
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WebsocketLoginStatus
|
||||||
|
{
|
||||||
|
bool logged_in;
|
||||||
|
std::string account_name;
|
||||||
|
uint32 account_id;
|
||||||
|
int status;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WebsocketException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebsocketException(const std::string &msg)
|
||||||
|
: _msg(msg.empty() ? "Unknown Error" : msg) { }
|
||||||
|
|
||||||
|
~WebsocketException() throw() {}
|
||||||
|
|
||||||
|
virtual char const *what() const throw() {
|
||||||
|
return _msg.c_str();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const std::string _msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WebsocketServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::function<Json::Value(WebsocketServerConnection*, const Json::Value&)> MethodHandler;
|
||||||
|
typedef std::function<WebsocketLoginStatus(WebsocketServerConnection*, const std::string&, const std::string&)> LoginHandler;
|
||||||
|
|
||||||
|
WebsocketServer(const std::string &addr, int port);
|
||||||
|
~WebsocketServer();
|
||||||
|
|
||||||
|
void SetMethodHandler(const std::string& method, MethodHandler handler, int required_status);
|
||||||
|
void SetLoginHandler(LoginHandler handler);
|
||||||
|
void DispatchEvent(WebsocketSubscriptionEvent evt, Json::Value data = Json::Value(), int required_status = 0);
|
||||||
|
private:
|
||||||
|
void ReleaseConnection(WebsocketServerConnection *connection);
|
||||||
|
Json::Value HandleRequest(WebsocketServerConnection *connection, const std::string& method, const Json::Value ¶ms);
|
||||||
|
|
||||||
|
Json::Value Login(WebsocketServerConnection *connection, const Json::Value ¶ms);
|
||||||
|
Json::Value Subscribe(WebsocketServerConnection *connection, const Json::Value ¶ms);
|
||||||
|
Json::Value Unsubscribe(WebsocketServerConnection *connection, const Json::Value ¶ms);
|
||||||
|
void DoSubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub);
|
||||||
|
void DoUnsubscribe(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub);
|
||||||
|
bool IsSubscribed(WebsocketServerConnection *connection, WebsocketSubscriptionEvent sub);
|
||||||
|
void UnsubscribeAll(WebsocketServerConnection *connection);
|
||||||
|
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> _impl;
|
||||||
|
|
||||||
|
friend class WebsocketServerConnection;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
#include "websocket_server_connection.h"
|
||||||
|
#include "websocket_server.h"
|
||||||
|
#include "../timer.h"
|
||||||
|
#include "../util/uuid.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
struct EQ::Net::WebsocketServerConnection::Impl {
|
||||||
|
WebsocketServer *parent;
|
||||||
|
std::shared_ptr<TCPConnection> connection;
|
||||||
|
std::shared_ptr<websocket_connection> ws_connection;
|
||||||
|
std::string id;
|
||||||
|
bool authorized;
|
||||||
|
std::string account_name;
|
||||||
|
uint32 account_id;
|
||||||
|
int status;
|
||||||
|
};
|
||||||
|
|
||||||
|
EQ::Net::WebsocketServerConnection::WebsocketServerConnection(WebsocketServer *parent,
|
||||||
|
std::shared_ptr<TCPConnection> connection,
|
||||||
|
std::shared_ptr<websocket_connection> ws_connection)
|
||||||
|
{
|
||||||
|
_impl.reset(new Impl());
|
||||||
|
_impl->parent = parent;
|
||||||
|
_impl->connection = connection;
|
||||||
|
_impl->id = EQ::Util::UUID::Generate().ToString();
|
||||||
|
_impl->authorized = false;
|
||||||
|
_impl->account_id = 0;
|
||||||
|
_impl->status = 0;
|
||||||
|
_impl->ws_connection = ws_connection;
|
||||||
|
_impl->ws_connection->set_message_handler(std::bind(&WebsocketServerConnection::OnMessage, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
_impl->ws_connection->start();
|
||||||
|
|
||||||
|
connection->OnDisconnect([this](EQ::Net::TCPConnection *connection) {
|
||||||
|
_impl->parent->ReleaseConnection(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
connection->OnRead([this](EQ::Net::TCPConnection *c, const unsigned char *buffer, size_t buffer_size) {
|
||||||
|
_impl->ws_connection->read_all((const char*)buffer, buffer_size);
|
||||||
|
});
|
||||||
|
|
||||||
|
connection->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Net::WebsocketServerConnection::~WebsocketServerConnection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EQ::Net::WebsocketServerConnection::GetID() const
|
||||||
|
{
|
||||||
|
return _impl->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EQ::Net::WebsocketServerConnection::IsAuthorized() const
|
||||||
|
{
|
||||||
|
return _impl->authorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EQ::Net::WebsocketServerConnection::GetAccountName() const
|
||||||
|
{
|
||||||
|
return _impl->account_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 EQ::Net::WebsocketServerConnection::GetAccountID() const
|
||||||
|
{
|
||||||
|
return _impl->account_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EQ::Net::WebsocketServerConnection::GetStatus() const
|
||||||
|
{
|
||||||
|
return _impl->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EQ::Net::WebsocketServerConnection::RemoteIP() const
|
||||||
|
{
|
||||||
|
return _impl->connection->RemoteIP();
|
||||||
|
}
|
||||||
|
|
||||||
|
int EQ::Net::WebsocketServerConnection::RemotePort() const
|
||||||
|
{
|
||||||
|
return _impl->connection->RemotePort();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<EQ::Net::websocket_connection> EQ::Net::WebsocketServerConnection::GetWebsocketConnection()
|
||||||
|
{
|
||||||
|
return _impl->ws_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<EQ::Net::TCPConnection> EQ::Net::WebsocketServerConnection::GetTCPConnection()
|
||||||
|
{
|
||||||
|
return _impl->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServerConnection::OnMessage(websocketpp::connection_hdl hdl, websocket_message_ptr msg)
|
||||||
|
{
|
||||||
|
BenchTimer timer;
|
||||||
|
timer.reset();
|
||||||
|
|
||||||
|
if (msg->get_opcode() == websocketpp::frame::opcode::text) {
|
||||||
|
try {
|
||||||
|
auto &payload = msg->get_payload();
|
||||||
|
|
||||||
|
std::stringstream ss(payload);
|
||||||
|
Json::Value root;
|
||||||
|
|
||||||
|
ss >> root;
|
||||||
|
|
||||||
|
auto method = root["method"].asString();
|
||||||
|
auto params = root["params"];
|
||||||
|
std::string id = "";
|
||||||
|
|
||||||
|
auto idNode = root["id"];
|
||||||
|
if (!idNode.isNull() && idNode.isString()) {
|
||||||
|
id = idNode.asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value response;
|
||||||
|
response["type"] = "method";
|
||||||
|
response["data"] = _impl->parent->HandleRequest(this, method, params);
|
||||||
|
response["method"] = method;
|
||||||
|
if(id != "") {
|
||||||
|
response["id"] = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendResponse(response, timer.elapsed());
|
||||||
|
}
|
||||||
|
catch (std::exception &ex) {
|
||||||
|
Json::Value error;
|
||||||
|
error["type"] = "method";
|
||||||
|
error["error"] = fmt::format("{0}", ex.what());
|
||||||
|
SendResponse(error, timer.elapsed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServerConnection::SendResponse(const Json::Value &response, double time_elapsed)
|
||||||
|
{
|
||||||
|
Json::Value root = response;
|
||||||
|
root["execution_time"] = std::to_string(time_elapsed);
|
||||||
|
|
||||||
|
std::stringstream payload;
|
||||||
|
payload << root;
|
||||||
|
|
||||||
|
_impl->ws_connection->send(payload.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::WebsocketServerConnection::SetAuthorized(bool v, const std::string account_name, uint32 account_id, int status)
|
||||||
|
{
|
||||||
|
_impl->authorized = v;
|
||||||
|
_impl->account_name = account_name;
|
||||||
|
_impl->account_id = account_id;
|
||||||
|
_impl->status = status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tcp_server.h"
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../json/json-forwards.h"
|
||||||
|
#include <websocketpp/config/core.hpp>
|
||||||
|
#include <websocketpp/server.hpp>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Net
|
||||||
|
{
|
||||||
|
typedef websocketpp::server<websocketpp::config::core> websocket_server;
|
||||||
|
typedef websocketpp::connection<websocketpp::config::core> websocket_connection;
|
||||||
|
typedef websocket_server::message_ptr websocket_message_ptr;
|
||||||
|
|
||||||
|
class WebsocketServer;
|
||||||
|
class WebsocketServerConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebsocketServerConnection(WebsocketServer *parent,
|
||||||
|
std::shared_ptr<TCPConnection> connection,
|
||||||
|
std::shared_ptr<websocket_connection> ws_connection);
|
||||||
|
~WebsocketServerConnection();
|
||||||
|
|
||||||
|
std::string GetID() const;
|
||||||
|
bool IsAuthorized() const;
|
||||||
|
std::string GetAccountName() const;
|
||||||
|
uint32 GetAccountID() const;
|
||||||
|
int GetStatus() const;
|
||||||
|
std::string RemoteIP() const;
|
||||||
|
int RemotePort() const;
|
||||||
|
private:
|
||||||
|
std::shared_ptr<websocket_connection> GetWebsocketConnection();
|
||||||
|
std::shared_ptr<TCPConnection> GetTCPConnection();
|
||||||
|
void OnMessage(websocketpp::connection_hdl hdl, websocket_message_ptr msg);
|
||||||
|
void SendResponse(const Json::Value &response, double time_elapsed);
|
||||||
|
void SetAuthorized(bool v, const std::string account_name, uint32 account_id, int status);
|
||||||
|
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> _impl;
|
||||||
|
|
||||||
|
friend class WebsocketServer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "eqemu_logsys.h"
|
||||||
#include "emu_opcodes.h"
|
#include "emu_opcodes.h"
|
||||||
#include "opcodemgr.h"
|
#include "opcodemgr.h"
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ OpcodeManager::OpcodeManager() {
|
|||||||
bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors) {
|
bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors) {
|
||||||
FILE *opf = fopen(filename, "r");
|
FILE *opf = fopen(filename, "r");
|
||||||
if(opf == nullptr) {
|
if(opf == nullptr) {
|
||||||
fprintf(stderr, "Unable to open opcodes file '%s'. Thats bad.\n", filename);
|
LogError("Unable to open opcodes file [{}]", filename);
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-46
@@ -85,7 +85,7 @@ namespace RoF
|
|||||||
//TODO: figure out how to support shared memory with multiple patches...
|
//TODO: figure out how to support shared memory with multiple patches...
|
||||||
opcodes = new RegularOpcodeManager();
|
opcodes = new RegularOpcodeManager();
|
||||||
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error loading opcodes file [{}]. Not registering patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ namespace RoF
|
|||||||
signature.first_length = sizeof(structs::ClientZoneEntry_Struct);
|
signature.first_length = sizeof(structs::ClientZoneEntry_Struct);
|
||||||
signature.first_eq_opcode = opcodes->EmuToEQ(OP_ZoneEntry);
|
signature.first_eq_opcode = opcodes->EmuToEQ(OP_ZoneEntry);
|
||||||
into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy);
|
into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy);
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Registered patch %s", name);
|
LogNetcode("[StreamIdentify] Registered patch [{}]", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reload()
|
void Reload()
|
||||||
@@ -125,10 +125,10 @@ namespace RoF
|
|||||||
opfile += name;
|
opfile += name;
|
||||||
opfile += ".conf";
|
opfile += ".conf";
|
||||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error reloading opcodes file %s for patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Reloaded opcodes for patch %s", name);
|
LogNetcode("[OPCODES] Reloaded opcodes for patch [{}]", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +350,7 @@ namespace RoF
|
|||||||
|
|
||||||
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -589,7 +589,7 @@ namespace RoF
|
|||||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory);
|
||||||
if (ob.tellp() == last_pos)
|
if (ob.tellp() == last_pos)
|
||||||
Log(Logs::General, Logs::Netcode, "RoF::ENCODE(OP_CharInventory) Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
LogNetcode("RoF::ENCODE(OP_CharInventory) Serialization failed on item slot [{}] during OP_CharInventory. Item skipped", eq->slot_id);
|
||||||
|
|
||||||
last_pos = ob.tellp();
|
last_pos = ob.tellp();
|
||||||
}
|
}
|
||||||
@@ -1521,7 +1521,7 @@ namespace RoF
|
|||||||
|
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType);
|
||||||
if (ob.tellp() == last_pos) {
|
if (ob.tellp() == last_pos) {
|
||||||
Log(Logs::General, Logs::Netcode, "RoF::ENCODE(OP_ItemPacket) Serialization failed on item slot %d.", int_struct->slot_id);
|
LogNetcode("RoF::ENCODE(OP_ItemPacket) Serialization failed on item slot [{}]", int_struct->slot_id);
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2602,7 +2602,7 @@ namespace RoF
|
|||||||
|
|
||||||
outapp->WriteUInt8(0); // Unknown
|
outapp->WriteUInt8(0); // Unknown
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Player Profile Packet is %i bytes", outapp->GetWritePosition());
|
LogNetcode("[STRUCTS] Player Profile Packet is [{}] bytes", outapp->GetWritePosition());
|
||||||
|
|
||||||
auto NewBuffer = new unsigned char[outapp->GetWritePosition()];
|
auto NewBuffer = new unsigned char[outapp->GetWritePosition()];
|
||||||
memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition());
|
memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition());
|
||||||
@@ -3199,47 +3199,35 @@ namespace RoF
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
|
|
||||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToRoFSayLink(new_message, old_message);
|
ServerToRoFSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
@@ -3465,7 +3453,7 @@ namespace RoF
|
|||||||
|
|
||||||
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3816,7 +3804,7 @@ namespace RoF
|
|||||||
//determine and verify length
|
//determine and verify length
|
||||||
int entrycount = in->size / sizeof(Spawn_Struct);
|
int entrycount = in->size / sizeof(Spawn_Struct);
|
||||||
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4064,7 +4052,7 @@ namespace RoF
|
|||||||
Buffer += 29;
|
Buffer += 29;
|
||||||
if (Buffer != (BufferStart + PacketSize))
|
if (Buffer != (BufferStart + PacketSize))
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[ERROR] SPAWN ENCODE LOGIC PROBLEM: Buffer pointer is now %i from end", Buffer - (BufferStart + PacketSize));
|
LogNetcode("[ERROR] SPAWN ENCODE LOGIC PROBLEM: Buffer pointer is now [{}] from end", Buffer - (BufferStart + PacketSize));
|
||||||
}
|
}
|
||||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending zone spawn for %s packet is %i bytes", emu->name, outapp->size);
|
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending zone spawn for %s packet is %i bytes", emu->name, outapp->size);
|
||||||
//Log.Hex(Logs::Netcode, outapp->pBuffer, outapp->size);
|
//Log.Hex(Logs::Netcode, outapp->pBuffer, outapp->size);
|
||||||
@@ -4633,7 +4621,7 @@ namespace RoF
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
Log(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action");
|
LogNetcode("Unhandled OP_GuildBank action");
|
||||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
|
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5690,7 +5678,7 @@ namespace RoF
|
|||||||
RoFSlot = server_corpse_slot;
|
RoFSlot = server_corpse_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Corpse Slot %i to RoF Corpse Main Slot %i", server_corpse_slot, RoFSlot);
|
LogNetcode("Convert Server Corpse Slot [{}] to RoF Corpse Main Slot [{}]", server_corpse_slot, RoFSlot);
|
||||||
|
|
||||||
return RoFSlot;
|
return RoFSlot;
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-58
@@ -85,7 +85,7 @@ namespace RoF2
|
|||||||
//TODO: figure out how to support shared memory with multiple patches...
|
//TODO: figure out how to support shared memory with multiple patches...
|
||||||
opcodes = new RegularOpcodeManager();
|
opcodes = new RegularOpcodeManager();
|
||||||
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error loading opcodes file [{}]. Not registering patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ namespace RoF2
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Registered patch %s", name);
|
LogNetcode("[StreamIdentify] Registered patch [{}]", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reload()
|
void Reload()
|
||||||
@@ -128,10 +128,10 @@ namespace RoF2
|
|||||||
opfile += name;
|
opfile += name;
|
||||||
opfile += ".conf";
|
opfile += ".conf";
|
||||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error reloading opcodes file %s for patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Reloaded opcodes for patch %s", name);
|
LogNetcode("[OPCODES] Reloaded opcodes for patch [{}]", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ namespace RoF2
|
|||||||
|
|
||||||
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -657,7 +657,7 @@ namespace RoF2
|
|||||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory);
|
||||||
if (ob.tellp() == last_pos)
|
if (ob.tellp() == last_pos)
|
||||||
Log(Logs::General, Logs::Netcode, "RoF2::ENCODE(OP_CharInventory) Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
LogNetcode("RoF2::ENCODE(OP_CharInventory) Serialization failed on item slot [{}] during OP_CharInventory. Item skipped", eq->slot_id);
|
||||||
|
|
||||||
last_pos = ob.tellp();
|
last_pos = ob.tellp();
|
||||||
}
|
}
|
||||||
@@ -1589,7 +1589,7 @@ namespace RoF2
|
|||||||
|
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType);
|
||||||
if (ob.tellp() == last_pos) {
|
if (ob.tellp() == last_pos) {
|
||||||
Log(Logs::General, Logs::Netcode, "RoF2::ENCODE(OP_ItemPacket) Serialization failed on item slot %d.", int_struct->slot_id);
|
LogNetcode("RoF2::ENCODE(OP_ItemPacket) Serialization failed on item slot [{}]", int_struct->slot_id);
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2688,7 +2688,7 @@ namespace RoF2
|
|||||||
// Think we need 1 byte of padding at the end
|
// Think we need 1 byte of padding at the end
|
||||||
outapp->WriteUInt8(0); // Unknown
|
outapp->WriteUInt8(0); // Unknown
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Player Profile Packet is %i bytes", outapp->GetWritePosition());
|
LogNetcode("[STRUCTS] Player Profile Packet is [{}] bytes", outapp->GetWritePosition());
|
||||||
|
|
||||||
auto NewBuffer = new unsigned char[outapp->GetWritePosition()];
|
auto NewBuffer = new unsigned char[outapp->GetWritePosition()];
|
||||||
memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition());
|
memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition());
|
||||||
@@ -3266,47 +3266,35 @@ namespace RoF2
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
|
|
||||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToRoF2SayLink(new_message, old_message);
|
ServerToRoF2SayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
@@ -3532,7 +3520,7 @@ namespace RoF2
|
|||||||
|
|
||||||
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3642,7 +3630,7 @@ namespace RoF2
|
|||||||
|
|
||||||
OUT(TraderID);
|
OUT(TraderID);
|
||||||
snprintf(eq->SerialNumber, sizeof(eq->SerialNumber), "%016d", emu->ItemID);
|
snprintf(eq->SerialNumber, sizeof(eq->SerialNumber), "%016d", emu->ItemID);
|
||||||
Log(Logs::Detail, Logs::Trading, "ENCODE(OP_TraderDelItem): TraderID %d, SerialNumber: %d", emu->TraderID, emu->ItemID);
|
LogTrading("ENCODE(OP_TraderDelItem): TraderID [{}], SerialNumber: [{}]", emu->TraderID, emu->ItemID);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@@ -3673,7 +3661,7 @@ namespace RoF2
|
|||||||
eq->Traders2 = emu->Traders;
|
eq->Traders2 = emu->Traders;
|
||||||
eq->Items2 = emu->Items;
|
eq->Items2 = emu->Items;
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Trading, "ENCODE(OP_TraderShop): BazaarWelcome_Struct Code %d, Traders %d, Items %d",
|
LogTrading("ENCODE(OP_TraderShop): BazaarWelcome_Struct Code [{}], Traders [{}], Items [{}]",
|
||||||
eq->Code, eq->Traders, eq->Items);
|
eq->Code, eq->Traders, eq->Items);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
@@ -3696,14 +3684,14 @@ namespace RoF2
|
|||||||
OUT(Quantity);
|
OUT(Quantity);
|
||||||
snprintf(eq->SerialNumber, sizeof(eq->SerialNumber), "%016d", emu->ItemID);
|
snprintf(eq->SerialNumber, sizeof(eq->SerialNumber), "%016d", emu->ItemID);
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Trading, "ENCODE(OP_TraderShop): Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s",
|
LogTrading("ENCODE(OP_TraderShop): Buy Action [{}], Price [{}], Trader [{}], ItemID [{}], Quantity [{}], ItemName, [{}]",
|
||||||
eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, emu->ItemName);
|
eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, emu->ItemName);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Trading, "ENCODE(OP_TraderShop): Encode Size Unknown (%d)", psize);
|
LogTrading("ENCODE(OP_TraderShop): Encode Size Unknown ([{}])", psize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3958,7 +3946,7 @@ namespace RoF2
|
|||||||
//determine and verify length
|
//determine and verify length
|
||||||
int entrycount = in->size / sizeof(Spawn_Struct);
|
int entrycount = in->size / sizeof(Spawn_Struct);
|
||||||
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4290,7 +4278,7 @@ namespace RoF2
|
|||||||
Buffer += 29;
|
Buffer += 29;
|
||||||
if (Buffer != (BufferStart + PacketSize))
|
if (Buffer != (BufferStart + PacketSize))
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[ERROR] SPAWN ENCODE LOGIC PROBLEM: Buffer pointer is now %i from end", Buffer - (BufferStart + PacketSize));
|
LogNetcode("[ERROR] SPAWN ENCODE LOGIC PROBLEM: Buffer pointer is now [{}] from end", Buffer - (BufferStart + PacketSize));
|
||||||
}
|
}
|
||||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending zone spawn for %s packet is %i bytes", emu->name, outapp->size);
|
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending zone spawn for %s packet is %i bytes", emu->name, outapp->size);
|
||||||
//Log.Hex(Logs::Netcode, outapp->pBuffer, outapp->size);
|
//Log.Hex(Logs::Netcode, outapp->pBuffer, outapp->size);
|
||||||
@@ -4871,7 +4859,7 @@ namespace RoF2
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
Log(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action");
|
LogNetcode("Unhandled OP_GuildBank action");
|
||||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
|
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5024,7 +5012,7 @@ namespace RoF2
|
|||||||
emu->to_slot = RoF2ToServerSlot(eq->to_slot);
|
emu->to_slot = RoF2ToServerSlot(eq->to_slot);
|
||||||
IN(number_in_stack);
|
IN(number_in_stack);
|
||||||
|
|
||||||
//Log(Logs::General, Logs::Netcode, "[RoF2] MoveItem Slot from %u to %u, Number %u", emu->from_slot, emu->to_slot, emu->number_in_stack);
|
//LogNetcode("[RoF2] MoveItem Slot from [{}] to [{}], Number [{}]", emu->from_slot, emu->to_slot, emu->number_in_stack);
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
@@ -5257,7 +5245,7 @@ namespace RoF2
|
|||||||
IN(Code);
|
IN(Code);
|
||||||
IN(TraderID);
|
IN(TraderID);
|
||||||
IN(Approval);
|
IN(Approval);
|
||||||
Log(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderClick_Struct Code %d, TraderID %d, Approval %d",
|
LogTrading("DECODE(OP_TraderShop): TraderClick_Struct Code [{}], TraderID [{}], Approval [{}]",
|
||||||
eq->Code, eq->TraderID, eq->Approval);
|
eq->Code, eq->TraderID, eq->Approval);
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
@@ -5271,7 +5259,7 @@ namespace RoF2
|
|||||||
emu->Beginning.Action = eq->Code;
|
emu->Beginning.Action = eq->Code;
|
||||||
IN(Traders);
|
IN(Traders);
|
||||||
IN(Items);
|
IN(Items);
|
||||||
Log(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): BazaarWelcome_Struct Code %d, Traders %d, Items %d",
|
LogTrading("DECODE(OP_TraderShop): BazaarWelcome_Struct Code [{}], Traders [{}], Items [{}]",
|
||||||
eq->Code, eq->Traders, eq->Items);
|
eq->Code, eq->Traders, eq->Items);
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
@@ -5288,20 +5276,20 @@ namespace RoF2
|
|||||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||||
IN(ItemID);
|
IN(ItemID);
|
||||||
IN(Quantity);
|
IN(Quantity);
|
||||||
Log(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct (Unknowns) Unknown004 %d, Unknown008 %d, Unknown012 %d, Unknown076 %d, Unknown276 %d",
|
LogTrading("DECODE(OP_TraderShop): TraderBuy_Struct (Unknowns) Unknown004 [{}], Unknown008 [{}], Unknown012 [{}], Unknown076 [{}], Unknown276 [{}]",
|
||||||
eq->Unknown004, eq->Unknown008, eq->Unknown012, eq->Unknown076, eq->Unknown276);
|
eq->Unknown004, eq->Unknown008, eq->Unknown012, eq->Unknown076, eq->Unknown276);
|
||||||
Log(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s",
|
LogTrading("DECODE(OP_TraderShop): TraderBuy_Struct Buy Action [{}], Price [{}], Trader [{}], ItemID [{}], Quantity [{}], ItemName, [{}]",
|
||||||
eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, eq->ItemName);
|
eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, eq->ItemName);
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
else if (psize == 4)
|
else if (psize == 4)
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): Forwarding packet as-is with size 4");
|
LogTrading("DECODE(OP_TraderShop): Forwarding packet as-is with size 4");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): Decode Size Unknown (%d)", psize);
|
LogTrading("DECODE(OP_TraderShop): Decode Size Unknown ([{}])", psize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5978,7 +5966,7 @@ namespace RoF2
|
|||||||
RoF2Slot = server_corpse_slot;
|
RoF2Slot = server_corpse_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Corpse Slot %i to RoF2 Corpse Main Slot %i", server_corpse_slot, RoF2Slot);
|
LogNetcode("Convert Server Corpse Slot [{}] to RoF2 Corpse Main Slot [{}]", server_corpse_slot, RoF2Slot);
|
||||||
|
|
||||||
return RoF2Slot;
|
return RoF2Slot;
|
||||||
}
|
}
|
||||||
@@ -6161,7 +6149,7 @@ namespace RoF2
|
|||||||
ServerSlot = rof2_corpse_slot;
|
ServerSlot = rof2_corpse_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert RoF2 Corpse Main Slot %i to Server Corpse Slot %i", rof2_corpse_slot, ServerSlot);
|
LogNetcode("Convert RoF2 Corpse Main Slot [{}] to Server Corpse Slot [{}]", rof2_corpse_slot, ServerSlot);
|
||||||
|
|
||||||
return ServerSlot;
|
return ServerSlot;
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-46
@@ -79,7 +79,7 @@ namespace SoD
|
|||||||
//TODO: figure out how to support shared memory with multiple patches...
|
//TODO: figure out how to support shared memory with multiple patches...
|
||||||
opcodes = new RegularOpcodeManager();
|
opcodes = new RegularOpcodeManager();
|
||||||
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error loading opcodes file [{}]. Not registering patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ namespace SoD
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Registered patch %s", name);
|
LogNetcode("[StreamIdentify] Registered patch [{}]", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reload()
|
void Reload()
|
||||||
@@ -122,10 +122,10 @@ namespace SoD
|
|||||||
opfile += name;
|
opfile += name;
|
||||||
opfile += ".conf";
|
opfile += ".conf";
|
||||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error reloading opcodes file %s for patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Reloaded opcodes for patch %s", name);
|
LogNetcode("[OPCODES] Reloaded opcodes for patch [{}]", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ namespace SoD
|
|||||||
|
|
||||||
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -400,7 +400,7 @@ namespace SoD
|
|||||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0);
|
||||||
if (ob.tellp() == last_pos)
|
if (ob.tellp() == last_pos)
|
||||||
Log(Logs::General, Logs::Netcode, "SoD::ENCODE(OP_CharInventory) Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
LogNetcode("SoD::ENCODE(OP_CharInventory) Serialization failed on item slot [{}] during OP_CharInventory. Item skipped", eq->slot_id);
|
||||||
|
|
||||||
last_pos = ob.tellp();
|
last_pos = ob.tellp();
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1069,7 @@ namespace SoD
|
|||||||
|
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0);
|
||||||
if (ob.tellp() == last_pos) {
|
if (ob.tellp() == last_pos) {
|
||||||
Log(Logs::General, Logs::Netcode, "SoD::ENCODE(OP_ItemPacket) Serialization failed on item slot %d.", int_struct->slot_id);
|
LogNetcode("SoD::ENCODE(OP_ItemPacket) Serialization failed on item slot [{}]", int_struct->slot_id);
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2069,47 +2069,35 @@ namespace SoD
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
|
|
||||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToSoDSayLink(new_message, old_message);
|
ServerToSoDSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
@@ -2210,7 +2198,7 @@ namespace SoD
|
|||||||
|
|
||||||
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2447,7 +2435,7 @@ namespace SoD
|
|||||||
//determine and verify length
|
//determine and verify length
|
||||||
int entrycount = in->size / sizeof(Spawn_Struct);
|
int entrycount = in->size / sizeof(Spawn_Struct);
|
||||||
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3860,7 +3848,7 @@ namespace SoD
|
|||||||
SoDSlot = serverSlot;
|
SoDSlot = serverSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Slot %i to SoD Slot %i", serverSlot, SoDSlot);
|
LogNetcode("Convert Server Slot [{}] to SoD Slot [{}]", serverSlot, SoDSlot);
|
||||||
|
|
||||||
return SoDSlot;
|
return SoDSlot;
|
||||||
}
|
}
|
||||||
@@ -3877,7 +3865,7 @@ namespace SoD
|
|||||||
SoDSlot = server_corpse_slot - 2;
|
SoDSlot = server_corpse_slot - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Corpse Slot %i to SoD Corpse Slot %i", server_corpse_slot, SoDSlot);
|
LogNetcode("Convert Server Corpse Slot [{}] to SoD Corpse Slot [{}]", server_corpse_slot, SoDSlot);
|
||||||
|
|
||||||
return SoDSlot;
|
return SoDSlot;
|
||||||
}
|
}
|
||||||
@@ -3942,7 +3930,7 @@ namespace SoD
|
|||||||
server_slot = sod_slot;
|
server_slot = sod_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert SoD Slot %i to Server Slot %i", sod_slot, server_slot);
|
LogNetcode("Convert SoD Slot [{}] to Server Slot [{}]", sod_slot, server_slot);
|
||||||
|
|
||||||
return server_slot;
|
return server_slot;
|
||||||
}
|
}
|
||||||
@@ -3959,7 +3947,7 @@ namespace SoD
|
|||||||
server_slot = sod_corpse_slot + 2;
|
server_slot = sod_corpse_slot + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert SoD Corpse Slot %i to Server Corpse Slot %i", sod_corpse_slot, server_slot);
|
LogNetcode("Convert SoD Corpse Slot [{}] to Server Corpse Slot [{}]", sod_corpse_slot, server_slot);
|
||||||
|
|
||||||
return server_slot;
|
return server_slot;
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-43
@@ -79,7 +79,7 @@ namespace SoF
|
|||||||
//TODO: figure out how to support shared memory with multiple patches...
|
//TODO: figure out how to support shared memory with multiple patches...
|
||||||
opcodes = new RegularOpcodeManager();
|
opcodes = new RegularOpcodeManager();
|
||||||
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error loading opcodes file [{}]. Not registering patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ namespace SoF
|
|||||||
signature.first_eq_opcode = opcodes->EmuToEQ(OP_ZoneEntry);
|
signature.first_eq_opcode = opcodes->EmuToEQ(OP_ZoneEntry);
|
||||||
into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy);
|
into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy);
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Registered patch %s", name);
|
LogNetcode("[StreamIdentify] Registered patch [{}]", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reload()
|
void Reload()
|
||||||
@@ -120,10 +120,10 @@ namespace SoF
|
|||||||
opfile += name;
|
opfile += name;
|
||||||
opfile += ".conf";
|
opfile += ".conf";
|
||||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error reloading opcodes file %s for patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Reloaded opcodes for patch %s", name);
|
LogNetcode("[OPCODES] Reloaded opcodes for patch [{}]", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ namespace SoF
|
|||||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0);
|
||||||
if (ob.tellp() == last_pos)
|
if (ob.tellp() == last_pos)
|
||||||
Log(Logs::General, Logs::Netcode, "SoF::ENCODE(OP_CharInventory) Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
LogNetcode("SoF::ENCODE(OP_CharInventory) Serialization failed on item slot [{}] during OP_CharInventory. Item skipped", eq->slot_id);
|
||||||
|
|
||||||
last_pos = ob.tellp();
|
last_pos = ob.tellp();
|
||||||
}
|
}
|
||||||
@@ -864,7 +864,7 @@ namespace SoF
|
|||||||
|
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0);
|
||||||
if (ob.tellp() == last_pos) {
|
if (ob.tellp() == last_pos) {
|
||||||
Log(Logs::General, Logs::Netcode, "SoF::ENCODE(OP_ItemPacket) Serialization failed on item slot %d.", int_struct->slot_id);
|
LogNetcode("SoF::ENCODE(OP_ItemPacket) Serialization failed on item slot [{}]", int_struct->slot_id);
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1116,7 +1116,10 @@ namespace SoF
|
|||||||
}
|
}
|
||||||
OUT(deity);
|
OUT(deity);
|
||||||
OUT(intoxication);
|
OUT(intoxication);
|
||||||
|
|
||||||
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
||||||
|
eq->spellSlotRefresh[9] = 0; // 10th slot is not valid in this release
|
||||||
|
|
||||||
OUT(abilitySlotRefresh);
|
OUT(abilitySlotRefresh);
|
||||||
OUT(points); // Relocation Test
|
OUT(points); // Relocation Test
|
||||||
// OUT(unknown0166[4]);
|
// OUT(unknown0166[4]);
|
||||||
@@ -1177,7 +1180,10 @@ namespace SoF
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OUT(unknown4184[128]);
|
// OUT(unknown4184[128]);
|
||||||
|
|
||||||
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
||||||
|
eq->mem_spells[9] = 0xFFFFFFFFU; // 10th slot is not valid in this release
|
||||||
|
|
||||||
// OUT(unknown04396[32]);
|
// OUT(unknown04396[32]);
|
||||||
OUT(platinum);
|
OUT(platinum);
|
||||||
OUT(gold);
|
OUT(gold);
|
||||||
@@ -1720,47 +1726,35 @@ namespace SoF
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
|
in->ReadString(name);
|
||||||
|
|
||||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToSoFSayLink(new_message, old_message);
|
ServerToSoFSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
@@ -1833,7 +1827,7 @@ namespace SoF
|
|||||||
|
|
||||||
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1995,7 +1989,7 @@ namespace SoF
|
|||||||
//determine and verify length
|
//determine and verify length
|
||||||
int entrycount = in->size / sizeof(Spawn_Struct);
|
int entrycount = in->size / sizeof(Spawn_Struct);
|
||||||
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3250,7 +3244,7 @@ namespace SoF
|
|||||||
sof_slot = server_slot;
|
sof_slot = server_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Slot %i to SoF Slot %i", server_slot, sof_slot);
|
LogNetcode("Convert Server Slot [{}] to SoF Slot [{}]", server_slot, sof_slot);
|
||||||
|
|
||||||
return sof_slot;
|
return sof_slot;
|
||||||
}
|
}
|
||||||
@@ -3336,7 +3330,7 @@ namespace SoF
|
|||||||
server_slot = sof_slot;
|
server_slot = sof_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert SoF Slot %i to Server Slot %i", sof_slot, server_slot);
|
LogNetcode("Convert SoF Slot [{}] to Server Slot [{}]", sof_slot, server_slot);
|
||||||
|
|
||||||
return server_slot;
|
return server_slot;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,7 +328,11 @@ namespace SoF
|
|||||||
|
|
||||||
const int SPELL_ID_MAX = 15999;
|
const int SPELL_ID_MAX = 15999;
|
||||||
const int SPELLBOOK_SIZE = 480;
|
const int SPELLBOOK_SIZE = 480;
|
||||||
|
// Be careful not to confuse these two..SoF disc release has a special requirement...
|
||||||
|
// - The number of available spell gems HAS NOT increased from 9 at this point
|
||||||
|
// - The profile allocation HAS increased to 10 at this point
|
||||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||||
|
const int SPELL_GEM_PROFILE_SIZE = 10; // special case declaration
|
||||||
|
|
||||||
const int LONG_BUFFS = 25;
|
const int LONG_BUFFS = 25;
|
||||||
const int SHORT_BUFFS = 15;
|
const int SHORT_BUFFS = 15;
|
||||||
|
|||||||
@@ -885,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets
|
|||||||
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
||||||
/*00160*/ uint32 deity; // deity
|
/*00160*/ uint32 deity; // deity
|
||||||
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
||||||
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each
|
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_PROFILE_SIZE]; // Refresh time (millis) - 4 Octets Each
|
||||||
/*00208*/ uint32 abilitySlotRefresh;
|
/*00208*/ uint32 abilitySlotRefresh;
|
||||||
/*00212*/ uint8 haircolor; // Player hair color
|
/*00212*/ uint8 haircolor; // Player hair color
|
||||||
/*00213*/ uint8 beardcolor; // Player beard color
|
/*00213*/ uint8 beardcolor; // Player beard color
|
||||||
@@ -912,7 +912,7 @@ struct PlayerProfile_Struct //23576 Octets
|
|||||||
/*04173*/ uint8 unknown02264[147]; // was [139]
|
/*04173*/ uint8 unknown02264[147]; // was [139]
|
||||||
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
|
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
|
||||||
/*06232*/ uint8 unknown4184[128]; // was [136]
|
/*06232*/ uint8 unknown4184[128]; // was [136]
|
||||||
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized
|
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_PROFILE_SIZE]; // List of spells memorized
|
||||||
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
||||||
/*06464*/ uint32 platinum; // Platinum Pieces on player
|
/*06464*/ uint32 platinum; // Platinum Pieces on player
|
||||||
/*06468*/ uint32 gold; // Gold Pieces on player
|
/*06468*/ uint32 gold; // Gold Pieces on player
|
||||||
@@ -3768,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct LoadSpellSet_Struct {
|
struct LoadSpellSet_Struct {
|
||||||
uint32 spell[spells::SPELL_GEM_COUNT];
|
uint32 spell[spells::SPELL_GEM_PROFILE_SIZE];
|
||||||
uint32 unknown;
|
uint32 unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -87,14 +87,14 @@
|
|||||||
//check length of packet before decoding. Call before setup.
|
//check length of packet before decoding. Call before setup.
|
||||||
#define ENCODE_LENGTH_EXACT(struct_) \
|
#define ENCODE_LENGTH_EXACT(struct_) \
|
||||||
if((*p)->size != sizeof(struct_)) { \
|
if((*p)->size != sizeof(struct_)) { \
|
||||||
Log(Logs::Detail, Logs::Netcode, "Wrong size on outbound %s (" #struct_ "): Got %d, expected %d", opcodes->EmuToName((*p)->GetOpcode()), (*p)->size, sizeof(struct_)); \
|
LogNetcode("Wrong size on outbound [{}] (" #struct_ "): Got [{}], expected [{}]", opcodes->EmuToName((*p)->GetOpcode()), (*p)->size, sizeof(struct_)); \
|
||||||
delete *p; \
|
delete *p; \
|
||||||
*p = nullptr; \
|
*p = nullptr; \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
#define ENCODE_LENGTH_ATLEAST(struct_) \
|
#define ENCODE_LENGTH_ATLEAST(struct_) \
|
||||||
if((*p)->size < sizeof(struct_)) { \
|
if((*p)->size < sizeof(struct_)) { \
|
||||||
Log(Logs::Detail, Logs::Netcode, "Wrong size on outbound %s (" #struct_ "): Got %d, expected at least %d", opcodes->EmuToName((*p)->GetOpcode()), (*p)->size, sizeof(struct_)); \
|
LogNetcode("Wrong size on outbound [{}] (" #struct_ "): Got [{}], expected at least [{}]", opcodes->EmuToName((*p)->GetOpcode()), (*p)->size, sizeof(struct_)); \
|
||||||
delete *p; \
|
delete *p; \
|
||||||
*p = nullptr; \
|
*p = nullptr; \
|
||||||
return; \
|
return; \
|
||||||
@@ -153,13 +153,13 @@
|
|||||||
//check length of packet before decoding. Call before setup.
|
//check length of packet before decoding. Call before setup.
|
||||||
#define DECODE_LENGTH_EXACT(struct_) \
|
#define DECODE_LENGTH_EXACT(struct_) \
|
||||||
if(__packet->size != sizeof(struct_)) { \
|
if(__packet->size != sizeof(struct_)) { \
|
||||||
Log(Logs::Detail, Logs::Netcode, "Wrong size on incoming %s (" #struct_ "): Got %d, expected %d", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
LogNetcode("Wrong size on incoming [{}] (" #struct_ "): Got [{}], expected [{}]", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
||||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
#define DECODE_LENGTH_ATLEAST(struct_) \
|
#define DECODE_LENGTH_ATLEAST(struct_) \
|
||||||
if(__packet->size < sizeof(struct_)) { \
|
if(__packet->size < sizeof(struct_)) { \
|
||||||
Log(Logs::Detail, Logs::Netcode, "Wrong size on incoming %s (" #struct_ "): Got %d, expected at least %d", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
LogNetcode("Wrong size on incoming [{}] (" #struct_ "): Got [{}], expected at least [{}]", opcodes->EmuToName(__packet->GetOpcode()), __packet->size, sizeof(struct_)); \
|
||||||
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */ \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-44
@@ -78,7 +78,7 @@ namespace Titanium
|
|||||||
//TODO: figure out how to support shared memory with multiple patches...
|
//TODO: figure out how to support shared memory with multiple patches...
|
||||||
opcodes = new RegularOpcodeManager();
|
opcodes = new RegularOpcodeManager();
|
||||||
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error loading opcodes file [{}]. Not registering patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ namespace Titanium
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Registered patch %s", name);
|
LogNetcode("[StreamIdentify] Registered patch [{}]", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reload()
|
void Reload()
|
||||||
@@ -121,10 +121,10 @@ namespace Titanium
|
|||||||
opfile += name;
|
opfile += name;
|
||||||
opfile += ".conf";
|
opfile += ".conf";
|
||||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error reloading opcodes file %s for patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Reloaded opcodes for patch %s", name);
|
LogNetcode("[OPCODES] Reloaded opcodes for patch [{}]", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ namespace Titanium
|
|||||||
for (int r = 0; r < itemcount; r++, eq++) {
|
for (int r = 0; r < itemcount; r++, eq++) {
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, ServerToTitaniumSlot(eq->slot_id), 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, ServerToTitaniumSlot(eq->slot_id), 0);
|
||||||
if (ob.tellp() == last_pos)
|
if (ob.tellp() == last_pos)
|
||||||
Log(Logs::General, Logs::Netcode, "Titanium::ENCODE(OP_CharInventory) Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
LogNetcode("Titanium::ENCODE(OP_CharInventory) Serialization failed on item slot [{}] during OP_CharInventory. Item skipped", eq->slot_id);
|
||||||
|
|
||||||
last_pos = ob.tellp();
|
last_pos = ob.tellp();
|
||||||
}
|
}
|
||||||
@@ -822,7 +822,7 @@ namespace Titanium
|
|||||||
|
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, ServerToTitaniumSlot(int_struct->slot_id), 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, ServerToTitaniumSlot(int_struct->slot_id), 0);
|
||||||
if (ob.tellp() == last_pos) {
|
if (ob.tellp() == last_pos) {
|
||||||
Log(Logs::General, Logs::Netcode, "Titanium::ENCODE(OP_ItemPacket) Serialization failed on item slot %d.", int_struct->slot_id);
|
LogNetcode("Titanium::ENCODE(OP_ItemPacket) Serialization failed on item slot [{}]", int_struct->slot_id);
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1420,47 +1420,35 @@ namespace Titanium
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
|
|
||||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToTitaniumSayLink(new_message, old_message);
|
ServerToTitaniumSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_TaskDescription)
|
ENCODE(OP_TaskDescription)
|
||||||
@@ -1522,7 +1510,7 @@ namespace Titanium
|
|||||||
|
|
||||||
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1640,7 +1628,7 @@ namespace Titanium
|
|||||||
//determine and verify length
|
//determine and verify length
|
||||||
int entrycount = in->size / sizeof(Spawn_Struct);
|
int entrycount = in->size / sizeof(Spawn_Struct);
|
||||||
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2315,6 +2303,9 @@ namespace Titanium
|
|||||||
ob << '|' << itoa(item->SkillModType);
|
ob << '|' << itoa(item->SkillModType);
|
||||||
|
|
||||||
ob << '|' << itoa(item->BaneDmgRace);
|
ob << '|' << itoa(item->BaneDmgRace);
|
||||||
|
if (item->BaneDmgAmt > 255)
|
||||||
|
ob << '|' << "255";
|
||||||
|
else
|
||||||
ob << '|' << itoa(item->BaneDmgAmt);
|
ob << '|' << itoa(item->BaneDmgAmt);
|
||||||
ob << '|' << itoa(item->BaneDmgBody);
|
ob << '|' << itoa(item->BaneDmgBody);
|
||||||
|
|
||||||
@@ -2549,7 +2540,7 @@ namespace Titanium
|
|||||||
titanium_slot = server_slot;
|
titanium_slot = server_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Slot %i to Titanium Slot %i", server_slot, titanium_slot);
|
LogNetcode("Convert Server Slot [{}] to Titanium Slot [{}]", server_slot, titanium_slot);
|
||||||
|
|
||||||
return titanium_slot;
|
return titanium_slot;
|
||||||
}
|
}
|
||||||
@@ -2636,7 +2627,7 @@ namespace Titanium
|
|||||||
server_slot = titanium_slot;
|
server_slot = titanium_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Titanium Slot %i to Server Slot %i", titanium_slot, server_slot);
|
LogNetcode("Convert Titanium Slot [{}] to Server Slot [{}]", titanium_slot, server_slot);
|
||||||
|
|
||||||
return server_slot;
|
return server_slot;
|
||||||
}
|
}
|
||||||
@@ -2657,7 +2648,7 @@ namespace Titanium
|
|||||||
server_slot = titanium_corpse_slot + 4;
|
server_slot = titanium_corpse_slot + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Titanium Corpse Slot %i to Server Corpse Slot %i", titanium_corpse_slot, server_slot);
|
LogNetcode("Convert Titanium Corpse Slot [{}] to Server Corpse Slot [{}]", titanium_corpse_slot, server_slot);
|
||||||
|
|
||||||
return server_slot;
|
return server_slot;
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-46
@@ -79,7 +79,7 @@ namespace UF
|
|||||||
//TODO: figure out how to support shared memory with multiple patches...
|
//TODO: figure out how to support shared memory with multiple patches...
|
||||||
opcodes = new RegularOpcodeManager();
|
opcodes = new RegularOpcodeManager();
|
||||||
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
if (!opcodes->LoadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error loading opcodes file [{}]. Not registering patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ namespace UF
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[IDENTIFY] Registered patch %s", name);
|
LogNetcode("[StreamIdentify] Registered patch [{}]", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reload()
|
void Reload()
|
||||||
@@ -122,10 +122,10 @@ namespace UF
|
|||||||
opfile += name;
|
opfile += name;
|
||||||
opfile += ".conf";
|
opfile += ".conf";
|
||||||
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
if (!opcodes->ReloadOpcodes(opfile.c_str())) {
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Error reloading opcodes file %s for patch %s.", opfile.c_str(), name);
|
LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::Netcode, "[OPCODES] Reloaded opcodes for patch %s", name);
|
LogNetcode("[OPCODES] Reloaded opcodes for patch [{}]", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ namespace UF
|
|||||||
|
|
||||||
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -520,7 +520,7 @@ namespace UF
|
|||||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0);
|
||||||
if (ob.tellp() == last_pos)
|
if (ob.tellp() == last_pos)
|
||||||
Log(Logs::General, Logs::Netcode, "UF::ENCODE(OP_CharInventory) Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
LogNetcode("UF::ENCODE(OP_CharInventory) Serialization failed on item slot [{}] during OP_CharInventory. Item skipped", eq->slot_id);
|
||||||
|
|
||||||
last_pos = ob.tellp();
|
last_pos = ob.tellp();
|
||||||
}
|
}
|
||||||
@@ -1277,7 +1277,7 @@ namespace UF
|
|||||||
|
|
||||||
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0);
|
SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0);
|
||||||
if (ob.tellp() == last_pos) {
|
if (ob.tellp() == last_pos) {
|
||||||
Log(Logs::General, Logs::Netcode, "UF::ENCODE(OP_ItemPacket) Serialization failed on item slot %d.", int_struct->slot_id);
|
LogNetcode("UF::ENCODE(OP_ItemPacket) Serialization failed on item slot [{}]", int_struct->slot_id);
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2369,47 +2369,35 @@ namespace UF
|
|||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
*p = nullptr;
|
*p = nullptr;
|
||||||
|
|
||||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
SerializeBuffer buf(in->size);
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // speak mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // journal mode
|
||||||
|
buf.WriteInt8(in->ReadUInt8()); // language
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // message type
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // target spawn id
|
||||||
|
|
||||||
unsigned char *__emu_buffer = in->pBuffer;
|
std::string name;
|
||||||
|
in->ReadString(name); // NPC names max out at 63 chars
|
||||||
|
|
||||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
buf.WriteString(name);
|
||||||
|
|
||||||
|
buf.WriteInt32(in->ReadUInt32()); // loc
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
buf.WriteInt32(in->ReadUInt32());
|
||||||
|
|
||||||
|
std::string old_message;
|
||||||
std::string new_message;
|
std::string new_message;
|
||||||
|
|
||||||
|
in->ReadString(old_message);
|
||||||
|
|
||||||
ServerToUFSayLink(new_message, old_message);
|
ServerToUFSayLink(new_message, old_message);
|
||||||
|
|
||||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
buf.WriteString(new_message);
|
||||||
in->size = strlen(emu->sayer) + new_message.length() + 25;
|
|
||||||
in->pBuffer = new unsigned char[in->size];
|
|
||||||
|
|
||||||
char *OutBuffer = (char *)in->pBuffer;
|
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
dest->FastQueuePacket(&outapp, ack_req);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
delete in;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[0]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[1]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[2]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[3]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[4]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[5]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[6]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[7]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[8]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[9]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[10]);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->unknown12[11]);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
|
||||||
|
|
||||||
delete[] __emu_buffer;
|
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_Stun)
|
ENCODE(OP_Stun)
|
||||||
@@ -2484,7 +2472,7 @@ namespace UF
|
|||||||
|
|
||||||
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2716,7 +2704,7 @@ namespace UF
|
|||||||
//determine and verify length
|
//determine and verify length
|
||||||
int entrycount = in->size / sizeof(Spawn_Struct);
|
int entrycount = in->size / sizeof(Spawn_Struct);
|
||||||
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) {
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct));
|
||||||
delete in;
|
delete in;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4218,7 +4206,7 @@ namespace UF
|
|||||||
UFSlot = serverSlot;
|
UFSlot = serverSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Slot %i to UF Slot %i", serverSlot, UFSlot);
|
LogNetcode("Convert Server Slot [{}] to UF Slot [{}]", serverSlot, UFSlot);
|
||||||
|
|
||||||
return UFSlot;
|
return UFSlot;
|
||||||
}
|
}
|
||||||
@@ -4235,7 +4223,7 @@ namespace UF
|
|||||||
UFSlot = serverCorpseSlot - 2;
|
UFSlot = serverCorpseSlot - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert Server Corpse Slot %i to UF Corpse Slot %i", serverCorpseSlot, UFSlot);
|
LogNetcode("Convert Server Corpse Slot [{}] to UF Corpse Slot [{}]", serverCorpseSlot, UFSlot);
|
||||||
|
|
||||||
return UFSlot;
|
return UFSlot;
|
||||||
}
|
}
|
||||||
@@ -4300,7 +4288,7 @@ namespace UF
|
|||||||
ServerSlot = ufSlot;
|
ServerSlot = ufSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert UF Slot %i to Server Slot %i", ufSlot, ServerSlot);
|
LogNetcode("Convert UF Slot [{}] to Server Slot [{}]", ufSlot, ServerSlot);
|
||||||
|
|
||||||
return ServerSlot;
|
return ServerSlot;
|
||||||
}
|
}
|
||||||
@@ -4317,7 +4305,7 @@ namespace UF
|
|||||||
ServerSlot = ufCorpseSlot + 2;
|
ServerSlot = ufCorpseSlot + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Netcode, "Convert UF Corpse Slot %i to Server Corpse Slot %i", ufCorpseSlot, ServerSlot);
|
LogNetcode("Convert UF Corpse Slot [{}] to Server Corpse Slot [{}]", ufCorpseSlot, ServerSlot);
|
||||||
|
|
||||||
return ServerSlot;
|
return ServerSlot;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 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 "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
EQEmuExePlatform exe_platform = ExePlatformNone;
|
EQEmuExePlatform exe_platform = ExePlatformNone;
|
||||||
@@ -10,6 +30,44 @@ const EQEmuExePlatform& GetExecutablePlatform() {
|
|||||||
return exe_platform;
|
return exe_platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
int GetExecutablePlatformInt(){
|
int GetExecutablePlatformInt(){
|
||||||
return exe_platform;
|
return exe_platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns platform name by string
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string GetPlatformName()
|
||||||
|
{
|
||||||
|
switch (GetExecutablePlatformInt()) {
|
||||||
|
case EQEmuExePlatform::ExePlatformWorld:
|
||||||
|
return "WorldServer";
|
||||||
|
case EQEmuExePlatform::ExePlatformQueryServ:
|
||||||
|
return "QueryServer";
|
||||||
|
case EQEmuExePlatform::ExePlatformZone:
|
||||||
|
return "ZoneServer";
|
||||||
|
case EQEmuExePlatform::ExePlatformUCS:
|
||||||
|
return "UCS";
|
||||||
|
case EQEmuExePlatform::ExePlatformLogin:
|
||||||
|
return "LoginServer";
|
||||||
|
case EQEmuExePlatform::ExePlatformSocket_Server:
|
||||||
|
return "SocketServer";
|
||||||
|
case EQEmuExePlatform::ExePlatformSharedMemory:
|
||||||
|
return "SharedMemory";
|
||||||
|
case EQEmuExePlatform::ExePlatformClientImport:
|
||||||
|
return "ClientImport";
|
||||||
|
case EQEmuExePlatform::ExePlatformClientExport:
|
||||||
|
return "ClientExport";
|
||||||
|
case EQEmuExePlatform::ExePlatformLaunch:
|
||||||
|
return "Launch";
|
||||||
|
case EQEmuExePlatform::ExePlatformHC:
|
||||||
|
return "HC";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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_PLATFORM_H
|
#ifndef EQEMU_PLATFORM_H
|
||||||
#define EQEMU_PLATFORM_H
|
#define EQEMU_PLATFORM_H
|
||||||
|
|
||||||
|
#include "iostream"
|
||||||
|
|
||||||
enum EQEmuExePlatform
|
enum EQEmuExePlatform
|
||||||
{
|
{
|
||||||
ExePlatformNone = 0,
|
ExePlatformNone = 0,
|
||||||
@@ -20,5 +42,6 @@ enum EQEmuExePlatform
|
|||||||
void RegisterExecutablePlatform(EQEmuExePlatform p);
|
void RegisterExecutablePlatform(EQEmuExePlatform p);
|
||||||
const EQEmuExePlatform& GetExecutablePlatform();
|
const EQEmuExePlatform& GetExecutablePlatform();
|
||||||
int GetExecutablePlatformInt();
|
int GetExecutablePlatformInt();
|
||||||
|
std::string GetPlatformName();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-17
@@ -134,7 +134,6 @@ bool PersistentTimer::Load(Database *db) {
|
|||||||
(unsigned long)_char_id, _type);
|
(unsigned long)_char_id, _type);
|
||||||
auto results = db->QueryDatabase(query);
|
auto results = db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Error, "Error in PersistentTimer::Load, error: %s", results.ErrorMessage().c_str());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,9 +164,6 @@ bool PersistentTimer::Store(Database *db) {
|
|||||||
#endif
|
#endif
|
||||||
auto results = db->QueryDatabase(query);
|
auto results = db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
#if EQDEBUG > 5
|
|
||||||
Log(Logs::General, Logs::Error, "Error in PersistentTimer::Store, error: %s", results.ErrorMessage().c_str());
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +181,6 @@ bool PersistentTimer::Clear(Database *db) {
|
|||||||
|
|
||||||
auto results = db->QueryDatabase(query);
|
auto results = db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
#if EQDEBUG > 5
|
|
||||||
Log(Logs::General, Logs::Error, "Error in PersistentTimer::Clear, error: %s", results.ErrorMessage().c_str());
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +191,7 @@ bool PersistentTimer::Clear(Database *db) {
|
|||||||
/* This function checks if the timer triggered */
|
/* This function checks if the timer triggered */
|
||||||
bool PersistentTimer::Expired(Database *db, bool iReset) {
|
bool PersistentTimer::Expired(Database *db, bool iReset) {
|
||||||
if (this == nullptr) {
|
if (this == nullptr) {
|
||||||
Log(Logs::General, Logs::Error, "Null timer during ->Check()!?\n");
|
LogError("Null timer during ->Check()!?\n");
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
uint32 current_time = get_current_time();
|
uint32 current_time = get_current_time();
|
||||||
@@ -289,9 +282,6 @@ bool PTimerList::Load(Database *db) {
|
|||||||
(unsigned long)_char_id);
|
(unsigned long)_char_id);
|
||||||
auto results = db->QueryDatabase(query);
|
auto results = db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
#if EQDEBUG > 5
|
|
||||||
Log(Logs::General, Logs::Error, "Error in PersistentTimer::Load, error: %s", results.ErrorMessage().c_str());
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,9 +338,6 @@ bool PTimerList::Clear(Database *db) {
|
|||||||
#endif
|
#endif
|
||||||
auto results = db->QueryDatabase(query);
|
auto results = db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
#if EQDEBUG > 5
|
|
||||||
Log(Logs::General, Logs::Error, "Error in PersistentTimer::Clear, error: %s", results.ErrorMessage().c_str());
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,9 +427,6 @@ bool PTimerList::ClearOffline(Database *db, uint32 char_id, pTimerType type) {
|
|||||||
#endif
|
#endif
|
||||||
auto results = db->QueryDatabase(query);
|
auto results = db->QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
#if EQDEBUG > 5
|
|
||||||
Log(Logs::General, Logs::Error, "Error in PTimerList::ClearOffline, error: %s", results.ErrorMessage().c_str());
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+326
-69
@@ -21,6 +21,7 @@
|
|||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Commands:
|
Commands:
|
||||||
@@ -45,14 +46,14 @@ const char *RuleManager::s_categoryNames[_CatCount+1] = {
|
|||||||
|
|
||||||
const RuleManager::RuleInfo RuleManager::s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount+1] = {
|
const RuleManager::RuleInfo RuleManager::s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount+1] = {
|
||||||
/* this is done in three steps so we can reliably get to them by index*/
|
/* this is done in three steps so we can reliably get to them by index*/
|
||||||
#define RULE_INT(cat, rule, default_value) \
|
#define RULE_INT(cat, rule, default_value, notes) \
|
||||||
{ #cat ":" #rule, Category__##cat, IntRule, Int__##rule },
|
{ #cat ":" #rule, Category__##cat, IntRule, Int__##rule, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
#define RULE_REAL(cat, rule, default_value) \
|
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||||
{ #cat ":" #rule, Category__##cat, RealRule, Real__##rule },
|
{ #cat ":" #rule, Category__##cat, RealRule, Real__##rule, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
#define RULE_BOOL(cat, rule, default_value) \
|
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||||
{ #cat ":" #rule, Category__##cat, BoolRule, Bool__##rule },
|
{ #cat ":" #rule, Category__##cat, BoolRule, Bool__##rule, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
{ "Invalid Rule", _CatCount, IntRule }
|
{ "Invalid Rule", _CatCount, IntRule }
|
||||||
};
|
};
|
||||||
@@ -145,11 +146,11 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas
|
|||||||
switch(type) {
|
switch(type) {
|
||||||
case IntRule:
|
case IntRule:
|
||||||
m_RuleIntValues[index] = atoi(rule_value);
|
m_RuleIntValues[index] = atoi(rule_value);
|
||||||
Log(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]);
|
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleIntValues[index]);
|
||||||
break;
|
break;
|
||||||
case RealRule:
|
case RealRule:
|
||||||
m_RuleRealValues[index] = atof(rule_value);
|
m_RuleRealValues[index] = atof(rule_value);
|
||||||
Log(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
|
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleRealValues[index]);
|
||||||
break;
|
break;
|
||||||
case BoolRule:
|
case BoolRule:
|
||||||
uint32 val = 0;
|
uint32 val = 0;
|
||||||
@@ -157,7 +158,7 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas
|
|||||||
val = 1;
|
val = 1;
|
||||||
|
|
||||||
m_RuleBoolValues[index] = val;
|
m_RuleBoolValues[index] = val;
|
||||||
Log(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
|
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,11 +179,11 @@ void RuleManager::ResetRules(bool reload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values");
|
Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values");
|
||||||
#define RULE_INT(cat, rule, default_value) \
|
#define RULE_INT(cat, rule, default_value, notes) \
|
||||||
m_RuleIntValues[ Int__##rule ] = default_value;
|
m_RuleIntValues[ Int__##rule ] = default_value;
|
||||||
#define RULE_REAL(cat, rule, default_value) \
|
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||||
m_RuleRealValues[ Real__##rule ] = default_value;
|
m_RuleRealValues[ Real__##rule ] = default_value;
|
||||||
#define RULE_BOOL(cat, rule, default_value) \
|
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||||
m_RuleBoolValues[ Bool__##rule ] = default_value;
|
m_RuleBoolValues[ Bool__##rule ] = default_value;
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
|
|
||||||
@@ -217,12 +218,94 @@ const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
|||||||
case IntRule:
|
case IntRule:
|
||||||
return(s_RuleInfo[index].name);
|
return(s_RuleInfo[index].name);
|
||||||
case RealRule:
|
case RealRule:
|
||||||
return(s_RuleInfo[index + _IntRuleCount].name);
|
return(s_RuleInfo[index+_IntRuleCount].name);
|
||||||
case BoolRule:
|
case BoolRule:
|
||||||
return(s_RuleInfo[index + _IntRuleCount + _RealRuleCount].name);
|
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
//should never happen
|
//should never happen
|
||||||
return("InvalidRule??");
|
return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].name); // no need to create a string when one already exists...
|
||||||
|
}
|
||||||
|
|
||||||
|
//assumes index is valid!
|
||||||
|
const std::string &RuleManager::_GetRuleNotes(RuleType type, uint16 index) {
|
||||||
|
switch (type) {
|
||||||
|
case IntRule:
|
||||||
|
return(s_RuleInfo[index].notes);
|
||||||
|
case RealRule:
|
||||||
|
return(s_RuleInfo[index+_IntRuleCount].notes);
|
||||||
|
case BoolRule:
|
||||||
|
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].notes);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//should never happen
|
||||||
|
return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
||||||
|
|
||||||
|
int ruleset_id = this->GetRulesetID(database, ruleset_name);
|
||||||
|
if (ruleset_id < 0) {
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_activeRuleset = ruleset_id;
|
||||||
|
m_activeName = ruleset_name;
|
||||||
|
|
||||||
|
/* Load default ruleset values first if we're loading something other than default */
|
||||||
|
if (strcasecmp(ruleset_name, "default") != 0) {
|
||||||
|
|
||||||
|
std::string default_ruleset_name = "default";
|
||||||
|
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
|
||||||
|
|
||||||
|
if (default_ruleset_id < 0) {
|
||||||
|
Log(Logs::Detail,
|
||||||
|
Logs::Rules,
|
||||||
|
"Failed to find default ruleset '%s' for load operation. Canceling.",
|
||||||
|
default_ruleset_name.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Processing rule set '%s' (%d) load...", default_ruleset_name.c_str(), default_ruleset_id);
|
||||||
|
|
||||||
|
std::string query = StringFormat(
|
||||||
|
"SELECT `rule_name`, `rule_value` FROM `rule_values` WHERE `ruleset_id` = '%d'",
|
||||||
|
default_ruleset_id
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = database->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
if (!SetRule(row[0], row[1], nullptr, false, reload)) {
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for '%s'", row[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Processing rule set '%s' (%d) load...", ruleset_name, ruleset_id);
|
||||||
|
|
||||||
|
std::string query = StringFormat("SELECT `rule_name`, `rule_value` FROM `rule_values` WHERE `ruleset_id` = '%d'", ruleset_id);
|
||||||
|
|
||||||
|
auto results = database->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
if (!SetRule(row[0], row[1], nullptr, false, reload)) {
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for '%s'", row[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
||||||
@@ -257,56 +340,6 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
|
||||||
|
|
||||||
int ruleset_id = this->GetRulesetID(database, ruleset_name);
|
|
||||||
if (ruleset_id < 0) {
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset_name, ruleset_id);
|
|
||||||
|
|
||||||
m_activeRuleset = ruleset_id;
|
|
||||||
m_activeName = ruleset_name;
|
|
||||||
|
|
||||||
/* Load default ruleset values first if we're loading something other than default */
|
|
||||||
if (strcasecmp(ruleset_name, "default") != 0) {
|
|
||||||
std::string default_ruleset_name = "default";
|
|
||||||
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
|
|
||||||
if (default_ruleset_id < 0) {
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.",
|
|
||||||
default_ruleset_name.c_str());
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id);
|
|
||||||
|
|
||||||
std::string query = StringFormat(
|
|
||||||
"SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d",
|
|
||||||
default_ruleset_id
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = database->QueryDatabase(query);
|
|
||||||
if (!results.Success())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row)
|
|
||||||
if (!SetRule(row[0], row[1], nullptr, false, reload))
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
|
|
||||||
auto results = database->QueryDatabase(query);
|
|
||||||
if (!results.Success())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row)
|
|
||||||
if (!SetRule(row[0], row[1], nullptr, false, reload))
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
||||||
char value_string[100];
|
char value_string[100];
|
||||||
|
|
||||||
@@ -328,17 +361,241 @@ void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"REPLACE INTO rule_values "
|
"REPLACE INTO `rule_values`"
|
||||||
"(ruleset_id, rule_name, rule_value) "
|
"(`ruleset_id`, `rule_name`, `rule_value`, `notes`)"
|
||||||
" VALUES(%d, '%s', '%s')",
|
" VALUES('%d', '%s', '%s', '%s')",
|
||||||
m_activeRuleset,
|
m_activeRuleset,
|
||||||
_GetRuleName(type, index),
|
_GetRuleName(type, index),
|
||||||
value_string
|
value_string,
|
||||||
|
EscapeString(_GetRuleNotes(type, index)).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
database->QueryDatabase(query);
|
database->QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RuleManager::UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update)
|
||||||
|
{
|
||||||
|
std::vector<std::string> database_data;
|
||||||
|
std::map<std::string, std::pair<std::string, const std::string *>> rule_data;
|
||||||
|
std::vector<std::tuple<int, std::string, std::string, std::string>> injected_rule_entries;
|
||||||
|
|
||||||
|
if (ruleset_name == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ruleset_id = GetRulesetID(db, ruleset_name);
|
||||||
|
if (ruleset_id < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load database rule names
|
||||||
|
std::string query(StringFormat("SELECT `rule_name` FROM `rule_values` WHERE `ruleset_id` = '%i'", ruleset_id));
|
||||||
|
|
||||||
|
auto results = db->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build database data entries
|
||||||
|
for (auto row : results) {
|
||||||
|
database_data.push_back(std::string(row[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// build rule data entries
|
||||||
|
for (const auto &ri_iter : s_RuleInfo) {
|
||||||
|
if (strcasecmp(ri_iter.name, "Invalid Rule") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[100];
|
||||||
|
|
||||||
|
switch (ri_iter.type) {
|
||||||
|
case IntRule:
|
||||||
|
sprintf(buffer, "%d", m_RuleIntValues[ri_iter.rule_index]);
|
||||||
|
rule_data[ri_iter.name].first = buffer;
|
||||||
|
rule_data[ri_iter.name].second = &ri_iter.notes;
|
||||||
|
break;
|
||||||
|
case RealRule:
|
||||||
|
sprintf(buffer, "%.13f", m_RuleRealValues[ri_iter.rule_index]);
|
||||||
|
rule_data[ri_iter.name].first = buffer;
|
||||||
|
rule_data[ri_iter.name].second = &ri_iter.notes;
|
||||||
|
break;
|
||||||
|
case BoolRule:
|
||||||
|
sprintf(buffer, "%s", (m_RuleBoolValues[ri_iter.rule_index] ? "true" : "false"));
|
||||||
|
rule_data[ri_iter.name].first = buffer;
|
||||||
|
rule_data[ri_iter.name].second = &ri_iter.notes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build injected entries
|
||||||
|
for (const auto &rd_iter : rule_data) {
|
||||||
|
|
||||||
|
const auto &dd_iter = std::find(database_data.begin(), database_data.end(), rd_iter.first);
|
||||||
|
if (dd_iter == database_data.end()) {
|
||||||
|
|
||||||
|
injected_rule_entries.push_back(
|
||||||
|
std::tuple<int, std::string, std::string, std::string>(
|
||||||
|
ruleset_id, // `ruleset_id`
|
||||||
|
rd_iter.first, // `rule_name`
|
||||||
|
rd_iter.second.first, // `rule_value`
|
||||||
|
EscapeString(*rd_iter.second.second) // `notes`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!quiet_update) {
|
||||||
|
LogInfo(
|
||||||
|
"Adding new rule [{}] ruleset [{}] ({}) value [{}]",
|
||||||
|
rd_iter.first.c_str(),
|
||||||
|
ruleset_name,
|
||||||
|
ruleset_id,
|
||||||
|
rd_iter.second.first.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (injected_rule_entries.size()) {
|
||||||
|
|
||||||
|
std::string query(
|
||||||
|
fmt::format(
|
||||||
|
"REPLACE INTO `rule_values`(`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}",
|
||||||
|
implode(
|
||||||
|
",",
|
||||||
|
std::pair<char, char>('(', ')'),
|
||||||
|
join_tuple(",", std::pair<char, char>('\'', '\''), injected_rule_entries)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!db->QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"[{}] New rule(s) added to ruleset [{}] [{}]",
|
||||||
|
injected_rule_entries.size(),
|
||||||
|
ruleset_name,
|
||||||
|
ruleset_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleManager::UpdateOrphanedRules(Database *db, bool quiet_update)
|
||||||
|
{
|
||||||
|
std::vector<std::string> rule_data;
|
||||||
|
std::vector<std::string> orphaned_rule_entries;
|
||||||
|
|
||||||
|
// load database rule names
|
||||||
|
std::string query("SELECT `rule_name` FROM `rule_values` GROUP BY `rule_name`");
|
||||||
|
|
||||||
|
auto results = db->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build rule data entries
|
||||||
|
for (const auto &ri_iter : s_RuleInfo) {
|
||||||
|
if (strcasecmp(ri_iter.name, "Invalid Rule") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_data.push_back(ri_iter.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build orphaned entries
|
||||||
|
for (auto row : results) {
|
||||||
|
|
||||||
|
const auto &rd_iter = std::find(rule_data.begin(), rule_data.end(), row[0]);
|
||||||
|
if (rd_iter == rule_data.end()) {
|
||||||
|
|
||||||
|
orphaned_rule_entries.push_back(std::string(row[0]));
|
||||||
|
|
||||||
|
if (!quiet_update) {
|
||||||
|
LogInfo(
|
||||||
|
"Rule [{}] no longer exists... Deleting orphaned entry from `rule_values` table...",
|
||||||
|
row[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orphaned_rule_entries.size()) {
|
||||||
|
|
||||||
|
std::string query (
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM `rule_values` WHERE `rule_name` IN ({})",
|
||||||
|
implode(",", std::pair<char, char>('\'', '\''), orphaned_rule_entries)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!db->QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("[{}] Orphaned Rule(s) Deleted from [All Rulesets] (-1)", orphaned_rule_entries.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleManager::RestoreRuleNotes(Database *db)
|
||||||
|
{
|
||||||
|
std::string query("SELECT `ruleset_id`, `rule_name`, `notes` FROM `rule_values`");
|
||||||
|
|
||||||
|
auto results = db->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int update_count = 0;
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
|
||||||
|
auto rule = [](const char *rule_name) {
|
||||||
|
|
||||||
|
for (auto rule_iter : s_RuleInfo) {
|
||||||
|
if (strcasecmp(rule_iter.name, rule_name) == 0) {
|
||||||
|
return rule_iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount];
|
||||||
|
}(row[1]);
|
||||||
|
|
||||||
|
if (strcasecmp(rule.name, row[1]) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row[2] != nullptr && rule.notes.compare(row[2]) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string query(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE `rule_values` SET `notes` = '{}' WHERE `ruleset_id` = '{}' AND `rule_name` = '{}'",
|
||||||
|
EscapeString(rule.notes),
|
||||||
|
row[0],
|
||||||
|
row[1]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!db->QueryDatabase(query).Success()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++update_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_count > 0) {
|
||||||
|
LogInfo("[{}] Rule Note [{}] Restored", update_count, (update_count == 1 ? "" : "s"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
|
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
|
||||||
|
|
||||||
|
|||||||
+11
-3
@@ -49,21 +49,21 @@ class RuleManager {
|
|||||||
public:
|
public:
|
||||||
//generate our rule enums:
|
//generate our rule enums:
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define RULE_INT(cat, rule, default_value) \
|
#define RULE_INT(cat, rule, default_value, notes) \
|
||||||
Int__##rule,
|
Int__##rule,
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
_IntRuleCount
|
_IntRuleCount
|
||||||
} IntType;
|
} IntType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define RULE_REAL(cat, rule, default_value) \
|
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||||
Real__##rule,
|
Real__##rule,
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
_RealRuleCount
|
_RealRuleCount
|
||||||
} RealType;
|
} RealType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define RULE_BOOL(cat, rule, default_value) \
|
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||||
Bool__##rule,
|
Bool__##rule,
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
_BoolRuleCount
|
_BoolRuleCount
|
||||||
@@ -97,6 +97,9 @@ public:
|
|||||||
static const char *GetRuleName(IntType t) { return(s_RuleInfo[t].name); }
|
static const char *GetRuleName(IntType t) { return(s_RuleInfo[t].name); }
|
||||||
static const char *GetRuleName(RealType t) { return(s_RuleInfo[t+_IntRuleCount].name); }
|
static const char *GetRuleName(RealType t) { return(s_RuleInfo[t+_IntRuleCount].name); }
|
||||||
static const char *GetRuleName(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].name); }
|
static const char *GetRuleName(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].name); }
|
||||||
|
static const std::string &GetRuleNotes(IntType t) { return(s_RuleInfo[t].notes); }
|
||||||
|
static const std::string &GetRuleNotes(RealType t) { return(s_RuleInfo[t+_IntRuleCount].notes); }
|
||||||
|
static const std::string &GetRuleNotes(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].notes); }
|
||||||
static uint32 CountRules() { return(_RulesCount); }
|
static uint32 CountRules() { return(_RulesCount); }
|
||||||
static CategoryType FindCategory(const char *catname);
|
static CategoryType FindCategory(const char *catname);
|
||||||
bool ListRules(const char *catname, std::vector<const char *> &into);
|
bool ListRules(const char *catname, std::vector<const char *> &into);
|
||||||
@@ -113,6 +116,9 @@ public:
|
|||||||
void ResetRules(bool reload = false);
|
void ResetRules(bool reload = false);
|
||||||
bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false);
|
bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false);
|
||||||
void SaveRules(Database *db, const char *ruleset = nullptr);
|
void SaveRules(Database *db, const char *ruleset = nullptr);
|
||||||
|
bool UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update = false);
|
||||||
|
bool UpdateOrphanedRules(Database *db, bool quiet_update = false);
|
||||||
|
bool RestoreRuleNotes(Database *db);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RuleManager();
|
RuleManager();
|
||||||
@@ -137,6 +143,7 @@ private:
|
|||||||
|
|
||||||
static bool _FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into);
|
static bool _FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into);
|
||||||
static const char *_GetRuleName(RuleType type, uint16 index);
|
static const char *_GetRuleName(RuleType type, uint16 index);
|
||||||
|
static const std::string &_GetRuleNotes(RuleType type, uint16 index);
|
||||||
static int _FindOrCreateRuleset(Database *db, const char *ruleset);
|
static int _FindOrCreateRuleset(Database *db, const char *ruleset);
|
||||||
void _SaveRule(Database *db, RuleType type, uint16 index);
|
void _SaveRule(Database *db, RuleType type, uint16 index);
|
||||||
|
|
||||||
@@ -146,6 +153,7 @@ private:
|
|||||||
CategoryType category;
|
CategoryType category;
|
||||||
RuleType type;
|
RuleType type;
|
||||||
uint16 rule_index; //index into its 'type' array
|
uint16 rule_index; //index into its 'type' array
|
||||||
|
const std::string notes;
|
||||||
} RuleInfo;
|
} RuleInfo;
|
||||||
static const RuleInfo s_RuleInfo[];
|
static const RuleInfo s_RuleInfo[];
|
||||||
|
|
||||||
|
|||||||
+623
-603
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -100,8 +100,8 @@ const std::string &EQEmu::SayLinkEngine::GenerateLink()
|
|||||||
if ((m_Link.length() == 0) || (m_Link.length() > (EQEmu::constants::SAY_LINK_MAXIMUM_SIZE))) {
|
if ((m_Link.length() == 0) || (m_Link.length() > (EQEmu::constants::SAY_LINK_MAXIMUM_SIZE))) {
|
||||||
m_Error = true;
|
m_Error = true;
|
||||||
m_Link = "<LINKER ERROR>";
|
m_Link = "<LINKER ERROR>";
|
||||||
Log(Logs::General, Logs::Error, "SayLinkEngine::GenerateLink() failed to generate a useable say link");
|
LogError("SayLinkEngine::GenerateLink() failed to generate a useable say link");
|
||||||
Log(Logs::General, Logs::Error, ">> LinkType: %i, Lengths: {link: %u(%u), body: %u(%u), text: %u(%u)}",
|
LogError(">> LinkType: {}, Lengths: {link: {}({}), body: {}({}), text: {}({})}",
|
||||||
m_LinkType,
|
m_LinkType,
|
||||||
m_Link.length(),
|
m_Link.length(),
|
||||||
EQEmu::constants::SAY_LINK_MAXIMUM_SIZE,
|
EQEmu::constants::SAY_LINK_MAXIMUM_SIZE,
|
||||||
@@ -110,8 +110,8 @@ const std::string &EQEmu::SayLinkEngine::GenerateLink()
|
|||||||
m_LinkText.length(),
|
m_LinkText.length(),
|
||||||
EQEmu::constants::SAY_LINK_TEXT_SIZE
|
EQEmu::constants::SAY_LINK_TEXT_SIZE
|
||||||
);
|
);
|
||||||
Log(Logs::General, Logs::Error, ">> LinkBody: %s", m_LinkBody.c_str());
|
LogError(">> LinkBody: {}", m_LinkBody.c_str());
|
||||||
Log(Logs::General, Logs::Error, ">> LinkText: %s", m_LinkText.c_str());
|
LogError(">> LinkText: {}", m_LinkText.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_Link;
|
return m_Link;
|
||||||
@@ -316,7 +316,7 @@ std::string EQEmu::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text,
|
|||||||
|
|
||||||
results = database.QueryDatabase(insert_query);
|
results = database.QueryDatabase(insert_query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Error, "Error in saylink phrase queries %s", results.ErrorMessage().c_str());
|
LogError("Error in saylink phrase queries {}", results.ErrorMessage().c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
saylink_id = results.LastInsertedID();
|
saylink_id = results.LastInsertedID();
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public:
|
|||||||
void WriteString(const char *str)
|
void WriteString(const char *str)
|
||||||
{
|
{
|
||||||
assert(str != nullptr);
|
assert(str != nullptr);
|
||||||
auto len = strlen(str) + 1;
|
auto len = std::char_traits<char>::length(str) + 1;
|
||||||
if (m_pos + len > m_capacity)
|
if (m_pos + len > m_capacity)
|
||||||
Grow(m_capacity + len);
|
Grow(m_capacity + len);
|
||||||
memcpy(m_buffer + m_pos, str, len);
|
memcpy(m_buffer + m_pos, str, len);
|
||||||
|
|||||||
+69
-98
@@ -15,109 +15,80 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
// Serverinfo.cpp - Server information gathering functions, used in #serverinfo - Windows specific
|
|
||||||
// I'm not sure quite how to get this exact information in *nix, hopefully someone can fill that in
|
|
||||||
// -T7g
|
|
||||||
// Implement preliminary support for *nix variants
|
|
||||||
// misanthropicfiend
|
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#include "serverinfo.h"
|
||||||
#include <windows.h>
|
#include <uv.h>
|
||||||
|
|
||||||
char Ver_name[100];
|
size_t EQ::GetRSS()
|
||||||
DWORD Ver_build, Ver_min, Ver_maj, Ver_pid;
|
{
|
||||||
|
size_t rss = 0;
|
||||||
int GetOS() {
|
|
||||||
|
|
||||||
strcpy(Ver_name, "Unknown operating system");
|
|
||||||
|
|
||||||
OSVERSIONINFO Ver_os;
|
|
||||||
Ver_os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
||||||
|
|
||||||
if(!(GetVersionEx(&Ver_os))) return 1;
|
|
||||||
|
|
||||||
Ver_build = Ver_os.dwBuildNumber & 0xFFFF;
|
|
||||||
Ver_min = Ver_os.dwMinorVersion;
|
|
||||||
Ver_maj = Ver_os.dwMajorVersion;
|
|
||||||
Ver_pid = Ver_os.dwPlatformId;
|
|
||||||
|
|
||||||
if ((Ver_pid == 1) && (Ver_maj == 4))
|
|
||||||
{
|
|
||||||
if ((Ver_min < 10) && (Ver_build == 950))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 95");
|
|
||||||
}
|
|
||||||
else if ((Ver_min < 10) &&
|
|
||||||
((Ver_build > 950) && (Ver_build <= 1080)))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 95 SP1");
|
|
||||||
}
|
|
||||||
else if ((Ver_min < 10) && (Ver_build > 1080))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 95 OSR2");
|
|
||||||
}
|
|
||||||
else if ((Ver_min == 10) && (Ver_build == 1998))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 98");
|
|
||||||
}
|
|
||||||
else if ((Ver_min == 10) &&
|
|
||||||
((Ver_build > 1998) && (Ver_build < 2183)))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 98, Service Pack 1");
|
|
||||||
}
|
|
||||||
else if ((Ver_min == 10) && (Ver_build >= 2183))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 98 Second Edition");
|
|
||||||
}
|
|
||||||
else if (Ver_min == 90)
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows ME");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Ver_pid == 2)
|
|
||||||
{
|
|
||||||
if ((Ver_maj == 3) && (Ver_min == 51))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows NT 3.51");
|
|
||||||
}
|
|
||||||
else if ((Ver_maj == 4) && (Ver_min == 0))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows NT 4");
|
|
||||||
}
|
|
||||||
else if ((Ver_maj == 5) && (Ver_min == 0))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 2000");
|
|
||||||
}
|
|
||||||
else if ((Ver_maj == 5) && (Ver_min == 1))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows XP");
|
|
||||||
}
|
|
||||||
else if ((Ver_maj == 5) && (Ver_min == 2))
|
|
||||||
{
|
|
||||||
strcpy(Ver_name, "Microsoft Windows 2003");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (0 != uv_resident_set_memory(&rss)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
char* GetOS(char* os_string) {
|
|
||||||
utsname info;
|
|
||||||
|
|
||||||
if(uname(&info)==0) {
|
|
||||||
snprintf(os_string, 99, "%s %s %s %s %s", info.sysname, info.nodename, info.release, info.version, info.machine);
|
|
||||||
} else {
|
|
||||||
strncpy(os_string, "Error determining OS & version!", 25);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return os_string;
|
return rss;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
double EQ::GetUptime()
|
||||||
|
{
|
||||||
|
double uptime = 0.0;
|
||||||
|
|
||||||
|
if (0 != uv_uptime(&uptime)) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uptime;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t EQ::GetPID()
|
||||||
|
{
|
||||||
|
return uv_os_getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<eq_cpu_info_t> EQ::GetCPUs()
|
||||||
|
{
|
||||||
|
std::vector<eq_cpu_info_t> ret;
|
||||||
|
uv_cpu_info_t *cpu_info = nullptr;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (0 != uv_cpu_info(&cpu_info, &count)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.reserve(count);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
eq_cpu_info_t r;
|
||||||
|
auto &entry = cpu_info[i];
|
||||||
|
|
||||||
|
r.model = entry.model;
|
||||||
|
r.speed = entry.speed / 1000.0;
|
||||||
|
r.time_user = entry.cpu_times.user;
|
||||||
|
r.time_sys = entry.cpu_times.sys;
|
||||||
|
r.time_idle = entry.cpu_times.idle;
|
||||||
|
r.time_nice = entry.cpu_times.nice;
|
||||||
|
r.time_irq = entry.cpu_times.irq;
|
||||||
|
|
||||||
|
ret.push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_free_cpu_info(cpu_info, count);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
eq_utsname_t EQ::GetOS()
|
||||||
|
{
|
||||||
|
eq_utsname_t ret;
|
||||||
|
uv_utsname_t name;
|
||||||
|
|
||||||
|
if (0 != uv_os_uname(&name)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.machine = name.machine;
|
||||||
|
ret.release = name.release;
|
||||||
|
ret.sysname = name.sysname;
|
||||||
|
ret.version = name.version;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
+28
-10
@@ -15,15 +15,33 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef SERVERINFO_H
|
#pragma once
|
||||||
#define SERVERINFO_H
|
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#include <string>
|
||||||
extern char Ver_name[36];
|
#include <vector>
|
||||||
extern DWORD Ver_build, Ver_min, Ver_maj, Ver_pid;
|
|
||||||
int GetOS();
|
|
||||||
#else
|
|
||||||
char* GetOS(char* os_string);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
typedef struct eq_cpu_info_s {
|
||||||
|
std::string model;
|
||||||
|
double speed;
|
||||||
|
uint64_t time_user;
|
||||||
|
uint64_t time_nice;
|
||||||
|
uint64_t time_sys;
|
||||||
|
uint64_t time_idle;
|
||||||
|
uint64_t time_irq;
|
||||||
|
} eq_cpu_info_t;
|
||||||
|
|
||||||
|
typedef struct eq_utsname_s {
|
||||||
|
std::string sysname;
|
||||||
|
std::string release;
|
||||||
|
std::string version;
|
||||||
|
std::string machine;
|
||||||
|
} eq_utsname_t;
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
size_t GetRSS();
|
||||||
|
double GetUptime();
|
||||||
|
size_t GetPID();
|
||||||
|
std::vector<eq_cpu_info_t> GetCPUs();
|
||||||
|
eq_utsname_t GetOS();
|
||||||
|
}
|
||||||
|
|||||||
+76
-19
@@ -80,6 +80,7 @@
|
|||||||
#define ServerOP_GroupJoin 0x003e //for joining ooz folks
|
#define ServerOP_GroupJoin 0x003e //for joining ooz folks
|
||||||
#define ServerOP_UpdateSpawn 0x003f
|
#define ServerOP_UpdateSpawn 0x003f
|
||||||
#define ServerOP_SpawnStatusChange 0x0040
|
#define ServerOP_SpawnStatusChange 0x0040
|
||||||
|
#define ServerOP_DropClient 0x0041 // DropClient
|
||||||
#define ServerOP_ReloadTasks 0x0060
|
#define ServerOP_ReloadTasks 0x0060
|
||||||
#define ServerOP_DepopAllPlayersCorpses 0x0061
|
#define ServerOP_DepopAllPlayersCorpses 0x0061
|
||||||
#define ServerOP_ReloadTitles 0x0062
|
#define ServerOP_ReloadTitles 0x0062
|
||||||
@@ -142,7 +143,7 @@
|
|||||||
#define ServerOP_ClientVersionSummary 0x0215
|
#define ServerOP_ClientVersionSummary 0x0215
|
||||||
#define ServerOP_LSInfo 0x1000
|
#define ServerOP_LSInfo 0x1000
|
||||||
#define ServerOP_LSStatus 0x1001
|
#define ServerOP_LSStatus 0x1001
|
||||||
#define ServerOP_LSClientAuth 0x1002
|
#define ServerOP_LSClientAuthLeg 0x1002
|
||||||
#define ServerOP_LSFatalError 0x1003
|
#define ServerOP_LSFatalError 0x1003
|
||||||
#define ServerOP_SystemwideMessage 0x1005
|
#define ServerOP_SystemwideMessage 0x1005
|
||||||
#define ServerOP_ListWorlds 0x1006
|
#define ServerOP_ListWorlds 0x1006
|
||||||
@@ -150,6 +151,7 @@
|
|||||||
#define ServerOP_NewLSInfo 0x1008
|
#define ServerOP_NewLSInfo 0x1008
|
||||||
#define ServerOP_LSRemoteAddr 0x1009
|
#define ServerOP_LSRemoteAddr 0x1009
|
||||||
#define ServerOP_LSAccountUpdate 0x100A
|
#define ServerOP_LSAccountUpdate 0x100A
|
||||||
|
#define ServerOP_LSClientAuth 0x100B
|
||||||
|
|
||||||
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
|
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
|
||||||
#define ServerOP_WorldListUpdate 0x2008
|
#define ServerOP_WorldListUpdate 0x2008
|
||||||
@@ -170,8 +172,10 @@
|
|||||||
#define ServerOP_LSPlayerJoinWorld 0x3007
|
#define ServerOP_LSPlayerJoinWorld 0x3007
|
||||||
#define ServerOP_LSPlayerZoneChange 0x3008
|
#define ServerOP_LSPlayerZoneChange 0x3008
|
||||||
|
|
||||||
#define ServerOP_UsertoWorldReq 0xAB00
|
#define ServerOP_UsertoWorldReqLeg 0xAB00
|
||||||
#define ServerOP_UsertoWorldResp 0xAB01
|
#define ServerOP_UsertoWorldRespLeg 0xAB01
|
||||||
|
#define ServerOP_UsertoWorldReq 0xAB02
|
||||||
|
#define ServerOP_UsertoWorldResp 0xAB03
|
||||||
|
|
||||||
#define ServerOP_LauncherConnectInfo 0x3000
|
#define ServerOP_LauncherConnectInfo 0x3000
|
||||||
#define ServerOP_LauncherZoneRequest 0x3001
|
#define ServerOP_LauncherZoneRequest 0x3001
|
||||||
@@ -213,6 +217,15 @@ enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_
|
|||||||
|
|
||||||
#define ServerOP_Speech 0x4513
|
#define ServerOP_Speech 0x4513
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UserToWorldStatusWorldUnavail = 0,
|
||||||
|
UserToWorldStatusSuccess = 1,
|
||||||
|
UserToWorldStatusSuspended = -1,
|
||||||
|
UserToWorldStatusBanned = -2,
|
||||||
|
UserToWorldStatusWorldAtCapacity = -3,
|
||||||
|
UserToWorldStatusAlreadyOnline = -4
|
||||||
|
};
|
||||||
|
|
||||||
/************ PACKET RELATED STRUCT ************/
|
/************ PACKET RELATED STRUCT ************/
|
||||||
class ServerPacket
|
class ServerPacket
|
||||||
{
|
{
|
||||||
@@ -308,11 +321,17 @@ struct ServerZoneIncomingClient_Struct {
|
|||||||
uint32 accid;
|
uint32 accid;
|
||||||
int16 admin;
|
int16 admin;
|
||||||
uint32 charid;
|
uint32 charid;
|
||||||
|
uint32 lsid;
|
||||||
bool tellsoff;
|
bool tellsoff;
|
||||||
char charname[64];
|
char charname[64];
|
||||||
char lskey[30];
|
char lskey[30];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ServerZoneDropClient_Struct
|
||||||
|
{
|
||||||
|
uint32 lsid;
|
||||||
|
};
|
||||||
|
|
||||||
struct ServerChangeWID_Struct {
|
struct ServerChangeWID_Struct {
|
||||||
uint32 charid;
|
uint32 charid;
|
||||||
uint32 newwid;
|
uint32 newwid;
|
||||||
@@ -343,7 +362,8 @@ struct ServerChannelMessage_Struct {
|
|||||||
bool noreply;
|
bool noreply;
|
||||||
uint16 chan_num;
|
uint16 chan_num;
|
||||||
uint32 guilddbid;
|
uint32 guilddbid;
|
||||||
uint16 language;
|
uint8 language;
|
||||||
|
uint8 lang_skill;
|
||||||
uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline
|
uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline
|
||||||
char message[0];
|
char message[0];
|
||||||
};
|
};
|
||||||
@@ -452,15 +472,15 @@ struct ServerLSInfo_Struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ServerNewLSInfo_Struct {
|
struct ServerNewLSInfo_Struct {
|
||||||
char name[201]; // name the worldserver wants
|
char server_long_name[201]; // name the worldserver wants
|
||||||
char shortname[50]; // shortname the worldserver wants
|
char server_short_name[50]; // shortname the worldserver wants
|
||||||
char remote_address[125]; // DNS address of the server
|
char remote_ip_address[125]; // DNS address of the server
|
||||||
char local_address[125]; // DNS address of the server
|
char local_ip_address[125]; // DNS address of the server
|
||||||
char account[31]; // account name for the worldserver
|
char account_name[31]; // account name for the worldserver
|
||||||
char password[31]; // password for the name
|
char account_password[31]; // password for the name
|
||||||
char protocolversion[25]; // Major protocol version number
|
char protocol_version[25]; // Major protocol version number
|
||||||
char serverversion[64]; // minor server software version number
|
char server_version[64]; // minor server software version number
|
||||||
uint8 servertype; // 0=world, 1=chat, 2=login, 3=MeshLogin
|
uint8 server_process_type; // 0=world, 1=chat, 2=login, 3=MeshLogin
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerLSAccountUpdate_Struct { // for updating info on login server
|
struct ServerLSAccountUpdate_Struct { // for updating info on login server
|
||||||
@@ -469,7 +489,7 @@ struct ServerLSAccountUpdate_Struct { // for updating info on login server
|
|||||||
uint32 useraccountid; // player account ID
|
uint32 useraccountid; // player account ID
|
||||||
char useraccount[31]; // player account name
|
char useraccount[31]; // player account name
|
||||||
char userpassword[51]; // player account password
|
char userpassword[51]; // player account password
|
||||||
char useremail[101]; // player account email address
|
char user_email[101]; // player account email address
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerLSStatus_Struct {
|
struct ServerLSStatus_Struct {
|
||||||
@@ -516,18 +536,35 @@ struct ServerLSPlayerZoneChange_Struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ClientAuth_Struct {
|
struct ClientAuth_Struct {
|
||||||
uint32 lsaccount_id; // ID# in login server's db
|
uint32 loginserver_account_id; // ID# in login server's db
|
||||||
char name[30]; // username in login server's db
|
char loginserver_name[64];
|
||||||
|
char account_name[30]; // username in login server's db
|
||||||
char key[30]; // the Key the client will present
|
char key[30]; // the Key the client will present
|
||||||
uint8 lsadmin; // login server admin level
|
uint8 lsadmin; // login server admin level
|
||||||
int16 worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
|
int16 is_world_admin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
|
||||||
uint32 ip;
|
uint32 ip;
|
||||||
uint8 local; // 1 if the client is from the local network
|
uint8 is_client_from_local_network; // 1 if the client is from the local network
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive &ar)
|
void serialize(Archive &ar)
|
||||||
{
|
{
|
||||||
ar(lsaccount_id, name, key, lsadmin, worldadmin, ip, local);
|
ar(loginserver_account_id, loginserver_name, account_name, key, lsadmin, is_world_admin, ip, is_client_from_local_network);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClientAuthLegacy_Struct {
|
||||||
|
uint32 loginserver_account_id; // ID# in login server's db
|
||||||
|
char loginserver_account_name[30]; // username in login server's db
|
||||||
|
char key[30]; // the Key the client will present
|
||||||
|
uint8 loginserver_admin_level; // login server admin level
|
||||||
|
int16 is_world_admin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
|
||||||
|
uint32 ip;
|
||||||
|
uint8 is_client_from_local_network; // 1 if the client is from the local network
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void serialize(Archive &ar)
|
||||||
|
{
|
||||||
|
ar(loginserver_account_id, loginserver_account_name, key, loginserver_admin_level, is_world_admin, ip, is_client_from_local_network);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -655,12 +692,29 @@ struct ServerSyncWorldList_Struct {
|
|||||||
bool placeholder;
|
bool placeholder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UsertoWorldRequestLegacy_Struct {
|
||||||
|
uint32 lsaccountid;
|
||||||
|
uint32 worldid;
|
||||||
|
uint32 FromID;
|
||||||
|
uint32 ToID;
|
||||||
|
char IPAddr[64];
|
||||||
|
};
|
||||||
|
|
||||||
struct UsertoWorldRequest_Struct {
|
struct UsertoWorldRequest_Struct {
|
||||||
uint32 lsaccountid;
|
uint32 lsaccountid;
|
||||||
uint32 worldid;
|
uint32 worldid;
|
||||||
uint32 FromID;
|
uint32 FromID;
|
||||||
uint32 ToID;
|
uint32 ToID;
|
||||||
char IPAddr[64];
|
char IPAddr[64];
|
||||||
|
char login[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UsertoWorldResponseLegacy_Struct {
|
||||||
|
uint32 lsaccountid;
|
||||||
|
uint32 worldid;
|
||||||
|
int8 response; // -3) World Full, -2) Banned, -1) Suspended, 0) Denied, 1) Allowed
|
||||||
|
uint32 FromID;
|
||||||
|
uint32 ToID;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UsertoWorldResponse_Struct {
|
struct UsertoWorldResponse_Struct {
|
||||||
@@ -669,6 +723,7 @@ struct UsertoWorldResponse_Struct {
|
|||||||
int8 response; // -3) World Full, -2) Banned, -1) Suspended, 0) Denied, 1) Allowed
|
int8 response; // -3) World Full, -2) Banned, -1) Suspended, 0) Denied, 1) Allowed
|
||||||
uint32 FromID;
|
uint32 FromID;
|
||||||
uint32 ToID;
|
uint32 ToID;
|
||||||
|
char login[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
// generic struct to be used for alot of simple zone->world questions
|
// generic struct to be used for alot of simple zone->world questions
|
||||||
@@ -856,6 +911,8 @@ struct ServerRaidGroupAction_Struct { //add / remove depends on opcode.
|
|||||||
struct ServerRaidMessage_Struct {
|
struct ServerRaidMessage_Struct {
|
||||||
uint32 rid;
|
uint32 rid;
|
||||||
uint32 gid;
|
uint32 gid;
|
||||||
|
uint8 language;
|
||||||
|
uint8 lang_skill;
|
||||||
char from[64];
|
char from[64];
|
||||||
char message[0];
|
char message[0];
|
||||||
};
|
};
|
||||||
|
|||||||
+84
-43
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -123,7 +124,7 @@ void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
|||||||
MailKeyString, CharID);
|
MailKeyString, CharID);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
Log(Logs::General, Logs::Error, "SharedDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, results.ErrorMessage().c_str());
|
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, MailKeyString, results.ErrorMessage().c_str());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,8 +467,6 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQEmu::InventoryProfile *inv, bool
|
|||||||
id);
|
id);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Error, "Database::GetSharedBank(uint32 account_id): %s",
|
|
||||||
results.ErrorMessage().c_str());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,8 +486,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQEmu::InventoryProfile *inv, bool
|
|||||||
const EQEmu::ItemData *item = GetItem(item_id);
|
const EQEmu::ItemData *item = GetItem(item_id);
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
Log(Logs::General, Logs::Error,
|
LogError("Warning: [{}] [{}] has an invalid item_id [{}] in inventory slot [{}]",
|
||||||
"Warning: %s %i has an invalid item_id %i in inventory slot %i",
|
|
||||||
((is_charid == true) ? "charid" : "acctid"), id, item_id, slot_id);
|
((is_charid == true) ? "charid" : "acctid"), id, item_id, slot_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -536,8 +534,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQEmu::InventoryProfile *inv, bool
|
|||||||
if (put_slot_id != INVALID_INDEX)
|
if (put_slot_id != INVALID_INDEX)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Log(Logs::General, Logs::Error,
|
LogError("Warning: Invalid slot_id for item in shared bank inventory: [{}]=[{}], item_id=[{}], slot_id=[{}]",
|
||||||
"Warning: Invalid slot_id for item in shared bank inventory: %s=%i, item_id=%i, slot_id=%i",
|
|
||||||
((is_charid == true) ? "charid" : "acctid"), id, item_id, slot_id);
|
((is_charid == true) ? "charid" : "acctid"), id, item_id, slot_id);
|
||||||
|
|
||||||
if (is_charid)
|
if (is_charid)
|
||||||
@@ -561,7 +558,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
|||||||
char_id);
|
char_id);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Error, "If you got an error related to the 'instnodrop' field, run the "
|
LogError("If you got an error related to the 'instnodrop' field, run the "
|
||||||
"following SQL Queries:\nalter table inventory add instnodrop "
|
"following SQL Queries:\nalter table inventory add instnodrop "
|
||||||
"tinyint(1) unsigned default 0 not null;\n");
|
"tinyint(1) unsigned default 0 not null;\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -625,8 +622,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
|||||||
const EQEmu::ItemData *item = GetItem(item_id);
|
const EQEmu::ItemData *item = GetItem(item_id);
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
Log(Logs::General, Logs::Error,
|
LogError("Warning: charid [{}] has an invalid item_id [{}] in inventory slot [{}]", char_id, item_id,
|
||||||
"Warning: charid %i has an invalid item_id %i in inventory slot %i", char_id, item_id,
|
|
||||||
slot_id);
|
slot_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -699,8 +695,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
|||||||
put_slot_id = inv->PushCursor(*inst);
|
put_slot_id = inv->PushCursor(*inst);
|
||||||
} else if (slot_id >= 3111 && slot_id <= 3179) {
|
} else if (slot_id >= 3111 && slot_id <= 3179) {
|
||||||
// Admins: please report any occurrences of this error
|
// Admins: please report any occurrences of this error
|
||||||
Log(Logs::General, Logs::Error, "Warning: Defunct location for item in inventory: "
|
LogError("Warning: Defunct location for item in inventory: charid={}, item_id={}, slot_id={} .. pushing to cursor...",
|
||||||
"charid=%i, item_id=%i, slot_id=%i .. pushing to cursor...",
|
|
||||||
char_id, item_id, slot_id);
|
char_id, item_id, slot_id);
|
||||||
put_slot_id = inv->PushCursor(*inst);
|
put_slot_id = inv->PushCursor(*inst);
|
||||||
} else {
|
} else {
|
||||||
@@ -711,8 +706,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
|||||||
|
|
||||||
// Save ptr to item in inventory
|
// Save ptr to item in inventory
|
||||||
if (put_slot_id == INVALID_INDEX) {
|
if (put_slot_id == INVALID_INDEX) {
|
||||||
Log(Logs::General, Logs::Error,
|
LogError("Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]",
|
||||||
"Warning: Invalid slot_id for item in inventory: charid=%i, item_id=%i, slot_id=%i",
|
|
||||||
char_id, item_id, slot_id);
|
char_id, item_id, slot_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -720,8 +714,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
|||||||
if (cv_conflict) {
|
if (cv_conflict) {
|
||||||
char char_name[64] = "";
|
char char_name[64] = "";
|
||||||
GetCharName(char_id, char_name);
|
GetCharName(char_id, char_name);
|
||||||
Log(Logs::General, Logs::Error,
|
LogError("ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
|
||||||
"ClientVersion/Expansion conflict during inventory load at zone entry for '%s' (charid: %u, inver: %s, gmi: %s)",
|
|
||||||
char_name,
|
char_name,
|
||||||
char_id,
|
char_id,
|
||||||
EQEmu::versions::MobVersionName(inv->InventoryVersion()),
|
EQEmu::versions::MobVersionName(inv->InventoryVersion()),
|
||||||
@@ -746,7 +739,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQEmu::Inventor
|
|||||||
name, account_id);
|
name, account_id);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Error, "If you got an error related to the 'instnodrop' field, run the "
|
LogError("If you got an error related to the 'instnodrop' field, run the "
|
||||||
"following SQL Queries:\nalter table inventory add instnodrop "
|
"following SQL Queries:\nalter table inventory add instnodrop "
|
||||||
"tinyint(1) unsigned default 0 not null;\n");
|
"tinyint(1) unsigned default 0 not null;\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -834,8 +827,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQEmu::Inventor
|
|||||||
|
|
||||||
// Save ptr to item in inventory
|
// Save ptr to item in inventory
|
||||||
if (put_slot_id == INVALID_INDEX)
|
if (put_slot_id == INVALID_INDEX)
|
||||||
Log(Logs::General, Logs::Error, "Warning: Invalid slot_id for item in inventory: name=%s, "
|
LogError("Warning: Invalid slot_id for item in inventory: name={}, acctid={}, item_id={}, slot_id={}",
|
||||||
"acctid=%i, item_id=%i, slot_id=%i",
|
|
||||||
name, account_id, item_id, slot_id);
|
name, account_id, item_id, slot_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -911,7 +903,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) {
|
|||||||
items_hash = std::unique_ptr<EQEmu::FixedMemoryHashSet<EQEmu::ItemData>>(new EQEmu::FixedMemoryHashSet<EQEmu::ItemData>(reinterpret_cast<uint8*>(items_mmf->Get()), items_mmf->Size()));
|
items_hash = std::unique_ptr<EQEmu::FixedMemoryHashSet<EQEmu::ItemData>>(new EQEmu::FixedMemoryHashSet<EQEmu::ItemData>(reinterpret_cast<uint8*>(items_mmf->Get()), items_mmf->Size()));
|
||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
} catch(std::exception& ex) {
|
} catch(std::exception& ex) {
|
||||||
Log(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what());
|
LogError("Error Loading Items: {}", ex.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -998,7 +990,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
|||||||
item.SkillModMax = (int32)atoul(row[ItemField::skillmodmax]);
|
item.SkillModMax = (int32)atoul(row[ItemField::skillmodmax]);
|
||||||
item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]);
|
item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]);
|
||||||
item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]);
|
item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]);
|
||||||
item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]);
|
item.BaneDmgAmt = (int32)atoul(row[ItemField::banedmgamt]);
|
||||||
item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]);
|
item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]);
|
||||||
item.Magic = (atoi(row[ItemField::magic]) == 0) ? false : true;
|
item.Magic = (atoi(row[ItemField::magic]) == 0) ? false : true;
|
||||||
item.CastTime_ = (int32)atoul(row[ItemField::casttime_]);
|
item.CastTime_ = (int32)atoul(row[ItemField::casttime_]);
|
||||||
@@ -1172,7 +1164,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
|||||||
try {
|
try {
|
||||||
hash.insert(item.ID, item);
|
hash.insert(item.ID, item);
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
Log(Logs::General, Logs::Error, "Database::LoadItems: %s", ex.what());
|
LogError("Database::LoadItems: {}", ex.what());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1229,7 +1221,7 @@ std::string SharedDatabase::GetBook(const char *txtfile, int16 *language)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0) {
|
if (results.RowCount() == 0) {
|
||||||
Log(Logs::General, Logs::Error, "No book to send, (%s)", txtfile);
|
LogError("No book to send, ({})", txtfile);
|
||||||
txtout.assign(" ",1);
|
txtout.assign(" ",1);
|
||||||
return txtout;
|
return txtout;
|
||||||
}
|
}
|
||||||
@@ -1334,7 +1326,7 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) {
|
|||||||
faction_hash = std::unique_ptr<EQEmu::FixedMemoryHashSet<NPCFactionList>>(new EQEmu::FixedMemoryHashSet<NPCFactionList>(reinterpret_cast<uint8*>(faction_mmf->Get()), faction_mmf->Size()));
|
faction_hash = std::unique_ptr<EQEmu::FixedMemoryHashSet<NPCFactionList>>(new EQEmu::FixedMemoryHashSet<NPCFactionList>(reinterpret_cast<uint8*>(faction_mmf->Get()), faction_mmf->Size()));
|
||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
} catch(std::exception& ex) {
|
} catch(std::exception& ex) {
|
||||||
Log(Logs::General, Logs::Error, "Error Loading npc factions: %s", ex.what());
|
LogError("Error Loading npc factions: {}", ex.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1352,8 +1344,8 @@ EQEmu::ItemInstance* SharedDatabase::CreateItem(uint32 item_id, int16 charges, u
|
|||||||
inst = CreateBaseItem(item, charges);
|
inst = CreateBaseItem(item, charges);
|
||||||
|
|
||||||
if (inst == nullptr) {
|
if (inst == nullptr) {
|
||||||
Log(Logs::General, Logs::Error, "Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem()");
|
LogError("Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem()");
|
||||||
Log(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges);
|
LogError("Item Data = ID: {}, Name: {}, Charges: {}", item->ID, item->Name, charges);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1378,8 +1370,8 @@ EQEmu::ItemInstance* SharedDatabase::CreateItem(const EQEmu::ItemData* item, int
|
|||||||
inst = CreateBaseItem(item, charges);
|
inst = CreateBaseItem(item, charges);
|
||||||
|
|
||||||
if (inst == nullptr) {
|
if (inst == nullptr) {
|
||||||
Log(Logs::General, Logs::Error, "Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem()");
|
LogError("Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem()");
|
||||||
Log(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges);
|
LogError("Item Data = ID: {}, Name: {}, Charges: {}", item->ID, item->Name, charges);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1409,8 +1401,8 @@ EQEmu::ItemInstance* SharedDatabase::CreateBaseItem(const EQEmu::ItemData* item,
|
|||||||
inst = new EQEmu::ItemInstance(item, charges);
|
inst = new EQEmu::ItemInstance(item, charges);
|
||||||
|
|
||||||
if (inst == nullptr) {
|
if (inst == nullptr) {
|
||||||
Log(Logs::General, Logs::Error, "Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateBaseItem()");
|
LogError("Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateBaseItem()");
|
||||||
Log(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges);
|
LogError("Item Data = ID: {}, Name: {}, Charges: {}", item->ID, item->Name, charges);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1469,6 +1461,55 @@ bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, s
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected)
|
||||||
|
{
|
||||||
|
if (injected.size()) {
|
||||||
|
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"REPLACE INTO `command_settings`(`command`, `access`) VALUES {}",
|
||||||
|
implode(
|
||||||
|
",",
|
||||||
|
std::pair<char, char>('(', ')'),
|
||||||
|
join_pair(",", std::pair<char, char>('\'', '\''), injected)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"[{0}] New Command(s) Added",
|
||||||
|
injected.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned)
|
||||||
|
{
|
||||||
|
if (orphaned.size()) {
|
||||||
|
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"DELETE FROM `command_settings` WHERE `command` IN ({})",
|
||||||
|
implode(",", std::pair<char, char>('\'', '\''), orphaned)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"{} Orphaned Command{} Deleted",
|
||||||
|
orphaned.size(),
|
||||||
|
(orphaned.size() == 1 ? "" : "s")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
||||||
skill_caps_mmf.reset(nullptr);
|
skill_caps_mmf.reset(nullptr);
|
||||||
|
|
||||||
@@ -1485,7 +1526,7 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
|||||||
skill_caps_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
skill_caps_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
} catch(std::exception &ex) {
|
} catch(std::exception &ex) {
|
||||||
Log(Logs::General, Logs::Error, "Error loading skill caps: %s", ex.what());
|
LogError("Error loading skill caps: {}", ex.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1501,7 +1542,7 @@ void SharedDatabase::LoadSkillCaps(void *data) {
|
|||||||
const std::string query = "SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level";
|
const std::string query = "SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level";
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
Log(Logs::General, Logs::Error, "Error loading skill caps from database: %s", results.ErrorMessage().c_str());
|
LogError("Error loading skill caps from database: {}", results.ErrorMessage().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1645,7 +1686,7 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const
|
|||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
}
|
}
|
||||||
catch(std::exception& ex) {
|
catch(std::exception& ex) {
|
||||||
Log(Logs::General, Logs::Error, "Error Loading Spells: %s", ex.what());
|
LogError("Error Loading Spells: {}", ex.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -1662,7 +1703,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(results.ColumnCount() <= SPELL_LOAD_FIELD_COUNT) {
|
if(results.ColumnCount() <= SPELL_LOAD_FIELD_COUNT) {
|
||||||
Log(Logs::Detail, Logs::Spells, "Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT(%u)", SPELL_LOAD_FIELD_COUNT);
|
LogSpells("Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT([{}])", SPELL_LOAD_FIELD_COUNT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1672,7 +1713,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
tempid = atoi(row[0]);
|
tempid = atoi(row[0]);
|
||||||
if(tempid >= max_spells) {
|
if(tempid >= max_spells) {
|
||||||
Log(Logs::Detail, Logs::Spells, "Non fatal error: spell.id >= max_spells, ignoring.");
|
LogSpells("Non fatal error: spell.id >= max_spells, ignoring");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1849,7 +1890,7 @@ bool SharedDatabase::LoadBaseData(const std::string &prefix) {
|
|||||||
base_data_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
base_data_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
} catch(std::exception& ex) {
|
} catch(std::exception& ex) {
|
||||||
Log(Logs::General, Logs::Error, "Error Loading Base Data: %s", ex.what());
|
LogError("Error Loading Base Data: {}", ex.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1873,22 +1914,22 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) {
|
|||||||
cl = atoi(row[1]);
|
cl = atoi(row[1]);
|
||||||
|
|
||||||
if(lvl <= 0) {
|
if(lvl <= 0) {
|
||||||
Log(Logs::General, Logs::Error, "Non fatal error: base_data.level <= 0, ignoring.");
|
LogError("Non fatal error: base_data.level <= 0, ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lvl >= max_level) {
|
if(lvl >= max_level) {
|
||||||
Log(Logs::General, Logs::Error, "Non fatal error: base_data.level >= max_level, ignoring.");
|
LogError("Non fatal error: base_data.level >= max_level, ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cl <= 0) {
|
if(cl <= 0) {
|
||||||
Log(Logs::General, Logs::Error, "Non fatal error: base_data.cl <= 0, ignoring.");
|
LogError("Non fatal error: base_data.cl <= 0, ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cl > 16) {
|
if(cl > 16) {
|
||||||
Log(Logs::General, Logs::Error, "Non fatal error: base_data.class > 16, ignoring.");
|
LogError("Non fatal error: base_data.class > 16, ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2096,7 +2137,7 @@ bool SharedDatabase::LoadLoot(const std::string &prefix) {
|
|||||||
loot_drop_mmf->Size()));
|
loot_drop_mmf->Size()));
|
||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
} catch(std::exception &ex) {
|
} catch(std::exception &ex) {
|
||||||
Log(Logs::General, Logs::Error, "Error loading loot: %s", ex.what());
|
LogError("Error loading loot: {}", ex.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2112,7 +2153,7 @@ const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) {
|
|||||||
return &loot_table_hash->at(loottable_id);
|
return &loot_table_hash->at(loottable_id);
|
||||||
}
|
}
|
||||||
} catch(std::exception &ex) {
|
} catch(std::exception &ex) {
|
||||||
Log(Logs::General, Logs::Error, "Could not get loot table: %s", ex.what());
|
LogError("Could not get loot table: {}", ex.what());
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -2126,7 +2167,7 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) {
|
|||||||
return &loot_drop_hash->at(lootdrop_id);
|
return &loot_drop_hash->at(lootdrop_id);
|
||||||
}
|
}
|
||||||
} catch(std::exception &ex) {
|
} catch(std::exception &ex) {
|
||||||
Log(Logs::General, Logs::Error, "Could not get loot drop: %s", ex.what());
|
LogError("Could not get loot drop: {}", ex.what());
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ class SharedDatabase : public Database
|
|||||||
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
|
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
|
||||||
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
|
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
|
||||||
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
||||||
|
bool UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected);
|
||||||
|
bool UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned);
|
||||||
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
||||||
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||||
std::string GetMailKey(int CharID, bool key_only = false);
|
std::string GetMailKey(int CharID, bool key_only = false);
|
||||||
|
|||||||
+1
-1
@@ -850,7 +850,7 @@ DmgShieldType GetDamageShieldType(uint16 spell_id, int32 DSType)
|
|||||||
// If we have a DamageShieldType for this spell from the damageshieldtypes table, return that,
|
// If we have a DamageShieldType for this spell from the damageshieldtypes table, return that,
|
||||||
// else, make a guess, based on the resist type. Default return value is DS_THORNS
|
// else, make a guess, based on the resist type. Default return value is DS_THORNS
|
||||||
if (IsValidSpell(spell_id)) {
|
if (IsValidSpell(spell_id)) {
|
||||||
Log(Logs::Detail, Logs::Spells, "DamageShieldType for spell %i (%s) is %X\n", spell_id,
|
LogSpells("DamageShieldType for spell [{}] ([{}]) is [{}]", spell_id,
|
||||||
spells[spell_id].name, spells[spell_id].DamageShieldType);
|
spells[spell_id].name, spells[spell_id].DamageShieldType);
|
||||||
|
|
||||||
if (spells[spell_id].DamageShieldType)
|
if (spells[spell_id].DamageShieldType)
|
||||||
|
|||||||
+2
-1
@@ -22,6 +22,7 @@
|
|||||||
#include "skills.h"
|
#include "skills.h"
|
||||||
|
|
||||||
#define SPELL_UNKNOWN 0xFFFF
|
#define SPELL_UNKNOWN 0xFFFF
|
||||||
|
#define POISON_PROC 0xFFFE
|
||||||
#define SPELLBOOK_UNKNOWN 0xFFFFFFFF //player profile spells are 32 bit
|
#define SPELLBOOK_UNKNOWN 0xFFFFFFFF //player profile spells are 32 bit
|
||||||
|
|
||||||
//some spell IDs which will prolly change, but are needed
|
//some spell IDs which will prolly change, but are needed
|
||||||
@@ -590,7 +591,7 @@ typedef enum {
|
|||||||
#define SE_CorruptionCounter 369 // implemented
|
#define SE_CorruptionCounter 369 // implemented
|
||||||
#define SE_ResistCorruption 370 // implemented
|
#define SE_ResistCorruption 370 // implemented
|
||||||
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
|
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
|
||||||
#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
|
#define SE_ForageSkill 372 // implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
|
||||||
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
|
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
|
||||||
#define SE_ApplyEffect 374 // implemented
|
#define SE_ApplyEffect 374 // implemented
|
||||||
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
|
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
#else
|
#else
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef va_copy
|
#ifndef va_copy
|
||||||
@@ -123,6 +125,25 @@ std::vector<std::string> SplitString(const std::string &str, char delim) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string implode(std::string glue, std::vector<std::string> src)
|
||||||
|
{
|
||||||
|
if (src.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream output;
|
||||||
|
std::vector<std::string>::iterator src_iter;
|
||||||
|
|
||||||
|
for (src_iter = src.begin(); src_iter != src.end(); src_iter++) {
|
||||||
|
output << *src_iter << glue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string final_output = output.str();
|
||||||
|
final_output.resize (output.str().size () - glue.size());
|
||||||
|
|
||||||
|
return final_output;
|
||||||
|
}
|
||||||
|
|
||||||
std::string EscapeString(const std::string &s) {
|
std::string EscapeString(const std::string &s) {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
@@ -241,6 +262,18 @@ void find_replace(std::string &string_subject, const std::string &search_string,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver)
|
||||||
|
{
|
||||||
|
auto split = SplitString(s, ':');
|
||||||
|
if (split.size() == 2) {
|
||||||
|
loginserver = split[0];
|
||||||
|
account = split[1];
|
||||||
|
}
|
||||||
|
else if(split.size() == 1) {
|
||||||
|
account = split[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Const char based
|
//Const char based
|
||||||
|
|
||||||
// normal strncpy doesnt put a null term on copied strings, this one does
|
// normal strncpy doesnt put a null term on copied strings, this one does
|
||||||
|
|||||||
@@ -20,6 +20,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
// this doesn't appear to affect linux-based systems..need feedback for _WIN64
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
@@ -30,6 +36,94 @@ const std::string ucfirst(std::string s);
|
|||||||
std::vector<std::string> split(std::string str_to_split, char delimiter);
|
std::vector<std::string> split(std::string str_to_split, char delimiter);
|
||||||
const std::string StringFormat(const char* format, ...);
|
const std::string StringFormat(const char* format, ...);
|
||||||
const std::string vStringFormat(const char* format, va_list args);
|
const std::string vStringFormat(const char* format, va_list args);
|
||||||
|
std::string implode(std::string glue, std::vector<std::string> src);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::string implode(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<T> &src)
|
||||||
|
{
|
||||||
|
if (src.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
for (const T &src_iter : src) {
|
||||||
|
oss << encapsulation.first << src_iter << encapsulation.second << glue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string output(oss.str());
|
||||||
|
output.resize(output.size() - glue.size());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
std::vector<std::string> join_pair(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<std::pair<T1, T2>> &src)
|
||||||
|
{
|
||||||
|
if (src.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> output;
|
||||||
|
|
||||||
|
for (const std::pair<T1, T2> &src_iter : src) {
|
||||||
|
output.push_back(
|
||||||
|
|
||||||
|
fmt::format(
|
||||||
|
"{}{}{}{}{}{}{}",
|
||||||
|
encapsulation.first,
|
||||||
|
src_iter.first,
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
src_iter.second,
|
||||||
|
encapsulation.second
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4>
|
||||||
|
std::vector<std::string> join_tuple(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<std::tuple<T1, T2, T3, T4>> &src)
|
||||||
|
{
|
||||||
|
if (src.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> output;
|
||||||
|
|
||||||
|
for (const std::tuple<T1, T2, T3, T4> &src_iter : src) {
|
||||||
|
|
||||||
|
output.push_back(
|
||||||
|
|
||||||
|
fmt::format(
|
||||||
|
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<0>(src_iter),
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<1>(src_iter),
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<2>(src_iter),
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<3>(src_iter),
|
||||||
|
encapsulation.second
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||||
std::string EscapeString(const char *src, size_t sz);
|
std::string EscapeString(const char *src, size_t sz);
|
||||||
std::string EscapeString(const std::string &s);
|
std::string EscapeString(const std::string &s);
|
||||||
@@ -38,6 +132,7 @@ void ToLowerString(std::string &s);
|
|||||||
void ToUpperString(std::string &s);
|
void ToUpperString(std::string &s);
|
||||||
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim);
|
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim);
|
||||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
|
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
|
||||||
|
void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver);
|
||||||
|
|
||||||
//const char based
|
//const char based
|
||||||
|
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ void StructStrategy::ErrorEncoder(EQApplicationPacket **in_p, std::shared_ptr<EQ
|
|||||||
EQApplicationPacket *p = *in_p;
|
EQApplicationPacket *p = *in_p;
|
||||||
*in_p = nullptr;
|
*in_p = nullptr;
|
||||||
|
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Error encoding opcode %s: no encoder provided. Dropping.", OpcodeManager::EmuToName(p->GetOpcode()));
|
LogNetcode("[STRUCTS] Error encoding opcode [{}]: no encoder provided. Dropping", OpcodeManager::EmuToName(p->GetOpcode()));
|
||||||
|
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StructStrategy::ErrorDecoder(EQApplicationPacket *p) {
|
void StructStrategy::ErrorDecoder(EQApplicationPacket *p) {
|
||||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Error decoding opcode %s: no decoder provided. Invalidating.", OpcodeManager::EmuToName(p->GetOpcode()));
|
LogNetcode("[STRUCTS] Error decoding opcode [{}]: no decoder provided. Invalidating", OpcodeManager::EmuToName(p->GetOpcode()));
|
||||||
p->SetOpcode(OP_Unknown);
|
p->SetOpcode(OP_Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ ThreadReturnType BaseTCPServer::TCPServerLoop(void* tmp) {
|
|||||||
BaseTCPServer* tcps = (BaseTCPServer*) tmp;
|
BaseTCPServer* tcps = (BaseTCPServer*) tmp;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
Log(Logs::Detail, Logs::None, "Starting TCPServerLoop with thread ID %d", pthread_self());
|
LogDebug( "Starting TCPServerLoop with thread ID [{}]", pthread_self());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tcps->MLoopRunning.lock();
|
tcps->MLoopRunning.lock();
|
||||||
@@ -79,7 +79,7 @@ ThreadReturnType BaseTCPServer::TCPServerLoop(void* tmp) {
|
|||||||
tcps->MLoopRunning.unlock();
|
tcps->MLoopRunning.unlock();
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
Log(Logs::Detail, Logs::None, "Ending TCPServerLoop with thread ID %d", pthread_self());
|
LogDebug( "Ending TCPServerLoop with thread ID [{}]", pthread_self());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
THREAD_RETURN(nullptr);
|
THREAD_RETURN(nullptr);
|
||||||
|
|||||||
@@ -42,9 +42,6 @@ void TimeoutManager::CheckTimeouts() {
|
|||||||
for(; cur != end; ++cur) {
|
for(; cur != end; ++cur) {
|
||||||
Timeoutable *it = *cur;
|
Timeoutable *it = *cur;
|
||||||
if(it->next_check.Check()) {
|
if(it->next_check.Check()) {
|
||||||
#ifdef TIMEOUT_DEBUG
|
|
||||||
Log(Logs::General, Logs::None,, "Checking timeout on 0x%x\n", it);
|
|
||||||
#endif
|
|
||||||
it->CheckTimeout();
|
it->CheckTimeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,15 +54,9 @@ void TimeoutManager::AddMember(Timeoutable *who) {
|
|||||||
|
|
||||||
DeleteMember(who); //just in case... prolly not needed.
|
DeleteMember(who); //just in case... prolly not needed.
|
||||||
members.push_back(who);
|
members.push_back(who);
|
||||||
#ifdef TIMEOUT_DEBUG
|
|
||||||
Log(Logs::General, Logs::None,, "Adding timeoutable 0x%x\n", who);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeoutManager::DeleteMember(Timeoutable *who) {
|
void TimeoutManager::DeleteMember(Timeoutable *who) {
|
||||||
#ifdef TIMEOUT_DEBUG
|
|
||||||
Log(Logs::General, Logs::None,, "Removing timeoutable 0x%x\n", who);
|
|
||||||
#endif
|
|
||||||
std::vector<Timeoutable *>::iterator cur,end;
|
std::vector<Timeoutable *>::iterator cur,end;
|
||||||
cur = members.begin();
|
cur = members.begin();
|
||||||
end = members.end();
|
end = members.end();
|
||||||
|
|||||||
@@ -1,318 +0,0 @@
|
|||||||
/*
|
|
||||||
www.sourceforge.net/projects/tinyxml
|
|
||||||
Original file by Yves Berquin.
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any
|
|
||||||
damages arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any
|
|
||||||
purpose, including commercial applications, and to alter it and
|
|
||||||
redistribute it freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must
|
|
||||||
not claim that you wrote the original software. If you use this
|
|
||||||
software in a product, an acknowledgment in the product documentation
|
|
||||||
would be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and
|
|
||||||
must not be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tinyxml.h"
|
|
||||||
|
|
||||||
#ifndef TIXML_USE_STL
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "tinystr.h"
|
|
||||||
|
|
||||||
// TiXmlString constructor, based on a C string
|
|
||||||
TiXmlString::TiXmlString (const char* instring)
|
|
||||||
{
|
|
||||||
size_t newlen;
|
|
||||||
char * newstring;
|
|
||||||
|
|
||||||
if (!instring)
|
|
||||||
{
|
|
||||||
allocated = 0;
|
|
||||||
cstring = nullptr;
|
|
||||||
current_length = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
newlen = strlen (instring) + 1;
|
|
||||||
newstring = new char [newlen];
|
|
||||||
memcpy (newstring, instring, newlen);
|
|
||||||
// strcpy (newstring, instring);
|
|
||||||
allocated = newlen;
|
|
||||||
cstring = newstring;
|
|
||||||
current_length = newlen - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString copy constructor
|
|
||||||
TiXmlString::TiXmlString (const TiXmlString& copy)
|
|
||||||
{
|
|
||||||
size_t newlen;
|
|
||||||
char * newstring;
|
|
||||||
|
|
||||||
// Prevent copy to self!
|
|
||||||
if ( © == this )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (! copy . allocated)
|
|
||||||
{
|
|
||||||
allocated = 0;
|
|
||||||
cstring = nullptr;
|
|
||||||
current_length = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
newlen = copy . length () + 1;
|
|
||||||
newstring = new char [newlen];
|
|
||||||
// strcpy (newstring, copy . cstring);
|
|
||||||
memcpy (newstring, copy . cstring, newlen);
|
|
||||||
allocated = newlen;
|
|
||||||
cstring = newstring;
|
|
||||||
current_length = newlen - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString = operator. Safe when assign own content
|
|
||||||
void TiXmlString ::operator = (const char * content)
|
|
||||||
{
|
|
||||||
size_t newlen;
|
|
||||||
char * newstring;
|
|
||||||
|
|
||||||
if (! content)
|
|
||||||
{
|
|
||||||
empty_it ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
newlen = strlen (content) + 1;
|
|
||||||
newstring = new char [newlen];
|
|
||||||
// strcpy (newstring, content);
|
|
||||||
memcpy (newstring, content, newlen);
|
|
||||||
empty_it ();
|
|
||||||
allocated = newlen;
|
|
||||||
cstring = newstring;
|
|
||||||
current_length = newlen - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// = operator. Safe when assign own content
|
|
||||||
void TiXmlString ::operator = (const TiXmlString & copy)
|
|
||||||
{
|
|
||||||
size_t newlen;
|
|
||||||
char * newstring;
|
|
||||||
|
|
||||||
if (! copy . length ())
|
|
||||||
{
|
|
||||||
empty_it ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
newlen = copy . length () + 1;
|
|
||||||
newstring = new char [newlen];
|
|
||||||
// strcpy (newstring, copy . c_str ());
|
|
||||||
memcpy (newstring, copy . c_str (), newlen);
|
|
||||||
empty_it ();
|
|
||||||
allocated = newlen;
|
|
||||||
cstring = newstring;
|
|
||||||
current_length = newlen - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// append a const char * to an existing TiXmlString
|
|
||||||
void TiXmlString::append( const char* str, size_t len )
|
|
||||||
{
|
|
||||||
char * new_string;
|
|
||||||
size_t new_alloc, new_size, size_suffix;
|
|
||||||
|
|
||||||
// don't use strlen - it can overrun the len passed in!
|
|
||||||
const char* p = str;
|
|
||||||
size_suffix = 0;
|
|
||||||
|
|
||||||
while ( *p && size_suffix < (unsigned)len )
|
|
||||||
{
|
|
||||||
++p;
|
|
||||||
++size_suffix;
|
|
||||||
}
|
|
||||||
if ( !size_suffix)
|
|
||||||
return;
|
|
||||||
|
|
||||||
new_size = length () + size_suffix + 1;
|
|
||||||
// check if we need to expand
|
|
||||||
if (new_size > allocated)
|
|
||||||
{
|
|
||||||
// compute new size
|
|
||||||
new_alloc = assign_new_size (new_size);
|
|
||||||
|
|
||||||
// allocate new buffer
|
|
||||||
new_string = new char [new_alloc];
|
|
||||||
new_string [0] = 0;
|
|
||||||
|
|
||||||
// copy the previous allocated buffer into this one
|
|
||||||
if (allocated && cstring)
|
|
||||||
// strcpy (new_string, cstring);
|
|
||||||
memcpy (new_string, cstring, length ());
|
|
||||||
|
|
||||||
// append the suffix. It does exist, otherwize we wouldn't be expanding
|
|
||||||
// strncat (new_string, str, len);
|
|
||||||
memcpy (new_string + length (),
|
|
||||||
str,
|
|
||||||
size_suffix);
|
|
||||||
|
|
||||||
// return previsously allocated buffer if any
|
|
||||||
if (allocated && cstring)
|
|
||||||
delete [] cstring;
|
|
||||||
|
|
||||||
// update member variables
|
|
||||||
cstring = new_string;
|
|
||||||
allocated = new_alloc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we know we can safely append the new string
|
|
||||||
// strncat (cstring, str, len);
|
|
||||||
memcpy (cstring + length (),
|
|
||||||
str,
|
|
||||||
size_suffix);
|
|
||||||
}
|
|
||||||
current_length = new_size - 1;
|
|
||||||
cstring [current_length] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// append a const char * to an existing TiXmlString
|
|
||||||
void TiXmlString::append( const char * suffix )
|
|
||||||
{
|
|
||||||
char * new_string;
|
|
||||||
size_t new_alloc, new_size;
|
|
||||||
|
|
||||||
new_size = length () + strlen (suffix) + 1;
|
|
||||||
// check if we need to expand
|
|
||||||
if (new_size > allocated)
|
|
||||||
{
|
|
||||||
// compute new size
|
|
||||||
new_alloc = assign_new_size (new_size);
|
|
||||||
|
|
||||||
// allocate new buffer
|
|
||||||
new_string = new char [new_alloc];
|
|
||||||
new_string [0] = 0;
|
|
||||||
|
|
||||||
// copy the previous allocated buffer into this one
|
|
||||||
if (allocated && cstring)
|
|
||||||
memcpy (new_string, cstring, 1 + length ());
|
|
||||||
// strcpy (new_string, cstring);
|
|
||||||
|
|
||||||
// append the suffix. It does exist, otherwize we wouldn't be expanding
|
|
||||||
// strcat (new_string, suffix);
|
|
||||||
memcpy (new_string + length (),
|
|
||||||
suffix,
|
|
||||||
strlen (suffix) + 1);
|
|
||||||
|
|
||||||
// return previsously allocated buffer if any
|
|
||||||
if (allocated && cstring)
|
|
||||||
delete [] cstring;
|
|
||||||
|
|
||||||
// update member variables
|
|
||||||
cstring = new_string;
|
|
||||||
allocated = new_alloc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we know we can safely append the new string
|
|
||||||
// strcat (cstring, suffix);
|
|
||||||
memcpy (cstring + length (),
|
|
||||||
suffix,
|
|
||||||
strlen (suffix) + 1);
|
|
||||||
}
|
|
||||||
current_length = new_size - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for TiXmlString equuivalence
|
|
||||||
//bool TiXmlString::operator == (const TiXmlString & compare) const
|
|
||||||
//{
|
|
||||||
// return (! strcmp (c_str (), compare . c_str ()));
|
|
||||||
//}
|
|
||||||
|
|
||||||
//unsigned TiXmlString::length () const
|
|
||||||
//{
|
|
||||||
// if (allocated)
|
|
||||||
// // return strlen (cstring);
|
|
||||||
// return current_length;
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned TiXmlString::find (char tofind, unsigned offset) const
|
|
||||||
{
|
|
||||||
char * lookup;
|
|
||||||
|
|
||||||
if (offset >= length ())
|
|
||||||
return (unsigned) notfound;
|
|
||||||
for (lookup = cstring + offset; * lookup; lookup++)
|
|
||||||
if (* lookup == tofind)
|
|
||||||
return (unsigned)(lookup - cstring);
|
|
||||||
return (unsigned) notfound;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TiXmlString::operator == (const TiXmlString & compare) const
|
|
||||||
{
|
|
||||||
if ( allocated && compare.allocated )
|
|
||||||
{
|
|
||||||
assert( cstring );
|
|
||||||
assert( compare.cstring );
|
|
||||||
return ( strcmp( cstring, compare.cstring ) == 0 );
|
|
||||||
}
|
|
||||||
else if ( length() == 0 && compare.length() == 0 )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TiXmlString::operator == (const char* compare) const
|
|
||||||
{
|
|
||||||
if ( allocated && compare && *compare )
|
|
||||||
{
|
|
||||||
assert( cstring );
|
|
||||||
return ( strcmp( cstring, compare ) == 0 );
|
|
||||||
}
|
|
||||||
else if ( length() == 0 && (!compare || !*compare ) ) // this is a little dubious, but try to duplicate behavior in other operator==
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TiXmlString::operator < (const TiXmlString & compare) const
|
|
||||||
{
|
|
||||||
if ( allocated && compare.allocated )
|
|
||||||
{
|
|
||||||
assert( cstring );
|
|
||||||
assert( compare.cstring );
|
|
||||||
return ( strcmp( cstring, compare.cstring ) > 0 );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TiXmlString::operator > (const TiXmlString & compare) const
|
|
||||||
{
|
|
||||||
if ( allocated && compare.allocated )
|
|
||||||
{
|
|
||||||
assert( cstring );
|
|
||||||
assert( compare.cstring );
|
|
||||||
return ( strcmp( cstring, compare.cstring ) < 0 );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // TIXML_USE_STL
|
|
||||||
@@ -1,250 +0,0 @@
|
|||||||
/*
|
|
||||||
www.sourceforge.net/projects/tinyxml
|
|
||||||
Original file by Yves Berquin.
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any
|
|
||||||
damages arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any
|
|
||||||
purpose, including commercial applications, and to alter it and
|
|
||||||
redistribute it freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must
|
|
||||||
not claim that you wrote the original software. If you use this
|
|
||||||
software in a product, an acknowledgment in the product documentation
|
|
||||||
would be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and
|
|
||||||
must not be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tinyxml.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef TIXML_USE_STL
|
|
||||||
|
|
||||||
#ifndef TIXML_STRING_INCLUDED
|
|
||||||
#define TIXML_STRING_INCLUDED
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning( disable : 4530 )
|
|
||||||
#pragma warning( disable : 4786 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
TiXmlString is an emulation of the std::string template.
|
|
||||||
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
|
||||||
Only the member functions relevant to the TinyXML project have been implemented.
|
|
||||||
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
|
||||||
a string and there's no more room, we allocate a buffer twice as big as we need.
|
|
||||||
*/
|
|
||||||
class TiXmlString
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
// TiXmlString constructor, based on a string, mark explicit to force
|
|
||||||
// us to find unnecessary casting.
|
|
||||||
explicit TiXmlString (const char * instring);
|
|
||||||
|
|
||||||
// TiXmlString empty constructor
|
|
||||||
TiXmlString ()
|
|
||||||
{
|
|
||||||
allocated = 0;
|
|
||||||
cstring = nullptr;
|
|
||||||
current_length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString copy constructor
|
|
||||||
explicit TiXmlString (const TiXmlString& copy);
|
|
||||||
|
|
||||||
// TiXmlString destructor
|
|
||||||
~ TiXmlString ()
|
|
||||||
{
|
|
||||||
empty_it ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a TiXmlString into a classical char *
|
|
||||||
const char * c_str () const
|
|
||||||
{
|
|
||||||
if (allocated)
|
|
||||||
return cstring;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the length of a TiXmlString
|
|
||||||
size_t length () const
|
|
||||||
{
|
|
||||||
return ( allocated ) ? current_length : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString = operator
|
|
||||||
void operator = (const char * content);
|
|
||||||
|
|
||||||
// = operator
|
|
||||||
void operator = (const TiXmlString & copy);
|
|
||||||
|
|
||||||
// += operator. Maps to append
|
|
||||||
TiXmlString& operator += (const char * suffix)
|
|
||||||
{
|
|
||||||
append (suffix);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// += operator. Maps to append
|
|
||||||
TiXmlString& operator += (char single)
|
|
||||||
{
|
|
||||||
append (single);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// += operator. Maps to append
|
|
||||||
TiXmlString& operator += (TiXmlString & suffix)
|
|
||||||
{
|
|
||||||
append (suffix);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
bool operator == (const TiXmlString & compare) const;
|
|
||||||
bool operator == (const char* compare) const;
|
|
||||||
bool operator < (const TiXmlString & compare) const;
|
|
||||||
bool operator > (const TiXmlString & compare) const;
|
|
||||||
|
|
||||||
// Checks if a TiXmlString is empty
|
|
||||||
bool empty () const
|
|
||||||
{
|
|
||||||
return length () ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// single char extraction
|
|
||||||
const char& at (unsigned index) const
|
|
||||||
{
|
|
||||||
assert( index < length ());
|
|
||||||
return cstring [index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a char in a string. Return TiXmlString::notfound if not found
|
|
||||||
unsigned find (char lookup) const
|
|
||||||
{
|
|
||||||
return find (lookup, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a char in a string from an offset. Return TiXmlString::notfound if not found
|
|
||||||
unsigned find (char tofind, unsigned offset) const;
|
|
||||||
|
|
||||||
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
|
||||||
function clears the content of the TiXmlString if any exists.
|
|
||||||
*/
|
|
||||||
void reserve (unsigned size)
|
|
||||||
{
|
|
||||||
empty_it ();
|
|
||||||
if (size)
|
|
||||||
{
|
|
||||||
allocated = size;
|
|
||||||
cstring = new char [size];
|
|
||||||
cstring [0] = 0;
|
|
||||||
current_length = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// [] operator
|
|
||||||
char& operator [] (unsigned index) const
|
|
||||||
{
|
|
||||||
assert( index < length ());
|
|
||||||
return cstring [index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error value for find primitive
|
|
||||||
enum { notfound = 0xffffffff,
|
|
||||||
npos = notfound };
|
|
||||||
|
|
||||||
void append (const char *str, size_t len );
|
|
||||||
|
|
||||||
protected :
|
|
||||||
|
|
||||||
// The base string
|
|
||||||
char * cstring;
|
|
||||||
// Number of chars allocated
|
|
||||||
size_t allocated;
|
|
||||||
// Current string size
|
|
||||||
size_t current_length;
|
|
||||||
|
|
||||||
// New size computation. It is simplistic right now : it returns twice the amount
|
|
||||||
// we need
|
|
||||||
size_t assign_new_size (size_t minimum_to_allocate)
|
|
||||||
{
|
|
||||||
return minimum_to_allocate * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal function that clears the content of a TiXmlString
|
|
||||||
void empty_it ()
|
|
||||||
{
|
|
||||||
if (cstring)
|
|
||||||
delete [] cstring;
|
|
||||||
cstring = nullptr;
|
|
||||||
allocated = 0;
|
|
||||||
current_length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append (const char *suffix );
|
|
||||||
|
|
||||||
// append function for another TiXmlString
|
|
||||||
void append (const TiXmlString & suffix)
|
|
||||||
{
|
|
||||||
append (suffix . c_str ());
|
|
||||||
}
|
|
||||||
|
|
||||||
// append for a single char.
|
|
||||||
void append (char single)
|
|
||||||
{
|
|
||||||
if ( cstring && current_length < (allocated-1) )
|
|
||||||
{
|
|
||||||
cstring[ current_length ] = single;
|
|
||||||
++current_length;
|
|
||||||
cstring[ current_length ] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char smallstr [2];
|
|
||||||
smallstr [0] = single;
|
|
||||||
smallstr [1] = 0;
|
|
||||||
append (smallstr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} ;
|
|
||||||
|
|
||||||
/*
|
|
||||||
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
|
||||||
Only the operators that we need for TinyXML have been developped.
|
|
||||||
*/
|
|
||||||
class TiXmlOutStream : public TiXmlString
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
TiXmlOutStream () : TiXmlString () {}
|
|
||||||
|
|
||||||
// TiXmlOutStream << operator. Maps to TiXmlString::append
|
|
||||||
TiXmlOutStream & operator << (const char * in)
|
|
||||||
{
|
|
||||||
append (in);
|
|
||||||
return (* this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlOutStream << operator. Maps to TiXmlString::append
|
|
||||||
TiXmlOutStream & operator << (const TiXmlString & in)
|
|
||||||
{
|
|
||||||
append (in . c_str ());
|
|
||||||
return (* this);
|
|
||||||
}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning( default : 4530 )
|
|
||||||
#pragma warning( default : 4786 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TIXML_STRING_INCLUDED
|
|
||||||
#endif // TIXML_USE_STL
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
www.sourceforge.net/projects/tinyxml
|
|
||||||
Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any
|
|
||||||
damages arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any
|
|
||||||
purpose, including commercial applications, and to alter it and
|
|
||||||
redistribute it freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must
|
|
||||||
not claim that you wrote the original software. If you use this
|
|
||||||
software in a product, an acknowledgment in the product documentation
|
|
||||||
would be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and
|
|
||||||
must not be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tinyxml.h"
|
|
||||||
|
|
||||||
// The goal of the seperate error file is to make the first
|
|
||||||
// step towards localization. tinyxml (currently) only supports
|
|
||||||
// latin-1, but at least the error messages could now be translated.
|
|
||||||
//
|
|
||||||
// It also cleans up the code a bit.
|
|
||||||
//
|
|
||||||
|
|
||||||
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
|
|
||||||
{
|
|
||||||
"No error",
|
|
||||||
"Error",
|
|
||||||
"Failed to open file",
|
|
||||||
"Memory allocation failed.",
|
|
||||||
"Error parsing Element.",
|
|
||||||
"Failed to read Element name",
|
|
||||||
"Error reading Element value.",
|
|
||||||
"Error reading Attributes.",
|
|
||||||
"Error: empty tag.",
|
|
||||||
"Error reading end tag.",
|
|
||||||
"Error parsing Unknown.",
|
|
||||||
"Error parsing Comment.",
|
|
||||||
"Error parsing Declaration.",
|
|
||||||
"Error document empty.",
|
|
||||||
"Error null (0) or unexpected EOF found in input stream.",
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -31,10 +31,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9138
|
#define CURRENT_BINARY_DATABASE_VERSION 9143
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9022
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026
|
||||||
#else
|
#else
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ bool WorldConnection::SendPacket(ServerPacket* pack) {
|
|||||||
|
|
||||||
void WorldConnection::OnConnected() {
|
void WorldConnection::OnConnected() {
|
||||||
const EQEmuConfig *Config=EQEmuConfig::get();
|
const EQEmuConfig *Config=EQEmuConfig::get();
|
||||||
Log(Logs::General, Logs::Netcode, "[WORLD] Connected to World: %s:%d", Config->WorldIP.c_str(), Config->WorldTCPPort);
|
LogNetcode("[WORLD] Connected to World: [{}]:[{}]", Config->WorldIP.c_str(), Config->WorldTCPPort);
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_ZAAuth, 16);
|
auto pack = new ServerPacket(ServerOP_ZAAuth, 16);
|
||||||
MD5::Generate((const uchar*) m_password.c_str(), m_password.length(), pack->pBuffer);
|
MD5::Generate((const uchar*) m_password.c_str(), m_password.length(), pack->pBuffer);
|
||||||
@@ -76,7 +76,7 @@ bool WorldConnection::Connect() {
|
|||||||
if (tcpc.Connect(Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf)) {
|
if (tcpc.Connect(Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Log(Logs::General, Logs::Netcode, "[WORLD] WorldConnection connect: Connecting to the server %s:%d failed: %s", Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf);
|
LogNetcode("[WORLD] WorldConnection connect: Connecting to the server [{}]:[{}] failed: [{}]", Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
||||||
are required to give you total support for your newly bought product;
|
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
#include "global_define.h"
|
|
||||||
#include "xml_parser.h"
|
|
||||||
|
|
||||||
XMLParser::XMLParser() {
|
|
||||||
ParseOkay = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool XMLParser::ParseFile(const char *file, const char *root_ele) {
|
|
||||||
std::map<std::string,ElementHandler>::iterator handler;
|
|
||||||
TiXmlDocument doc( file );
|
|
||||||
if(!doc.LoadFile()) {
|
|
||||||
printf("Unable to load '%s': %s\n", file, doc.ErrorDesc());
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TiXmlElement *root = doc.FirstChildElement( root_ele );
|
|
||||||
if(root == nullptr) {
|
|
||||||
printf("Unable to find root '%s' in %s\n",root_ele, file);
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseOkay=true;
|
|
||||||
|
|
||||||
TiXmlNode *main_element = nullptr;
|
|
||||||
while( (main_element = root->IterateChildren( main_element )) ) {
|
|
||||||
if(main_element->Type() != TiXmlNode::ELEMENT)
|
|
||||||
continue; //skip crap we dont care about
|
|
||||||
TiXmlElement *ele = (TiXmlElement *) main_element;
|
|
||||||
|
|
||||||
handler=Handlers.find(ele->Value());
|
|
||||||
if (handler!=Handlers.end() && handler->second) {
|
|
||||||
ElementHandler h=handler->second;
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* This is kinda a sketchy operation here, since all of these
|
|
||||||
* element handler methods will be functions in child classes.
|
|
||||||
* This essentially causes us to do an un-checkable (and hence
|
|
||||||
* un-handle-properly-able) cast down to the child class. This
|
|
||||||
* WILL BREAK if any children classes do multiple inheritance.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
(this->*h)(ele);
|
|
||||||
} else {
|
|
||||||
//unhandled element.... do nothing for now
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return(ParseOkay);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *XMLParser::ParseTextBlock(TiXmlNode *within, const char *name, bool optional) {
|
|
||||||
TiXmlElement * txt = within->FirstChildElement(name);
|
|
||||||
if(txt == nullptr) {
|
|
||||||
if(!optional) {
|
|
||||||
printf("Unable to find a '%s' element on %s element at line %d\n", name, within->Value(), within->Row());
|
|
||||||
ParseOkay=false;
|
|
||||||
}
|
|
||||||
return(nullptr);
|
|
||||||
}
|
|
||||||
TiXmlNode *contents = txt->FirstChild();
|
|
||||||
if(contents == nullptr || contents->Type() != TiXmlNode::TEXT) {
|
|
||||||
if(!optional)
|
|
||||||
printf("Node '%s' was expected to be a text element in %s element at line %d\n", name, txt->Value(), txt->Row());
|
|
||||||
return(nullptr);
|
|
||||||
}
|
|
||||||
return(contents->Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *XMLParser::GetText(TiXmlNode *within, bool optional) {
|
|
||||||
TiXmlNode *contents = within->FirstChild();
|
|
||||||
if(contents == nullptr || contents->Type() != TiXmlNode::TEXT) {
|
|
||||||
if(!optional) {
|
|
||||||
printf("Node was expected to be a text element in %s element at line %d\n", within->Value(), within->Row());
|
|
||||||
ParseOkay=false;
|
|
||||||
}
|
|
||||||
return(nullptr);
|
|
||||||
}
|
|
||||||
return(contents->Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
||||||
are required to give you total support for your newly bought product;
|
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
#ifndef XMLParser_H
|
|
||||||
#define XMLParser_H
|
|
||||||
|
|
||||||
#include "global_define.h"
|
|
||||||
#include "tinyxml/tinyxml.h"
|
|
||||||
#include "../common/types.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See note in XMLParser::ParseFile() before inheriting this class.
|
|
||||||
*/
|
|
||||||
class XMLParser {
|
|
||||||
public:
|
|
||||||
typedef void (XMLParser::*ElementHandler)(TiXmlElement *ele);
|
|
||||||
|
|
||||||
XMLParser();
|
|
||||||
virtual ~XMLParser() {}
|
|
||||||
|
|
||||||
bool ParseFile(const char *file, const char *root_ele);
|
|
||||||
bool ParseStatus() const { return ParseOkay; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const char *ParseTextBlock(TiXmlNode *within, const char *name, bool optional = false);
|
|
||||||
const char *GetText(TiXmlNode *within, bool optional = false);
|
|
||||||
|
|
||||||
std::map<std::string,ElementHandler> Handlers;
|
|
||||||
|
|
||||||
bool ParseOkay;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
* text=auto
|
||||||
|
*.c text
|
||||||
|
*.h text
|
||||||
|
Makefile text
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
*.diff
|
||||||
|
*.patch
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.a
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
*.gcov
|
||||||
|
|
||||||
|
/example
|
||||||
|
/example64
|
||||||
|
/examplesh
|
||||||
|
/libz.so*
|
||||||
|
/libz-ng.so*
|
||||||
|
/minigzip
|
||||||
|
/minigzip64
|
||||||
|
/minigzipsh
|
||||||
|
/zlib.pc
|
||||||
|
/zlib-ng.pc
|
||||||
|
/CVE-2003-0107
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
*_fuzzer
|
||||||
|
*.obj
|
||||||
|
*.exe
|
||||||
|
*.pdb
|
||||||
|
*.exp
|
||||||
|
*.lib
|
||||||
|
*.dll
|
||||||
|
*.res
|
||||||
|
foo.gz
|
||||||
|
*.manifest
|
||||||
|
*.opensdf
|
||||||
|
*.sln
|
||||||
|
*.sdf
|
||||||
|
*.vcxproj
|
||||||
|
*.vcxproj.filters
|
||||||
|
.vs
|
||||||
|
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
Testing
|
||||||
|
*.cmake
|
||||||
|
*.stackdump
|
||||||
|
zconf.h
|
||||||
|
zconf.h.cmakein
|
||||||
|
zconf.h.included
|
||||||
|
zconf-ng.h
|
||||||
|
zconf-ng.h.cmakein
|
||||||
|
ztest*
|
||||||
|
|
||||||
|
configure.log
|
||||||
|
a.out
|
||||||
|
|
||||||
|
/Makefile
|
||||||
|
/arch/arm/Makefile
|
||||||
|
/arch/generic/Makefile
|
||||||
|
/arch/x86/Makefile
|
||||||
|
.kdev4
|
||||||
|
*.kdev4
|
||||||
|
|
||||||
|
/Debug
|
||||||
|
/example.dir
|
||||||
|
/minigzip.dir
|
||||||
|
/zlib.dir
|
||||||
|
/zlibstatic.dir
|
||||||
|
/win32/Debug
|
||||||
|
|
||||||
|
/.idea
|
||||||
|
/cmake-build-debug
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
language: c
|
||||||
|
cache: ccache
|
||||||
|
dist: xenial
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- BUILDDIR=.
|
||||||
|
- MAKER="make -j2"
|
||||||
|
- TESTER="make test"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: windows
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake . "
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
- os: windows
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake ..\\zlib-ng -DZLIB_COMPAT=ON"
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
- BUILDDIR=..\\build
|
||||||
|
- os: windows
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake ."
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env: GENERATOR="./configure --warn"
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env: GENERATOR="cmake . -DZLIB_COMPAT=OFF -DWITH_GZFILEOP=ON -DWITH_NEW_STRATEGIES=YES -DWITH_OPTIM=ON"
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
- GENERATOR="../zlib-ng/configure --warn --zlib-compat"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env: GENERATOR="./configure --warn --zlib-compat --without-optimizations --without-new-strategies"
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env: GENERATOR="cmake ."
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake ../zlib-ng"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
env: GENERATOR="./configure --warn --zlib-compat"
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake ../zlib-ng"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- GENERATOR="scan-build -v --status-bugs cmake ../zlib-ng"
|
||||||
|
- MAKER="scan-build -v --status-bugs make"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
compiler: gcc
|
||||||
|
env: GENERATOR="./configure --warn --zlib-compat"
|
||||||
|
- os: osx
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
- GENERATOR="../zlib-ng/configure --warn --zlib-compat"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
- os: osx
|
||||||
|
compiler: gcc
|
||||||
|
env: GENERATOR="cmake ."
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
env: GENERATOR="./configure --warn --zlib-compat"
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake ../zlib-ng"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
|
||||||
|
# compiling for linux-ppc64le variants
|
||||||
|
- os: linux-ppc64le
|
||||||
|
compiler: gcc
|
||||||
|
env: GENERATOR="cmake ."
|
||||||
|
- os: linux-ppc64le
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake ../zlib-ng"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
|
||||||
|
- os: linux-ppc64le
|
||||||
|
compiler: clang
|
||||||
|
env: GENERATOR="./configure --warn --zlib-compat"
|
||||||
|
- os: linux-ppc64le
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake ../zlib-ng"
|
||||||
|
- BUILDDIR=../build
|
||||||
|
|
||||||
|
# Cross compiling for arm variants
|
||||||
|
- os: linux
|
||||||
|
compiler: aarch64-linux-gnu-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-aarch64-linux-gnu
|
||||||
|
- libc-dev-arm64-cross
|
||||||
|
# For all aarch64 implementations NEON is mandatory, while crypto/crc are not.
|
||||||
|
env:
|
||||||
|
- GENERATOR="./configure --warn --zlib-compat"
|
||||||
|
- CHOST=aarch64-linux-gnu
|
||||||
|
- os: linux
|
||||||
|
compiler: aarch64-linux-gnu-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-aarch64-linux-gnu
|
||||||
|
- libc-dev-arm64-cross
|
||||||
|
# For all aarch64 implementations NEON is mandatory, while crypto/crc are not.
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake . -DZLIB_COMPAT=ON"
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
- os: linux
|
||||||
|
compiler: aarch64-linux-gnu-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-aarch64-linux-gnu
|
||||||
|
- libc-dev-arm64-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="./configure --warn --zlib-compat"
|
||||||
|
- CHOST=aarch64-linux-gnu
|
||||||
|
- os: linux
|
||||||
|
compiler: aarch64-linux-gnu-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-aarch64-linux-gnu
|
||||||
|
- libc-dev-arm64-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake ."
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
# Hard-float subsets
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabihf-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabihf
|
||||||
|
- libc-dev-armhf-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="./configure --warn"
|
||||||
|
- CHOST=arm-linux-gnueabihf
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabihf-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabihf
|
||||||
|
- libc-dev-armhf-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabihf-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabihf
|
||||||
|
- libc-dev-armhf-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="./configure --warn --zlib-compat --without-neon"
|
||||||
|
- CHOST=arm-linux-gnueabihf
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabihf-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabihf
|
||||||
|
- libc-dev-armhf-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DWITH_NEON=OFF -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabihf-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabihf
|
||||||
|
- libc-dev-armhf-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="./configure --warn --zlib-compat"
|
||||||
|
- CHOST=arm-linux-gnueabihf
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabihf-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabihf
|
||||||
|
- libc-dev-armhf-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
# Soft-float subset
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabi-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabi
|
||||||
|
- libc-dev-armel-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="./configure"
|
||||||
|
- CHOST=arm-linux-gnueabi
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabi-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabi
|
||||||
|
- libc-dev-armel-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi"
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabi-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabi
|
||||||
|
- libc-dev-armel-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="./configure --zlib-compat"
|
||||||
|
- CHOST=arm-linux-gnueabi
|
||||||
|
- os: linux
|
||||||
|
compiler: arm-linux-gnueabi-gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu
|
||||||
|
- gcc-arm-linux-gnueabi
|
||||||
|
- libc-dev-armel-cross
|
||||||
|
env:
|
||||||
|
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi"
|
||||||
|
- MAKER="cmake --build . --config Release"
|
||||||
|
- TESTER="ctest --verbose -C Release"
|
||||||
|
|
||||||
|
script:
|
||||||
|
- mkdir -p $BUILDDIR
|
||||||
|
- cd $BUILDDIR
|
||||||
|
- $GENERATOR
|
||||||
|
- $MAKER
|
||||||
|
- $TESTER
|
||||||
@@ -0,0 +1,865 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5.1)
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||||
|
cmake_policy(VERSION ${CMAKE_VERSION})
|
||||||
|
else()
|
||||||
|
cmake_policy(VERSION 3.5.1...3.13.2)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_MACOSX_RPATH 1)
|
||||||
|
|
||||||
|
# If not specified on the command line, enable C99 as the default
|
||||||
|
# Configuration items that affect the global compiler envirionment standards
|
||||||
|
# should be issued before the "project" command.
|
||||||
|
if(NOT CMAKE_C_STANDARD)
|
||||||
|
set (CMAKE_C_STANDARD 99) # The C standard whose features are requested to build this target
|
||||||
|
endif()
|
||||||
|
if(NOT CMAKE_C_STANDARD_REQUIRED)
|
||||||
|
set (CMAKE_C_STANDARD_REQUIRED ON) # Boolean describing whether the value of C_STANDARD is a requirement
|
||||||
|
endif()
|
||||||
|
if(NOT CMAKE_C_EXTENSIONS)
|
||||||
|
set (CMAKE_C_EXTENSIONS OFF) # Boolean specifying whether compiler specific extensions are requested
|
||||||
|
endif()
|
||||||
|
set(VALID_C_STANDARDS "99" "11")
|
||||||
|
if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS )
|
||||||
|
MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in know standards list\n ${VALID_C_STANDARDS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
|
||||||
|
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h _zlib_h_contents)
|
||||||
|
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9]+.[0-9]+.[0-9]+).*\".*"
|
||||||
|
"\\1" ZLIB_HEADER_VERSION ${_zlib_h_contents})
|
||||||
|
string(REGEX REPLACE ".*#define[ \t]+ZLIBNG_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
|
||||||
|
"\\1" ZLIBNG_HEADER_VERSION ${_zlib_h_contents})
|
||||||
|
message(STATUS "ZLIB_HEADER_VERSION: ${ZLIB_HEADER_VERSION}")
|
||||||
|
message(STATUS "ZLIBNG_HEADER_VERSION: ${ZLIBNG_HEADER_VERSION}")
|
||||||
|
|
||||||
|
project(zlib
|
||||||
|
VERSION ${ZLIB_HEADER_VERSION}
|
||||||
|
LANGUAGES C)
|
||||||
|
|
||||||
|
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||||
|
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||||
|
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
||||||
|
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
|
||||||
|
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||||
|
|
||||||
|
include(CheckTypeSize)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
include(CheckCSourceRuns)
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
include(FeatureSummary)
|
||||||
|
|
||||||
|
# Make sure we use an appropriate BUILD_TYPE by default, "Release" to be exact
|
||||||
|
# this should select the maximum generic optimisation on the current platform (i.e. -O3 for gcc/clang)
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
||||||
|
"Choose the type of build, standard options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||||
|
FORCE)
|
||||||
|
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (default)")
|
||||||
|
else()
|
||||||
|
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (selected)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
||||||
|
check_include_file(stdint.h HAVE_STDINT_H)
|
||||||
|
check_include_file(stddef.h HAVE_STDDEF_H)
|
||||||
|
check_include_file(sys/sdt.h HAVE_SYS_SDT_H)
|
||||||
|
|
||||||
|
if(CMAKE_OSX_ARCHITECTURES)
|
||||||
|
# If multiple architectures are requested (universal build), pick only the first
|
||||||
|
list(GET CMAKE_OSX_ARCHITECTURES 0 ARCH)
|
||||||
|
else()
|
||||||
|
set(ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||||
|
endif()
|
||||||
|
message(STATUS "Architecture: ${ARCH}")
|
||||||
|
if(CMAKE_TOOLCHAIN_FILE)
|
||||||
|
message(STATUS "Using cmake toolchain: ${CMAKE_TOOLCHAIN_FILE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Options parsing
|
||||||
|
#
|
||||||
|
option(WITH_GZFILEOP "Compile with support for gzFile related functions" OFF)
|
||||||
|
option(ZLIB_COMPAT "Compile with zlib compatible API" OFF)
|
||||||
|
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
|
||||||
|
option(WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer" OFF)
|
||||||
|
option(WITH_MSAN "Build with memory sanitizer" OFF)
|
||||||
|
option(WITH_FUZZERS "Build test/fuzz" OFF)
|
||||||
|
option(WITH_OPTIM "Build with optimisation" ON)
|
||||||
|
option(WITH_NEW_STRATEGIES "Use new strategies" ON)
|
||||||
|
option(WITH_NATIVE_INSTRUCTIONS
|
||||||
|
"Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF)
|
||||||
|
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||||
|
option(WITH_ACLE "Build with ACLE CRC" ON)
|
||||||
|
option(WITH_NEON "Build with NEON intrinsics" ON)
|
||||||
|
elseif("${ARCH}" MATCHES "s390x")
|
||||||
|
option(WITH_DFLTCC_DEFLATE "Use DEFLATE CONVERSION CALL instruction for compression on IBM Z" OFF)
|
||||||
|
option(WITH_DFLTCC_INFLATE "Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Provide a zlib-compatible API")
|
||||||
|
add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile-related functions")
|
||||||
|
add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation")
|
||||||
|
add_feature_info(WITH_SANITIZERS WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer")
|
||||||
|
add_feature_info(WITH_MSAN WITH_MSAN "Build with memory sanitizer")
|
||||||
|
add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz")
|
||||||
|
add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies")
|
||||||
|
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||||
|
add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE CRC")
|
||||||
|
add_feature_info(WITH_NEON WITH_NEON "Build with NEON intrinsics")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (ZLIB_COMPAT)
|
||||||
|
add_definitions(-DZLIB_COMPAT)
|
||||||
|
set(WITH_GZFILEOP ON)
|
||||||
|
set(LIBNAME1 libz)
|
||||||
|
set(LIBNAME2 zlib)
|
||||||
|
set(SUFFIX "")
|
||||||
|
else()
|
||||||
|
set(LIBNAME1 libz-ng)
|
||||||
|
set(LIBNAME2 zlib-ng)
|
||||||
|
set(SUFFIX "-ng")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_GZFILEOP)
|
||||||
|
add_definitions(-DWITH_GZFILEOP)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${CMAKE_C_COMPILER} MATCHES "icc" OR ${CMAKE_C_COMPILER} MATCHES "icpc" OR ${CMAKE_C_COMPILER} MATCHES "icl")
|
||||||
|
if(WITH_NATIVE_INSTRUCTIONS)
|
||||||
|
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_HOST_UNIX)
|
||||||
|
if(NOT SSE2FLAG)
|
||||||
|
set(SSE2FLAG "-msse2")
|
||||||
|
endif()
|
||||||
|
if(NOT SSE4FLAG)
|
||||||
|
set(SSE4FLAG "-msse4.2")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(NOT SSE2FLAG)
|
||||||
|
set(SSE2FLAG "/arch:SSE2")
|
||||||
|
endif()
|
||||||
|
if(NOT SSE4FLAG)
|
||||||
|
set(SSE4FLAG "/arch:SSE4.2")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
elseif(MSVC)
|
||||||
|
# TODO. ICC can be used through MSVC. I'm not sure if we'd ever see that combination
|
||||||
|
# (who'd use cmake from an IDE...) but checking for ICC before checking for MSVC should
|
||||||
|
# avoid mistakes.
|
||||||
|
# /Oi ?
|
||||||
|
if(NOT ${ARCH} MATCHES "AMD64")
|
||||||
|
set(SSE2FLAG "/arch:SSE2")
|
||||||
|
endif()
|
||||||
|
if("${ARCH}" MATCHES "arm")
|
||||||
|
add_definitions("-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1")
|
||||||
|
set(NEONFLAG "/arch:VFPv4")
|
||||||
|
endif()
|
||||||
|
if(WITH_NATIVE_INSTRUCTIONS)
|
||||||
|
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# catch all GNU C compilers as well as Clang and AppleClang
|
||||||
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
set(__GNUC__ ON)
|
||||||
|
endif()
|
||||||
|
if(WITH_NATIVE_INSTRUCTIONS)
|
||||||
|
if(__GNUC__)
|
||||||
|
set(NATIVEFLAG "-march=native")
|
||||||
|
else()
|
||||||
|
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(__GNUC__ AND "${ARCH}" MATCHES "arm")
|
||||||
|
execute_process(COMMAND ${CMAKE_C_COMPILER} "-dumpmachine"
|
||||||
|
OUTPUT_VARIABLE GCC_MACHINE)
|
||||||
|
if ("${GCC_MACHINE}" MATCHES "eabihf")
|
||||||
|
set(FLOATABI "-mfloat-abi=hard")
|
||||||
|
else()
|
||||||
|
set(FLOATABI "-mfloat-abi=softfp")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(NOT NATIVEFLAG)
|
||||||
|
if(NOT SSE2FLAG)
|
||||||
|
if(__GNUC__)
|
||||||
|
set(SSE2FLAG "-msse2")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(NOT SSE4FLAG)
|
||||||
|
if(__GNUC__)
|
||||||
|
set(SSE4FLAG "-msse4")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(NOT PCLMULFLAG)
|
||||||
|
if(__GNUC__)
|
||||||
|
set(PCLMULFLAG "-mpclmul")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if("${ARCH}" MATCHES "arm")
|
||||||
|
set(ACLEFLAG "-march=armv8-a+crc")
|
||||||
|
set(NEONFLAG "${FLOATABI} -mfpu=neon")
|
||||||
|
elseif("${ARCH}" MATCHES "aarch64")
|
||||||
|
set(ACLEFLAG "-march=armv8-a+crc")
|
||||||
|
set(NEONFLAG "-march=armv8-a+crc+simd")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(SSE2FLAG ${NATIVEFLAG})
|
||||||
|
set(SSE4FLAG ${NATIVEFLAG})
|
||||||
|
set(PCLMULFLAG ${NATIVEFLAG})
|
||||||
|
if("${ARCH}" MATCHES "arm")
|
||||||
|
set(ACLEFLAG "${NATIVEFLAG}")
|
||||||
|
set(NEONFLAG "${FLOATABI} -mfpu=neon")
|
||||||
|
elseif("${ARCH}" MATCHES "aarch64")
|
||||||
|
set(ACLEFLAG "${NATIVEFLAG}")
|
||||||
|
set(NEONFLAG "${NATIVEFLAG}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check to see if we have large file support
|
||||||
|
#
|
||||||
|
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||||
|
# We add these other definitions here because CheckTypeSize.cmake
|
||||||
|
# in CMake 2.4.x does not automatically do so and we want
|
||||||
|
# compatibility with CMake 2.4.x.
|
||||||
|
if(HAVE_SYS_TYPES_H)
|
||||||
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
|
||||||
|
endif()
|
||||||
|
if(HAVE_STDINT_H)
|
||||||
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
|
||||||
|
endif()
|
||||||
|
if(HAVE_STDDEF_H)
|
||||||
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
|
||||||
|
endif()
|
||||||
|
check_type_size(off64_t OFF64_T)
|
||||||
|
if(HAVE_OFF64_T)
|
||||||
|
add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||||
|
else()
|
||||||
|
check_type_size(_off64_t _OFF64_T)
|
||||||
|
if(HAVE__OFF64_T)
|
||||||
|
add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||||
|
else()
|
||||||
|
check_type_size(__off64_t __OFF64_T)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check for fseeko and other optional functions
|
||||||
|
#
|
||||||
|
check_function_exists(fseeko HAVE_FSEEKO)
|
||||||
|
if(NOT HAVE_FSEEKO)
|
||||||
|
add_definitions(-DNO_FSEEKO)
|
||||||
|
endif()
|
||||||
|
check_function_exists(strerror HAVE_STRERROR)
|
||||||
|
if(NOT HAVE_STRERROR)
|
||||||
|
add_definitions(-DNO_STRERROR)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check for unistd.h and stdarg.h
|
||||||
|
#
|
||||||
|
check_include_file(unistd.h Z_HAVE_UNISTD_H)
|
||||||
|
|
||||||
|
if(WITH_SANITIZERS AND WITH_MSAN)
|
||||||
|
message(FATAL_ERROR "Memory sanitizer is incompatible with address sanitizer")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_MSAN)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory")
|
||||||
|
check_c_source_compiles("int main() { return 0; }" HAS_MSAN FAIL_REGEX "not supported")
|
||||||
|
if(${HAS_MSAN})
|
||||||
|
set(SANITIZERS_FLAGS "-fsanitize=memory")
|
||||||
|
message(STATUS "Adding memory sanitizer flag: ${SANITIZERS_FLAGS}")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_SANITIZERS)
|
||||||
|
set(_sanitize_flags
|
||||||
|
bool
|
||||||
|
address
|
||||||
|
array-bounds
|
||||||
|
float-divide-by-zero
|
||||||
|
function
|
||||||
|
integer-divide-by-zero
|
||||||
|
return
|
||||||
|
shift
|
||||||
|
signed-integer-overflow
|
||||||
|
undefined
|
||||||
|
unsigned-integer-overflow
|
||||||
|
vla-bound
|
||||||
|
vptr
|
||||||
|
)
|
||||||
|
set(SANITIZERS_FLAGS "")
|
||||||
|
foreach(_flag ${_sanitize_flags})
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-fsanitize=${_flag}")
|
||||||
|
check_c_source_compiles("int main() { return 0; }"
|
||||||
|
HAS_SANITIZER_${_flag} FAIL_REGEX "not supported")
|
||||||
|
if(${HAS_SANITIZER_${_flag}})
|
||||||
|
if("${SANITIZERS_FLAGS}" STREQUAL "")
|
||||||
|
set(SANITIZERS_FLAGS "-fsanitize=${_flag}")
|
||||||
|
else()
|
||||||
|
set(SANITIZERS_FLAGS "${SANITIZERS_FLAGS},${_flag}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
endforeach()
|
||||||
|
message(STATUS "Adding sanitizers flags: ${SANITIZERS_FLAGS}")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check if we can hide zlib internal symbols that are linked between separate source files using hidden
|
||||||
|
#
|
||||||
|
check_c_source_compiles(
|
||||||
|
"#define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))
|
||||||
|
int ZLIB_INTERNAL foo;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "not supported")
|
||||||
|
if(HAVE_ATTRIBUTE_VISIBILITY_HIDDEN)
|
||||||
|
add_definitions(-DHAVE_HIDDEN)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check if we can hide zlib internal symbols that are linked between separate source files using internal
|
||||||
|
#
|
||||||
|
check_c_source_compiles(
|
||||||
|
"#define ZLIB_INTERNAL __attribute__((visibility (\"internal\")))
|
||||||
|
int ZLIB_INTERNAL foo;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "not supported")
|
||||||
|
if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL)
|
||||||
|
add_definitions(-DHAVE_INTERNAL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# check for __builtin_ctzl() support in the compiler
|
||||||
|
#
|
||||||
|
check_c_source_compiles(
|
||||||
|
"int main(void)
|
||||||
|
{
|
||||||
|
unsigned int zero = 0;
|
||||||
|
long test = __builtin_ctzl(zero);
|
||||||
|
(void)test;
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_BUILTIN_CTZL
|
||||||
|
)
|
||||||
|
if(HAVE_BUILTIN_CTZL)
|
||||||
|
add_definitions(-DHAVE_BUILTIN_CTZL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# check for ptrdiff_t support
|
||||||
|
#
|
||||||
|
check_c_source_compiles(
|
||||||
|
"#include <stddef.h>
|
||||||
|
int main() { ptrdiff_t *a; return 0; }"
|
||||||
|
HAVE_PTRDIFF_T
|
||||||
|
)
|
||||||
|
if(NOT HAVE_PTRDIFF_T)
|
||||||
|
set(NEED_PTRDIFF_T 1)
|
||||||
|
|
||||||
|
check_type_size("void *" SIZEOF_DATA_PTR)
|
||||||
|
message(STATUS "sizeof(void *) is ${SIZEOF_DATA_PTR} bytes")
|
||||||
|
|
||||||
|
if(${SIZEOF_DATA_PTR} MATCHES "4")
|
||||||
|
set(PTRDIFF_TYPE "uint32_t")
|
||||||
|
elseif(${SIZEOF_DATA_PTR} MATCHES "8")
|
||||||
|
set(PTRDIFF_TYPE "uint64_t")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "sizeof(void *) is neither 32 nor 64 bit")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Macro to check if source compiles when cross-compiling
|
||||||
|
# or runs when compiling natively
|
||||||
|
macro(check_c_source_compile_or_run source flag)
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
check_c_source_compiles("${source}" ${flag})
|
||||||
|
else()
|
||||||
|
check_c_source_runs("${source}" ${flag})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DZLIB_DEBUG")
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
set(CMAKE_DEBUG_POSTFIX "d")
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||||
|
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||||
|
else()
|
||||||
|
#
|
||||||
|
# Not MSVC, so we need to check if we have the MS-style SSE etc. intrinsics
|
||||||
|
#
|
||||||
|
if(WITH_NATIVE_INSTRUCTIONS)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
||||||
|
else()
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}")
|
||||||
|
endif()
|
||||||
|
check_c_source_compile_or_run(
|
||||||
|
"#include <immintrin.h>
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
__m128i zero = _mm_setzero_si128();
|
||||||
|
(void)zero;
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_SSE2_INTRIN
|
||||||
|
)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
|
||||||
|
if(WITH_NATIVE_INSTRUCTIONS)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
||||||
|
else()
|
||||||
|
# Use the generic SSE4 enabler option to check for the SSE4.2 instruction we require:
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}")
|
||||||
|
endif()
|
||||||
|
check_c_source_compile_or_run(
|
||||||
|
"int main(void)
|
||||||
|
{
|
||||||
|
unsigned val = 0, h = 0;
|
||||||
|
__asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) );
|
||||||
|
return (int) h;
|
||||||
|
}"
|
||||||
|
HAVE_SSE42_INTRIN
|
||||||
|
)
|
||||||
|
check_c_source_compile_or_run(
|
||||||
|
"int main(void)
|
||||||
|
{
|
||||||
|
unsigned crc = 0;
|
||||||
|
char c = 'c';
|
||||||
|
crc = __builtin_ia32_crc32qi(crc, c);
|
||||||
|
(void)crc;
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_SSE42CRC_INTRIN
|
||||||
|
)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
|
||||||
|
if(WITH_NATIVE_INSTRUCTIONS)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
||||||
|
else()
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}")
|
||||||
|
endif()
|
||||||
|
if(NOT (APPLE AND ${ARCH} MATCHES "i386"))
|
||||||
|
# The pclmul code currently crashes on Mac in 32bit mode. Avoid for now.
|
||||||
|
check_c_source_compile_or_run(
|
||||||
|
"#include <immintrin.h>
|
||||||
|
#include <wmmintrin.h>
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
__m128i a = _mm_setzero_si128();
|
||||||
|
__m128i b = _mm_setzero_si128();
|
||||||
|
__m128i c = _mm_clmulepi64_si128(a, b, 0x10);
|
||||||
|
(void)c;
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_PCLMULQDQ_INTRIN
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(HAVE_PCLMULQDQ_INTRIN NO)
|
||||||
|
endif()
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check whether -mfpu=neon is available
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-mfpu=neon")
|
||||||
|
check_c_source_compiles(
|
||||||
|
"int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
MFPU_NEON_AVAILABLE FAIL_REGEX "not supported")
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
|
||||||
|
# FORCE_SSE2 option will only be shown if HAVE_SSE2_INTRIN is true
|
||||||
|
if("${ARCH}" MATCHES "i[3-6]86")
|
||||||
|
cmake_dependent_option(FORCE_SSE2 "Always assume CPU is SSE2 capable" OFF "HAVE_SSE2_INTRIN" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Enable deflate_medium at level 4-6
|
||||||
|
#
|
||||||
|
if(NOT WITH_NEW_STRATEGIES)
|
||||||
|
add_definitions(-DNO_MEDIUM_STRATEGY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Macro to add either the given intrinsics option to the global compiler options,
|
||||||
|
# or ${NATIVEFLAG} (-march=native) if that is appropriate and possible.
|
||||||
|
# An alternative version of this macro would take a file argument, and set ${flag}
|
||||||
|
# only for that file as opposed to ${NATIVEFLAG} globally, to limit side-effect of
|
||||||
|
# using ${flag} globally.
|
||||||
|
#
|
||||||
|
macro(add_intrinsics_option flag)
|
||||||
|
if(WITH_NATIVE_INSTRUCTIONS AND NATIVEFLAG)
|
||||||
|
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${NATIVEFLAG} .*")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATIVEFLAG}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${flag} .*")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set(ZLIB_ARCH_SRCS)
|
||||||
|
set(ARCHDIR "arch/generic")
|
||||||
|
if("${ARCH}" MATCHES "x86_64" OR "${ARCH}" MATCHES "AMD64" OR "${ARCH}" MATCHES "i[3-6]86")
|
||||||
|
set(ARCHDIR "arch/x86")
|
||||||
|
add_definitions(-DUNALIGNED_OK)
|
||||||
|
add_feature_info(SSE2 1 "Support the SSE2 instruction set, using \"${SSE2FLAG}\"")
|
||||||
|
elseif("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||||
|
set(ARCHDIR "arch/arm")
|
||||||
|
add_definitions(-DUNALIGNED_OK)
|
||||||
|
elseif("${ARCH}" MATCHES "s390x")
|
||||||
|
set(ARCHDIR "arch/s390")
|
||||||
|
else()
|
||||||
|
message(STATUS "No optimized architecture: using ${ARCHDIR}")
|
||||||
|
endif()
|
||||||
|
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/armfeature.c ${ARCHDIR}/fill_window_arm.c)
|
||||||
|
endif()
|
||||||
|
if(WITH_OPTIM)
|
||||||
|
if("${ARCH}" MATCHES "arm")
|
||||||
|
if(WITH_ACLE)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
|
||||||
|
add_definitions("-DARM_ACLE_CRC_HASH")
|
||||||
|
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
|
||||||
|
endif()
|
||||||
|
if(WITH_NEON)
|
||||||
|
if(MFPU_NEON_AVAILABLE)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
|
||||||
|
endif()
|
||||||
|
add_definitions("-DARM_NEON_ADLER32")
|
||||||
|
if(MSVC)
|
||||||
|
add_definitions("-D__ARM_NEON__=1")
|
||||||
|
endif(MSVC)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
|
||||||
|
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
|
||||||
|
endif()
|
||||||
|
elseif("${ARCH}" MATCHES "aarch64")
|
||||||
|
if(WITH_ACLE)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
|
||||||
|
add_definitions("-DARM_ACLE_CRC_HASH")
|
||||||
|
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
|
||||||
|
endif()
|
||||||
|
# We need to check WITH_NEON first
|
||||||
|
if(WITH_NEON)
|
||||||
|
add_definitions("-DARM_NEON_ADLER32")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
|
||||||
|
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
|
||||||
|
elseif(WITH_ACLE)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
|
||||||
|
endif()
|
||||||
|
elseif("${ARCHDIR}" MATCHES "arch/x86")
|
||||||
|
add_definitions("-DX86_CPUID")
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/x86.c)
|
||||||
|
if(HAVE_SSE42_INTRIN)
|
||||||
|
add_definitions(-DX86_SSE4_2_CRC_HASH)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/insert_string_sse.c)
|
||||||
|
add_feature_info(SSE4_CRC 1 "Support CRC hash generation using the SSE4.2 instruction set, using \"${SSE4FLAG}\"")
|
||||||
|
add_intrinsics_option("${SSE4FLAG}")
|
||||||
|
if(HAVE_SSE42CRC_INTRIN)
|
||||||
|
add_definitions(-DX86_SSE4_2_CRC_INTRIN)
|
||||||
|
endif()
|
||||||
|
if(WITH_NEW_STRATEGIES)
|
||||||
|
add_definitions(-DX86_QUICK_STRATEGY)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/deflate_quick.c)
|
||||||
|
add_feature_info(SSE4DEFLATE 1 "Support SSE4.2-accelerated quick compression")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(HAVE_SSE2_INTRIN)
|
||||||
|
add_definitions(-DX86_SSE2)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/fill_window_sse.c)
|
||||||
|
if(NOT ${ARCH} MATCHES "x86_64")
|
||||||
|
add_intrinsics_option("${SSE2FLAG}")
|
||||||
|
add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable")
|
||||||
|
if(FORCE_SSE2)
|
||||||
|
add_definitions(-DX86_NOCHECK_SSE2)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(HAVE_PCLMULQDQ_INTRIN)
|
||||||
|
add_definitions(-DX86_PCLMULQDQ_CRC)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc_folding.c)
|
||||||
|
add_intrinsics_option("${PCLMULFLAG}")
|
||||||
|
if(HAVE_SSE42_INTRIN)
|
||||||
|
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG}\"")
|
||||||
|
else()
|
||||||
|
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG} ${SSE4FLAG}\"")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
elseif("${ARCH}" MATCHES "s390x")
|
||||||
|
if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_common.c)
|
||||||
|
endif()
|
||||||
|
if(WITH_DFLTCC_DEFLATE)
|
||||||
|
add_definitions(-DS390_DFLTCC_DEFLATE)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_deflate.c)
|
||||||
|
endif()
|
||||||
|
if(WITH_DFLTCC_INFLATE)
|
||||||
|
add_definitions(-DS390_DFLTCC_INFLATE)
|
||||||
|
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_inflate.c)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}")
|
||||||
|
|
||||||
|
#============================================================================
|
||||||
|
# zconf.h
|
||||||
|
#============================================================================
|
||||||
|
|
||||||
|
macro(generate_cmakein input output)
|
||||||
|
file(REMOVE ${output})
|
||||||
|
file(STRINGS ${input} _lines)
|
||||||
|
foreach(_line IN LISTS _lines)
|
||||||
|
file(APPEND ${output} "${_line}\n")
|
||||||
|
|
||||||
|
if (_line STREQUAL "#define ZCONF_H" OR _line STREQUAL "#define ZCONFNG_H")
|
||||||
|
file(APPEND ${output} "#cmakedefine Z_HAVE_UNISTD_H\n")
|
||||||
|
if(NOT HAVE_PTRDIFF_T)
|
||||||
|
file(APPEND ${output} "#cmakedefine NEED_PTRDIFF_T\n")
|
||||||
|
file(APPEND ${output} "#cmakedefine PTRDIFF_TYPE ${PTRDIFF_TYPE}\n")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endmacro(generate_cmakein)
|
||||||
|
|
||||||
|
generate_cmakein( ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.in ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein )
|
||||||
|
|
||||||
|
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||||
|
# If we're doing an out of source build and the user has a zconf.h
|
||||||
|
# in their source tree...
|
||||||
|
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h)
|
||||||
|
message(STATUS "Renaming")
|
||||||
|
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h")
|
||||||
|
message(STATUS "to 'zconf${SUFFIX}.h.included' because this file is included with zlib")
|
||||||
|
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||||
|
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.included)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# If we're doing an out of source build and the user has a zconf.h.cmakein
|
||||||
|
# in their source tree...
|
||||||
|
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein)
|
||||||
|
message(STATUS "Renaming")
|
||||||
|
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein")
|
||||||
|
message(STATUS "to 'zconf${SUFFIX}.h.cmakeincluded' because this file is included with zlib")
|
||||||
|
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||||
|
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakeincluded)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME2}.pc)
|
||||||
|
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
|
||||||
|
${ZLIB_PC} @ONLY)
|
||||||
|
configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h @ONLY)
|
||||||
|
|
||||||
|
|
||||||
|
#============================================================================
|
||||||
|
# zlib
|
||||||
|
#============================================================================
|
||||||
|
|
||||||
|
set(ZLIB_PUBLIC_HDRS
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h
|
||||||
|
zlib${SUFFIX}.h
|
||||||
|
)
|
||||||
|
set(ZLIB_PRIVATE_HDRS
|
||||||
|
crc32.h
|
||||||
|
deflate.h
|
||||||
|
functable.h
|
||||||
|
gzguts.h
|
||||||
|
inffast.h
|
||||||
|
inffixed.h
|
||||||
|
inflate.h
|
||||||
|
inftrees.h
|
||||||
|
trees.h
|
||||||
|
zutil.h
|
||||||
|
)
|
||||||
|
set(ZLIB_SRCS
|
||||||
|
adler32.c
|
||||||
|
compress.c
|
||||||
|
crc32.c
|
||||||
|
deflate.c
|
||||||
|
deflate_fast.c
|
||||||
|
deflate_medium.c
|
||||||
|
deflate_slow.c
|
||||||
|
functable.c
|
||||||
|
inflate.c
|
||||||
|
infback.c
|
||||||
|
inftrees.c
|
||||||
|
inffast.c
|
||||||
|
trees.c
|
||||||
|
uncompr.c
|
||||||
|
zutil.c
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ZLIB_GZFILE_SRCS
|
||||||
|
gzclose.c
|
||||||
|
gzlib.c
|
||||||
|
gzread.c
|
||||||
|
gzwrite.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT MINGW AND NOT MSYS)
|
||||||
|
set(ZLIB_DLL_SRCS
|
||||||
|
win32/zlib${SUFFIX}1.rc # If present will override custom build rule below.
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(MINGW OR MSYS)
|
||||||
|
# This gets us DLL resource information when compiling on MinGW.
|
||||||
|
if(NOT CMAKE_RC_COMPILER)
|
||||||
|
set(CMAKE_RC_COMPILER windres.exe)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||||
|
COMMAND ${CMAKE_RC_COMPILER}
|
||||||
|
-D GCC_WINDRES
|
||||||
|
-I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
-I ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||||
|
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib${SUFFIX}1.rc)
|
||||||
|
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||||
|
target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||||
|
target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
if(WITH_GZFILEOP)
|
||||||
|
target_sources(zlib PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||||
|
target_sources(zlibstatic PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
|
||||||
|
set_target_properties(zlib PROPERTIES SOVERSION 1)
|
||||||
|
|
||||||
|
if (ZLIB_COMPAT)
|
||||||
|
set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION})
|
||||||
|
else()
|
||||||
|
set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION})
|
||||||
|
endif()
|
||||||
|
if(NOT CYGWIN)
|
||||||
|
# This property causes shared libraries on Linux to have the full version
|
||||||
|
# encoded into their final filename. We disable this on Cygwin because
|
||||||
|
# it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
|
||||||
|
# seems to be the default.
|
||||||
|
#
|
||||||
|
# This has no effect with MSVC, on that platform the version info for
|
||||||
|
# the DLL comes from the resource file win32/zlib1.rc
|
||||||
|
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
# On unix-like platforms the library is almost always called libz
|
||||||
|
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z${SUFFIX})
|
||||||
|
if(NOT APPLE)
|
||||||
|
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/${LIBNAME2}.map\"")
|
||||||
|
endif()
|
||||||
|
elseif(MSYS)
|
||||||
|
# Suppress version number from shared library name
|
||||||
|
set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 0)
|
||||||
|
elseif(BUILD_SHARED_LIBS AND WIN32)
|
||||||
|
# Creates zlib1.dll when building shared library version
|
||||||
|
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
|
||||||
|
install(TARGETS zlib zlibstatic
|
||||||
|
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
|
||||||
|
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
|
||||||
|
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
|
||||||
|
endif()
|
||||||
|
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
|
||||||
|
install(FILES zlib${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zlib${SUFFIX}.h)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zconf${SUFFIX}.h)
|
||||||
|
endif()
|
||||||
|
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||||
|
install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3" RENAME zlib${SUFFIX}.3)
|
||||||
|
endif()
|
||||||
|
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||||
|
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#============================================================================
|
||||||
|
# Example binaries
|
||||||
|
#============================================================================
|
||||||
|
|
||||||
|
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
|
||||||
|
if (ZLIB_ENABLE_TESTS)
|
||||||
|
enable_testing()
|
||||||
|
macro(configure_test_executable target)
|
||||||
|
target_link_libraries(${target} zlib)
|
||||||
|
if(NOT WITH_GZFILEOP)
|
||||||
|
target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP)
|
||||||
|
target_sources(${target} PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
add_executable(example test/example.c)
|
||||||
|
configure_test_executable(example)
|
||||||
|
add_test(NAME example COMMAND example${CMAKE_EXECUTABLE_SUFFIX})
|
||||||
|
|
||||||
|
add_executable(minigzip test/minigzip.c)
|
||||||
|
configure_test_executable(minigzip)
|
||||||
|
|
||||||
|
if(HAVE_OFF64_T)
|
||||||
|
add_executable(example64 test/example.c)
|
||||||
|
configure_test_executable(example64)
|
||||||
|
set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||||
|
add_test(NAME example64 COMMAND example64${CMAKE_EXECUTABLE_SUFFIX})
|
||||||
|
|
||||||
|
add_executable(minigzip64 test/minigzip.c)
|
||||||
|
configure_test_executable(minigzip64)
|
||||||
|
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_FUZZERS)
|
||||||
|
set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip)
|
||||||
|
file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
|
||||||
|
foreach(FUZZER ${FUZZERS})
|
||||||
|
add_executable(${FUZZER}_fuzzer test/fuzz/${FUZZER}_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
|
||||||
|
configure_test_executable(${FUZZER}_fuzzer)
|
||||||
|
add_test(${FUZZER}_fuzzer ${FUZZER}_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CVES CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096)
|
||||||
|
foreach(CVE ${CVES})
|
||||||
|
set(CVE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:minigzip> -d)
|
||||||
|
add_test(NAME ${CVE}
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
"-DCOMMAND=${CVE_COMMAND}"
|
||||||
|
-DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/${CVE}/test.gz
|
||||||
|
"-DSUCCESS_EXIT=0;1"
|
||||||
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(NOT WIN32 AND ZLIB_COMPAT)
|
||||||
|
add_executable(CVE-2003-0107 test/CVE-2003-0107.c)
|
||||||
|
target_link_libraries(CVE-2003-0107 zlib)
|
||||||
|
add_test(NAME CVE-2003-0107 COMMAND CVE-2003-0107)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,374 @@
|
|||||||
|
##
|
||||||
|
# THIS IS AN UNMAINTAINED COPY OF THE ORIGINAL FILE DISTRIBUTED WITH ZLIB 1.2.11
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Frequently Asked Questions about zlib
|
||||||
|
|
||||||
|
|
||||||
|
If your question is not there, please check the zlib home page
|
||||||
|
http://zlib.net/ which may have more recent information.
|
||||||
|
The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
|
||||||
|
|
||||||
|
|
||||||
|
1. Is zlib Y2K-compliant?
|
||||||
|
|
||||||
|
Yes. zlib doesn't handle dates.
|
||||||
|
|
||||||
|
2. Where can I get a Windows DLL version?
|
||||||
|
|
||||||
|
The zlib sources can be compiled without change to produce a DLL. See the
|
||||||
|
file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
|
||||||
|
precompiled DLL are found in the zlib web site at http://zlib.net/ .
|
||||||
|
|
||||||
|
3. Where can I get a Visual Basic interface to zlib?
|
||||||
|
|
||||||
|
See
|
||||||
|
* http://marknelson.us/1997/01/01/zlib-engine/
|
||||||
|
* win32/DLL_FAQ.txt in the zlib distribution
|
||||||
|
|
||||||
|
4. compress() returns Z_BUF_ERROR.
|
||||||
|
|
||||||
|
Make sure that before the call of compress(), the length of the compressed
|
||||||
|
buffer is equal to the available size of the compressed buffer and not
|
||||||
|
zero. For Visual Basic, check that this parameter is passed by reference
|
||||||
|
("as any"), not by value ("as long").
|
||||||
|
|
||||||
|
5. deflate() or inflate() returns Z_BUF_ERROR.
|
||||||
|
|
||||||
|
Before making the call, make sure that avail_in and avail_out are not zero.
|
||||||
|
When setting the parameter flush equal to Z_FINISH, also make sure that
|
||||||
|
avail_out is big enough to allow processing all pending input. Note that a
|
||||||
|
Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
|
||||||
|
made with more input or output space. A Z_BUF_ERROR may in fact be
|
||||||
|
unavoidable depending on how the functions are used, since it is not
|
||||||
|
possible to tell whether or not there is more output pending when
|
||||||
|
strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a
|
||||||
|
heavily annotated example.
|
||||||
|
|
||||||
|
6. Where's the zlib documentation (man pages, etc.)?
|
||||||
|
|
||||||
|
It's in zlib.h . Examples of zlib usage are in the files test/example.c
|
||||||
|
and test/minigzip.c, with more in examples/ .
|
||||||
|
|
||||||
|
7. Why don't you use GNU autoconf or libtool or ...?
|
||||||
|
|
||||||
|
Because we would like to keep zlib as a very small and simple package.
|
||||||
|
zlib is rather portable and doesn't need much configuration.
|
||||||
|
|
||||||
|
8. I found a bug in zlib.
|
||||||
|
|
||||||
|
Most of the time, such problems are due to an incorrect usage of zlib.
|
||||||
|
Please try to reproduce the problem with a small program and send the
|
||||||
|
corresponding source to us at zlib@gzip.org . Do not send multi-megabyte
|
||||||
|
data files without prior agreement.
|
||||||
|
|
||||||
|
9. Why do I get "undefined reference to gzputc"?
|
||||||
|
|
||||||
|
If "make test" produces something like
|
||||||
|
|
||||||
|
example.o(.text+0x154): undefined reference to `gzputc'
|
||||||
|
|
||||||
|
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
|
||||||
|
/usr/X11R6/lib. Remove any old versions, then do "make install".
|
||||||
|
|
||||||
|
10. I need a Delphi interface to zlib.
|
||||||
|
|
||||||
|
See the contrib/delphi directory in the zlib distribution.
|
||||||
|
|
||||||
|
11. Can zlib handle .zip archives?
|
||||||
|
|
||||||
|
Not by itself, no. See the directory contrib/minizip in the zlib
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
12. Can zlib handle .Z files?
|
||||||
|
|
||||||
|
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
|
||||||
|
the code of uncompress on your own.
|
||||||
|
|
||||||
|
13. How can I make a Unix shared library?
|
||||||
|
|
||||||
|
By default a shared (and a static) library is built for Unix. So:
|
||||||
|
|
||||||
|
make distclean
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
|
||||||
|
14. How do I install a shared zlib library on Unix?
|
||||||
|
|
||||||
|
After the above, then:
|
||||||
|
|
||||||
|
make install
|
||||||
|
|
||||||
|
However, many flavors of Unix come with a shared zlib already installed.
|
||||||
|
Before going to the trouble of compiling a shared version of zlib and
|
||||||
|
trying to install it, you may want to check if it's already there! If you
|
||||||
|
can #include <zlib.h>, it's there. The -lz option will probably link to
|
||||||
|
it. You can check the version at the top of zlib.h or with the
|
||||||
|
ZLIB_VERSION symbol defined in zlib.h .
|
||||||
|
|
||||||
|
15. I have a question about OttoPDF.
|
||||||
|
|
||||||
|
We are not the authors of OttoPDF. The real author is on the OttoPDF web
|
||||||
|
site: Joel Hainley, jhainley@myndkryme.com.
|
||||||
|
|
||||||
|
16. Can zlib decode Flate data in an Adobe PDF file?
|
||||||
|
|
||||||
|
Yes. See http://www.pdflib.com/ . To modify PDF forms, see
|
||||||
|
http://sourceforge.net/projects/acroformtool/ .
|
||||||
|
|
||||||
|
17. Why am I getting this "register_frame_info not found" error on Solaris?
|
||||||
|
|
||||||
|
After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
|
||||||
|
generates an error such as:
|
||||||
|
|
||||||
|
ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
|
||||||
|
symbol __register_frame_info: referenced symbol not found
|
||||||
|
|
||||||
|
The symbol __register_frame_info is not part of zlib, it is generated by
|
||||||
|
the C compiler (cc or gcc). You must recompile applications using zlib
|
||||||
|
which have this problem. This problem is specific to Solaris. See
|
||||||
|
http://www.sunfreeware.com for Solaris versions of zlib and applications
|
||||||
|
using zlib.
|
||||||
|
|
||||||
|
18. Why does gzip give an error on a file I make with compress/deflate?
|
||||||
|
|
||||||
|
The compress and deflate functions produce data in the zlib format, which
|
||||||
|
is different and incompatible with the gzip format. The gz* functions in
|
||||||
|
zlib on the other hand use the gzip format. Both the zlib and gzip formats
|
||||||
|
use the same compressed data format internally, but have different headers
|
||||||
|
and trailers around the compressed data.
|
||||||
|
|
||||||
|
19. Ok, so why are there two different formats?
|
||||||
|
|
||||||
|
The gzip format was designed to retain the directory information about a
|
||||||
|
single file, such as the name and last modification date. The zlib format
|
||||||
|
on the other hand was designed for in-memory and communication channel
|
||||||
|
applications, and has a much more compact header and trailer and uses a
|
||||||
|
faster integrity check than gzip.
|
||||||
|
|
||||||
|
20. Well that's nice, but how do I make a gzip file in memory?
|
||||||
|
|
||||||
|
You can request that deflate write the gzip format instead of the zlib
|
||||||
|
format using deflateInit2(). You can also request that inflate decode the
|
||||||
|
gzip format using inflateInit2(). Read zlib.h for more details.
|
||||||
|
|
||||||
|
21. Is zlib thread-safe?
|
||||||
|
|
||||||
|
Yes. However any library routines that zlib uses and any application-
|
||||||
|
provided memory allocation routines must also be thread-safe. zlib's gz*
|
||||||
|
functions use stdio library routines, and most of zlib's functions use the
|
||||||
|
library memory allocation routines by default. zlib's *Init* functions
|
||||||
|
allow for the application to provide custom memory allocation routines.
|
||||||
|
|
||||||
|
Of course, you should only operate on any given zlib or gzip stream from a
|
||||||
|
single thread at a time.
|
||||||
|
|
||||||
|
22. Can I use zlib in my commercial application?
|
||||||
|
|
||||||
|
Yes. Please read the license in zlib.h.
|
||||||
|
|
||||||
|
23. Is zlib under the GNU license?
|
||||||
|
|
||||||
|
No. Please read the license in zlib.h.
|
||||||
|
|
||||||
|
24. The license says that altered source versions must be "plainly marked". So
|
||||||
|
what exactly do I need to do to meet that requirement?
|
||||||
|
|
||||||
|
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
|
||||||
|
particular, the final version number needs to be changed to "f", and an
|
||||||
|
identification string should be appended to ZLIB_VERSION. Version numbers
|
||||||
|
x.x.x.f are reserved for modifications to zlib by others than the zlib
|
||||||
|
maintainers. For example, if the version of the base zlib you are altering
|
||||||
|
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
|
||||||
|
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
|
||||||
|
update the version strings in deflate.c and inftrees.c.
|
||||||
|
|
||||||
|
For altered source distributions, you should also note the origin and
|
||||||
|
nature of the changes in zlib.h, as well as in ChangeLog and README, along
|
||||||
|
with the dates of the alterations. The origin should include at least your
|
||||||
|
name (or your company's name), and an email address to contact for help or
|
||||||
|
issues with the library.
|
||||||
|
|
||||||
|
Note that distributing a compiled zlib library along with zlib.h and
|
||||||
|
zconf.h is also a source distribution, and so you should change
|
||||||
|
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
|
||||||
|
in zlib.h as you would for a full source distribution.
|
||||||
|
|
||||||
|
25. Will zlib work on a big-endian or little-endian architecture, and can I
|
||||||
|
exchange compressed data between them?
|
||||||
|
|
||||||
|
Yes and yes.
|
||||||
|
|
||||||
|
26. Will zlib work on a 64-bit machine?
|
||||||
|
|
||||||
|
Yes. It has been tested on 64-bit machines, and has no dependence on any
|
||||||
|
data types being limited to 32-bits in length. If you have any
|
||||||
|
difficulties, please provide a complete problem report to zlib@gzip.org
|
||||||
|
|
||||||
|
27. Will zlib decompress data from the PKWare Data Compression Library?
|
||||||
|
|
||||||
|
No. The PKWare DCL uses a completely different compressed data format than
|
||||||
|
does PKZIP and zlib. However, you can look in zlib's contrib/blast
|
||||||
|
directory for a possible solution to your problem.
|
||||||
|
|
||||||
|
28. Can I access data randomly in a compressed stream?
|
||||||
|
|
||||||
|
No, not without some preparation. If when compressing you periodically use
|
||||||
|
Z_FULL_FLUSH, carefully write all the pending data at those points, and
|
||||||
|
keep an index of those locations, then you can start decompression at those
|
||||||
|
points. You have to be careful to not use Z_FULL_FLUSH too often, since it
|
||||||
|
can significantly degrade compression. Alternatively, you can scan a
|
||||||
|
deflate stream once to generate an index, and then use that index for
|
||||||
|
random access. See examples/zran.c .
|
||||||
|
|
||||||
|
29. Does zlib work on MVS, OS/390, CICS, etc.?
|
||||||
|
|
||||||
|
It has in the past, but we have not heard of any recent evidence. There
|
||||||
|
were working ports of zlib 1.1.4 to MVS, but those links no longer work.
|
||||||
|
If you know of recent, successful applications of zlib on these operating
|
||||||
|
systems, please let us know. Thanks.
|
||||||
|
|
||||||
|
30. Is there some simpler, easier to read version of inflate I can look at to
|
||||||
|
understand the deflate format?
|
||||||
|
|
||||||
|
First off, you should read RFC 1951. Second, yes. Look in zlib's
|
||||||
|
contrib/puff directory.
|
||||||
|
|
||||||
|
31. Does zlib infringe on any patents?
|
||||||
|
|
||||||
|
As far as we know, no. In fact, that was originally the whole point behind
|
||||||
|
zlib. Look here for some more information:
|
||||||
|
|
||||||
|
http://www.gzip.org/#faq11
|
||||||
|
|
||||||
|
32. Can zlib work with greater than 4 GB of data?
|
||||||
|
|
||||||
|
Yes. inflate() and deflate() will process any amount of data correctly.
|
||||||
|
Each call of inflate() or deflate() is limited to input and output chunks
|
||||||
|
of the maximum value that can be stored in the compiler's "unsigned int"
|
||||||
|
type, but there is no limit to the number of chunks. Note however that the
|
||||||
|
strm.total_in and strm_total_out counters may be limited to 4 GB. These
|
||||||
|
counters are provided as a convenience and are not used internally by
|
||||||
|
inflate() or deflate(). The application can easily set up its own counters
|
||||||
|
updated after each call of inflate() or deflate() to count beyond 4 GB.
|
||||||
|
compress() and uncompress() may be limited to 4 GB, since they operate in a
|
||||||
|
single call. gzseek() and gztell() may be limited to 4 GB depending on how
|
||||||
|
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
|
||||||
|
|
||||||
|
The word "may" appears several times above since there is a 4 GB limit only
|
||||||
|
if the compiler's "long" type is 32 bits. If the compiler's "long" type is
|
||||||
|
64 bits, then the limit is 16 exabytes.
|
||||||
|
|
||||||
|
33. Does zlib have any security vulnerabilities?
|
||||||
|
|
||||||
|
The only one that we are aware of is potentially in gzprintf(). If zlib is
|
||||||
|
compiled to use sprintf() or vsprintf(), then there is no protection
|
||||||
|
against a buffer overflow of an 8K string space (or other value as set by
|
||||||
|
gzbuffer()), other than the caller of gzprintf() assuring that the output
|
||||||
|
will not exceed 8K. On the other hand, if zlib is compiled to use
|
||||||
|
snprintf() or vsnprintf(), which should normally be the case, then there is
|
||||||
|
no vulnerability. The ./configure script will display warnings if an
|
||||||
|
insecure variation of sprintf() will be used by gzprintf(). Also the
|
||||||
|
zlibCompileFlags() function will return information on what variant of
|
||||||
|
sprintf() is used by gzprintf().
|
||||||
|
|
||||||
|
If you don't have snprintf() or vsnprintf() and would like one, you can
|
||||||
|
find a portable implementation here:
|
||||||
|
|
||||||
|
http://www.ijs.si/software/snprintf/
|
||||||
|
|
||||||
|
Note that you should be using the most recent version of zlib. Versions
|
||||||
|
1.1.3 and before were subject to a double-free vulnerability, and versions
|
||||||
|
1.2.1 and 1.2.2 were subject to an access exception when decompressing
|
||||||
|
invalid compressed data.
|
||||||
|
|
||||||
|
34. Is there a Java version of zlib?
|
||||||
|
|
||||||
|
Probably what you want is to use zlib in Java. zlib is already included
|
||||||
|
as part of the Java SDK in the java.util.zip package. If you really want
|
||||||
|
a version of zlib written in the Java language, look on the zlib home
|
||||||
|
page for links: http://zlib.net/ .
|
||||||
|
|
||||||
|
35. I get this or that compiler or source-code scanner warning when I crank it
|
||||||
|
up to maximally-pedantic. Can't you guys write proper code?
|
||||||
|
|
||||||
|
Many years ago, we gave up attempting to avoid warnings on every compiler
|
||||||
|
in the universe. It just got to be a waste of time, and some compilers
|
||||||
|
were downright silly as well as contradicted each other. So now, we simply
|
||||||
|
make sure that the code always works.
|
||||||
|
|
||||||
|
36. Valgrind (or some similar memory access checker) says that deflate is
|
||||||
|
performing a conditional jump that depends on an uninitialized value.
|
||||||
|
Isn't that a bug?
|
||||||
|
|
||||||
|
No. That is intentional for performance reasons, and the output of deflate
|
||||||
|
is not affected. This only started showing up recently since zlib 1.2.x
|
||||||
|
uses malloc() by default for allocations, whereas earlier versions used
|
||||||
|
calloc(), which zeros out the allocated memory. Even though the code was
|
||||||
|
correct, versions 1.2.4 and later was changed to not stimulate these
|
||||||
|
checkers.
|
||||||
|
|
||||||
|
37. Will zlib read the (insert any ancient or arcane format here) compressed
|
||||||
|
data format?
|
||||||
|
|
||||||
|
Probably not. Look in the comp.compression FAQ for pointers to various
|
||||||
|
formats and associated software.
|
||||||
|
|
||||||
|
38. How can I encrypt/decrypt zip files with zlib?
|
||||||
|
|
||||||
|
zlib doesn't support encryption. The original PKZIP encryption is very
|
||||||
|
weak and can be broken with freely available programs. To get strong
|
||||||
|
encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
|
||||||
|
compression. For PKZIP compatible "encryption", look at
|
||||||
|
http://www.info-zip.org/
|
||||||
|
|
||||||
|
39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
|
||||||
|
|
||||||
|
"gzip" is the gzip format, and "deflate" is the zlib format. They should
|
||||||
|
probably have called the second one "zlib" instead to avoid confusion with
|
||||||
|
the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
|
||||||
|
correctly points to the zlib specification in RFC 1950 for the "deflate"
|
||||||
|
transfer encoding, there have been reports of servers and browsers that
|
||||||
|
incorrectly produce or expect raw deflate data per the deflate
|
||||||
|
specification in RFC 1951, most notably Microsoft. So even though the
|
||||||
|
"deflate" transfer encoding using the zlib format would be the more
|
||||||
|
efficient approach (and in fact exactly what the zlib format was designed
|
||||||
|
for), using the "gzip" transfer encoding is probably more reliable due to
|
||||||
|
an unfortunate choice of name on the part of the HTTP 1.1 authors.
|
||||||
|
|
||||||
|
Bottom line: use the gzip format for HTTP 1.1 encoding.
|
||||||
|
|
||||||
|
40. Does zlib support the new "Deflate64" format introduced by PKWare?
|
||||||
|
|
||||||
|
No. PKWare has apparently decided to keep that format proprietary, since
|
||||||
|
they have not documented it as they have previous compression formats. In
|
||||||
|
any case, the compression improvements are so modest compared to other more
|
||||||
|
modern approaches, that it's not worth the effort to implement.
|
||||||
|
|
||||||
|
41. I'm having a problem with the zip functions in zlib, can you help?
|
||||||
|
|
||||||
|
There are no zip functions in zlib. You are probably using minizip by
|
||||||
|
Giles Vollant, which is found in the contrib directory of zlib. It is not
|
||||||
|
part of zlib. In fact none of the stuff in contrib is part of zlib. The
|
||||||
|
files in there are not supported by the zlib authors. You need to contact
|
||||||
|
the authors of the respective contribution for help.
|
||||||
|
|
||||||
|
42. The match.asm code in contrib is under the GNU General Public License.
|
||||||
|
Since it's part of zlib, doesn't that mean that all of zlib falls under the
|
||||||
|
GNU GPL?
|
||||||
|
|
||||||
|
No. The files in contrib are not part of zlib. They were contributed by
|
||||||
|
other authors and are provided as a convenience to the user within the zlib
|
||||||
|
distribution. Each item in contrib has its own license.
|
||||||
|
|
||||||
|
43. Is zlib subject to export controls? What is its ECCN?
|
||||||
|
|
||||||
|
zlib is not subject to export controls, and so is classified as EAR99.
|
||||||
|
|
||||||
|
44. Can you please sign these lengthy legal documents and fax them back to us
|
||||||
|
so that we can use your software in our product?
|
||||||
|
|
||||||
|
No. Go away. Shoo.
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user